Ruby 2.7.0p0(2019-12-25revision647ee6f091eafcce70ffb75ddf7e121e192ab217)

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 */
146 off_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
171 VALUE rb_cIO;
172 VALUE rb_eEOFError;
173 VALUE rb_eIOError;
174 VALUE rb_mWaitReadable;
175 VALUE rb_mWaitWritable;
176
177 static VALUE rb_eEAGAINWaitReadable;
178 static VALUE rb_eEAGAINWaitWritable;
179 static VALUE rb_eEWOULDBLOCKWaitReadable;
180 static VALUE rb_eEWOULDBLOCKWaitWritable;
181 static VALUE rb_eEINPROGRESSWaitWritable;
182 static VALUE rb_eEINPROGRESSWaitReadable;
183
184 VALUE rb_stdin, rb_stdout, rb_stderr;
185 static VALUE orig_stdout, orig_stderr;
186
187 VALUE rb_output_fs;
188 VALUE rb_rs;
189 VALUE rb_output_rs;
190 VALUE rb_default_rs;
191
192 static VALUE argf;
193
194 static ID id_write, id_read, id_getc, id_flush, id_readpartial, id_set_encoding;
195 static VALUE sym_mode, sym_perm, sym_flags, sym_extenc, sym_intenc, sym_encoding, sym_open_args;
196 static VALUE sym_textmode, sym_binmode, sym_autoclose;
197 static VALUE sym_SET, sym_CUR, sym_END;
198 static VALUE sym_wait_readable, sym_wait_writable;
199 #ifdef SEEK_DATA
200 static VALUE sym_DATA;
201 #endif
202 #ifdef SEEK_HOLE
203 static VALUE sym_HOLE;
204 #endif
205
206 struct argf {
207 VALUE filename, current_file;
208 long last_lineno; /* $. */
209 long lineno;
210 VALUE argv;
211 VALUE inplace;
212 struct rb_io_enc_t encs;
213 int8_t init_p, next_p, binmode;
214 };
215
216 static rb_atomic_t max_file_descriptor = NOFILE;
217 void
218 rb_update_max_fd(int fd)
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
244 void
245 rb_maygvl_fd_fix_cloexec(int fd)
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
267 void
268 rb_fd_fix_cloexec(int fd)
269 {
270 rb_maygvl_fd_fix_cloexec(fd);
271 rb_update_max_fd(fd);
272 }
273
274 /* this is only called once */
275 static int
276 rb_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: */
287 rb_maygvl_fd_fix_cloexec(fd);
288 return 0;
289 }
290
291 int
292 rb_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) {
306 rb_maygvl_fd_fix_cloexec(ret);
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
317 int
318 rb_cloexec_dup(int oldfd)
319 {
320 /* Don't allocate standard file descriptors: 0, 1, 2 */
321 return rb_cloexec_fcntl_dupfd(oldfd, 3);
322 }
323
324 int
325 rb_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 }
355 rb_maygvl_fd_fix_cloexec(ret);
356 return ret;
357 }
358
359 static int
360 rb_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
377 int
378 rb_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) {
385 ret = pipe2(fildes, O_CLOEXEC | RUBY_PIPE_NONBLOCK_DEFAULT);
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]);
411 if (RUBY_PIPE_NONBLOCK_DEFAULT) {
412 rb_fd_set_nonblock(fildes[0]);
413 rb_fd_set_nonblock(fildes[1]);
414 }
415 return ret;
416 }
417
418 int
419 rb_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)
429 rb_maygvl_fd_fix_cloexec(ret);
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;
457 rb_maygvl_fd_fix_cloexec(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
503 static int io_fflush(rb_io_t *);
504 static 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 */
551 static void
552 io_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 */
638 static inline int
639 set_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
675 static int
676 is_socket(int fd, VALUE path)
677 {
678 struct stat sbuf;
679 if (fstat(fd, &sbuf) < 0)
680 rb_sys_fail_path(path);
681 return S_ISSOCK(sbuf.st_mode);
682 }
683 #endif
684
685 static const char closed_stream[] = "closed stream";
686
687 static void
688 io_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
696 void
697 rb_eof_error(void)
698 {
699 rb_raise(rb_eEOFError, "end of file reached");
700 }
701
702 VALUE
703 rb_io_taint_check(VALUE io)
704 {
705 rb_check_frozen(io);
706 return io;
707 }
708
709 void
710 rb_io_check_initialized(rb_io_t *fptr)
711 {
712 if (!fptr) {
713 rb_raise(rb_eIOError, "uninitialized stream");
714 }
715 }
716
717 void
718 rb_io_check_closed(rb_io_t *fptr)
719 {
720 rb_io_check_initialized(fptr);
721 io_fd_check_closed(fptr->fd);
722 }
723
724 static rb_io_t *
725 rb_io_get_fptr(VALUE io)
726 {
727 rb_io_t *fptr = RFILE(io)->fptr;
728 rb_io_check_initialized(fptr);
729 return fptr;
730 }
731
732 VALUE
733 rb_io_get_io(VALUE io)
734 {
735 return rb_convert_type_with_id(io, T_FILE, "IO", idTo_io);
736 }
737
738 VALUE
739 rb_io_check_io(VALUE io)
740 {
741 return rb_check_convert_type_with_id(io, T_FILE, "IO", idTo_io);
742 }
743
744 VALUE
745 rb_io_get_write_io(VALUE io)
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
755 VALUE
756 rb_io_set_write_io(VALUE io, VALUE w)
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 */
788 static VALUE
789 rb_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))
795 static void
796 io_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
816 static rb_encoding *io_input_encoding(rb_io_t *fptr);
817
818 static void
819 io_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
851 static rb_io_t *
852 flush_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
870 void
871 rb_io_check_char_readable(rb_io_t *fptr)
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
889 void
890 rb_io_check_byte_readable(rb_io_t *fptr)
891 {
892 rb_io_check_char_readable(fptr);
893 if (READ_CHAR_PENDING(fptr)) {
894 rb_raise(rb_eIOError, "byte oriented read for character buffered IO");
895 }
896 }
897
898 void
899 rb_io_check_readable(rb_io_t *fptr)
900 {
901 rb_io_check_byte_readable(fptr);
902 }
903
904 static rb_encoding*
905 io_read_encoding(rb_io_t *fptr)
906 {
907 if (fptr->encs.enc) {
908 return fptr->encs.enc;
909 }
910 return rb_default_external_encoding();
911 }
912
913 static rb_encoding*
914 io_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
922 void
923 rb_io_check_writable(rb_io_t *fptr)
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
934 int
935 rb_io_read_pending(rb_io_t *fptr)
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
943 void
944 rb_io_read_check(rb_io_t *fptr)
945 {
946 if (!READ_DATA_PENDING(fptr)) {
947 rb_thread_wait_fd(fptr->fd);
948 }
949 return;
950 }
951
952 int
953 rb_gc_for_fd(int err)
954 {
955 if (err == EMFILE || err == ENFILE || err == ENOMEM) {
956 rb_gc();
957 return 1;
958 }
959 return 0;
960 }
961
962 static int
963 ruby_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 }
977 rb_update_max_fd(fd);
978 return fd;
979 }
980
981 static VALUE
982 io_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
995 struct io_internal_read_struct {
996 int fd;
997 int nonblock;
998 void *buf;
999 size_t capa;
1000 };
1001
1002 struct io_internal_write_struct {
1003 int fd;
1004 const void *buf;
1005 size_t capa;
1006 };
1007
1008 #ifdef HAVE_WRITEV
1009 struct io_internal_writev_struct {
1010 int fd;
1011 int iovcnt;
1012 const struct iovec *iov;
1013 };
1014 #endif
1015
1016 static int nogvl_wait_for_single_fd(int fd, short events);
1017 static VALUE
1018 internal_read_func(void *ptr)
1019 {
1020 struct io_internal_read_struct *iis = ptr;
1021 ssize_t r;
1022 retry:
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
1041 static VALUE
1042 internal_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
1050 static void*
1051 internal_write_func2(void *ptr)
1052 {
1053 return (void*)internal_write_func(ptr);
1054 }
1055
1056 #ifdef HAVE_WRITEV
1057 static VALUE
1058 internal_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
1067 static ssize_t
1068 rb_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
1080 static ssize_t
1081 rb_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
1091 static ssize_t
1092 rb_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
1104 static ssize_t
1105 rb_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
1116 static VALUE
1117 io_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
1136 static void*
1137 io_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
1148 static VALUE
1149 io_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
1155 static VALUE
1156 io_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
1175 static inline int
1176 io_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
1189 static int
1190 io_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
1203 int
1204 rb_io_wait_readable(int f)
1205 {
1206 io_fd_check_closed(f);
1207 switch (errno) {
1208 case EINTR:
1209 #if defined(ERESTART)
1210 case ERESTART:
1211 #endif
1212 rb_thread_check_ints();
1213 return TRUE;
1214
1215 case EAGAIN:
1216 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
1217 case EWOULDBLOCK:
1218 #endif
1219 rb_thread_wait_fd(f);
1220 return TRUE;
1221
1222 default:
1223 return FALSE;
1224 }
1225 }
1226
1227 int
1228 rb_io_wait_writable(int f)
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 */
1245 rb_thread_check_ints();
1246 return TRUE;
1247
1248 case EAGAIN:
1249 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
1250 case EWOULDBLOCK:
1251 #endif
1252 rb_thread_fd_writable(f);
1253 return TRUE;
1254
1255 default:
1256 return FALSE;
1257 }
1258 }
1259
1260 static void
1261 make_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));
1281 fptr->writeconv_asciicompat = Qnil;
1282 }
1283 else {
1284 enc = fptr->encs.enc2 ? fptr->encs.enc2 : fptr->encs.enc;
1285 senc = rb_econv_asciicompat_encoding(rb_enc_name(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;
1291 fptr->writeconv_asciicompat = Qnil;
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 = "";
1303 fptr->writeconv_asciicompat = rb_str_new2(rb_enc_name(enc));
1304 }
1305 ecflags = fptr->encs.ecflags & (ECONV_ERROR_HANDLER_MASK|ECONV_STATEFUL_DECORATOR_MASK);
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 */
1316 struct binwrite_arg {
1317 rb_io_t *fptr;
1318 VALUE str;
1319 const char *ptr;
1320 long length;
1321 };
1322
1323 struct write_arg {
1324 VALUE io;
1325 VALUE str;
1326 int nosync;
1327 };
1328
1329 #ifdef HAVE_WRITEV
1330 static VALUE
1331 io_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
1368 static VALUE
1369 io_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
1393 if (fptr->stdio_file != stderr && !rb_thread_fd_writable(fptr->fd))
1394 rb_io_check_closed(fptr);
1395
1396 return rb_write_internal(p->fptr->fd, p->ptr, p->length);
1397 }
1398 #endif
1399
1400 static long
1401 io_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. */
1406 rb_thread_check_ints();
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);
1414 fptr->write_lock = rb_mutex_new();
1415 rb_mutex_allow_trap(fptr->write_lock, 1);
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)) {
1442 rb_io_check_closed(fptr);
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
1466 static VALUE
1467 do_writeconv(VALUE str, rb_io_t *fptr, int *converted)
1468 {
1469 if (NEED_WRITECONV(fptr)) {
1470 VALUE common_encoding = Qnil;
1471 SET_BINARY_MODE(fptr);
1472
1473 make_writeconv(fptr);
1474
1475 if (fptr->writeconv) {
1476 #define fmode (fptr->mode)
1477 if (!NIL_P(fptr->writeconv_asciicompat))
1478 common_encoding = fptr->writeconv_asciicompat;
1479 else if (MODE_BTMODE(DEFAULT_TEXTMODE,0,1) && !rb_enc_asciicompat(rb_enc_get(str))) {
1480 rb_raise(rb_eArgError, "ASCII incompatible string written for text mode IO without encoding conversion: %s",
1481 rb_enc_name(rb_enc_get(str)));
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,
1494 fptr->writeconv_pre_ecflags, fptr->writeconv_pre_ecopts);
1495 *converted = 1;
1496 }
1497
1498 if (fptr->writeconv) {
1499 str = rb_econv_str_convert(fptr->writeconv, str, ECONV_PARTIAL_INPUT);
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) &&
1507 !(fptr->encs.ecflags & ECONV_NEWLINE_DECORATOR_MASK)) {
1508 setmode(fptr->fd, O_BINARY);
1509 }
1510 else {
1511 setmode(fptr->fd, O_TEXT);
1512 }
1513 if (!rb_enc_asciicompat(rb_enc_get(str))) {
1514 rb_raise(rb_eArgError, "ASCII incompatible string written for text mode IO without encoding conversion: %s",
1515 rb_enc_name(rb_enc_get(str)));
1516 }
1517 }
1518 #undef fmode
1519 #endif
1520 return str;
1521 }
1522
1523 static long
1524 io_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) {
1532 long len = rb_w32_write_console(str, fptr->fd);
1533 if (len > 0) return len;
1534 }
1535 #endif
1536 str = do_writeconv(str, fptr, &converted);
1537 if (converted)
1538 OBJ_FREEZE(str);
1539
1540 tmp = rb_str_tmp_frozen_acquire(str);
1541 RSTRING_GETMEM(tmp, ptr, len);
1542 n = io_binwrite(tmp, ptr, len, fptr, nosync);
1543 rb_str_tmp_frozen_release(str, tmp);
1544
1545 return n;
1546 }
1547
1548 ssize_t
1549 rb_io_bufwrite(VALUE io, const void *buf, size_t size)
1550 {
1551 rb_io_t *fptr;
1552
1553 GetOpenFile(io, fptr);
1554 rb_io_check_writable(fptr);
1555 return (ssize_t)io_binwrite(0, buf, (long)size, fptr, 0);
1556 }
1557
1558 static VALUE
1559 io_write(VALUE io, VALUE str, int nosync)
1560 {
1561 rb_io_t *fptr;
1562 long n;
1563 VALUE tmp;
1564
1565 io = GetWriteIO(io);
1566 str = rb_obj_as_string(str);
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);
1576 rb_io_check_writable(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
1585 struct binwritev_arg {
1586 rb_io_t *fptr;
1587 const struct iovec *iov;
1588 int iovcnt;
1589 };
1590
1591 static VALUE
1592 call_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
1598 static long
1599 io_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. */
1605 rb_thread_check_ints();
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();
1616 rb_mutex_allow_trap(fptr->write_lock, 1);
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
1687 static long
1688 io_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++) {
1699 str = rb_obj_as_string(argv[i]);
1700 converted = 0;
1701 str = do_writeconv(str, fptr, &converted);
1702 if (converted)
1703 OBJ_FREEZE(str);
1704
1705 tmp = rb_str_tmp_frozen_acquire(str);
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
1724 static int
1725 iovcnt_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
1735 static VALUE
1736 io_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);
1752 rb_io_check_writable(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
1791 static VALUE
1792 io_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
1803 VALUE
1804 rb_io_write(VALUE io, VALUE str)
1805 {
1806 return rb_funcallv(io, id_write, 1, &str);
1807 }
1808
1809 static VALUE
1810 rb_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
1842 VALUE
1843 rb_io_addstr(VALUE io, VALUE str)
1844 {
1845 rb_io_write(io, str);
1846 return io;
1847 }
1848
1849 #ifdef HAVE_FSYNC
1850 static VALUE
1851 nogvl_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
1863 VALUE
1864 rb_io_flush_raw(VALUE io, int sync)
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
1902 VALUE
1903 rb_io_flush(VALUE io)
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
1921 static VALUE
1922 rb_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
1934 static VALUE
1935 rb_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
1948 static int
1949 interpret_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
1989 static VALUE
1990 rb_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
2015 static VALUE
2016 rb_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
2029 static 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
2047 static VALUE
2048 rb_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
2065 static int
2066 fptr_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
2075 static int
2076 io_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 }
2103 rb_syserr_fail_path(e, path);
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
2148 VALUE
2149 rb_io_eof(VALUE io)
2150 {
2151 rb_io_t *fptr;
2152
2153 GetOpenFile(io, fptr);
2154 rb_io_check_char_readable(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
2183 static VALUE
2184 rb_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
2208 static VALUE
2209 rb_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
2237 static VALUE
2238 rb_io_fsync(VALUE io)
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
2254 static VALUE
2255 rb_io_set_sync(VALUE io, VALUE sync)
2256 {
2257 rb_notimplement();
2258 UNREACHABLE;
2259 }
2260 #endif
2261
2262 #ifdef HAVE_FDATASYNC
2263 static VALUE
2264 nogvl_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
2286 static VALUE
2287 rb_io_fdatasync(VALUE io)
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
2319 static VALUE
2320 rb_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
2351 static VALUE
2352 rb_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
2370 static VALUE
2371 rb_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("#<");
2380 rb_str_append(result, rb_class_name(CLASS_OF(obj)));
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
2406 static VALUE
2407 rb_io_to_io(VALUE io)
2408 {
2409 return io;
2410 }
2411
2412 /* reading functions */
2413 static long
2414 read_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
2427 static long
2428 io_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
2464 static int io_setstrbuf(VALUE *str, long len);
2465
2466 struct bufread_arg {
2467 char *str_ptr;
2468 long len;
2469 rb_io_t *fptr;
2470 };
2471
2472 static VALUE
2473 bufread_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
2480 static long
2481 io_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
2496 static long
2497 remain_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
2525 static VALUE
2526 io_enc_str(VALUE str, rb_io_t *fptr)
2527 {
2528 rb_enc_associate(str, io_read_encoding(fptr));
2529 return str;
2530 }
2531
2532 static void
2533 make_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;
2553 if (size < IO_CBUF_CAPA_MIN) size = IO_CBUF_CAPA_MIN;
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
2561 static VALUE
2562 fill_cbuf(rb_io_t *fptr, int ec_flags)
2563 {
2564 const unsigned char *ss, *sp, *se;
2565 unsigned char *ds, *dp, *de;
2566 rb_econv_result_t res;
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
2601 exc = rb_econv_make_exception(fptr->readconv);
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);
2623 rb_econv_check_error(fptr->readconv);
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
2635 static VALUE
2636 more_char(rb_io_t *fptr)
2637 {
2638 VALUE v;
2639 v = fill_cbuf(fptr, ECONV_AFTER_OUTPUT);
2640 if (v != MORE_CHAR_SUSPENDED && v != MORE_CHAR_FINISHED)
2641 rb_exc_raise(v);
2642 return v;
2643 }
2644
2645 static VALUE
2646 io_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
2671 static int
2672 io_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 }
2690 rb_str_modify_expand(*str, len);
2691 return FALSE;
2692 }
2693
2694 #define MAX_REALLOC_GAP 4096
2695 static void
2696 io_shrink_read_string(VALUE str, long n)
2697 {
2698 if (rb_str_capacity(str) - n > MAX_REALLOC_GAP) {
2699 rb_str_resize(str, n);
2700 }
2701 }
2702
2703 static void
2704 io_set_read_length(VALUE str, long n, int shrinkable)
2705 {
2706 if (RSTRING_LEN(str) != n) {
2707 rb_str_modify(str);
2708 rb_str_set_len(str, n);
2709 if (shrinkable) io_shrink_read_string(str, n);
2710 }
2711 }
2712
2713 static VALUE
2714 read_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);
2735 if (v != MORE_CHAR_SUSPENDED && v != MORE_CHAR_FINISHED) {
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
2751 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
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;
2773 rb_str_modify_expand(str, BUFSIZ);
2774 }
2775 if (shrinkable) io_shrink_read_string(str, RSTRING_LEN(str));
2776 str = io_enc_str(str, fptr);
2777 ENC_CODERANGE_SET(str, cr);
2778 return str;
2779 }
2780
2781 void
2782 rb_io_set_nonblock(rb_io_t *fptr)
2783 {
2784 if (rb_fd_set_nonblock(fptr->fd) != 0) {
2785 rb_sys_fail_path(fptr->pathv);
2786 }
2787 }
2788
2789 static VALUE
2790 read_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
2797 static long
2798 read_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
2805 static VALUE
2806 io_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);
2823 rb_io_check_byte_readable(fptr);
2824
2825 if (len == 0)
2826 return str;
2827
2828 if (!nonblock)
2829 READ_CHECK(fptr);
2830 n = read_buffered_data(RSTRING_PTR(str), len, fptr);
2831 if (n <= 0) {
2832 again:
2833 if (nonblock) {
2834 rb_io_set_nonblock(fptr);
2835 }
2836 io_setstrbuf(&str, len);
2837 iis.fd = fptr->fd;
2838 iis.nonblock = nonblock;
2839 iis.buf = RSTRING_PTR(str);
2840 iis.capa = len;
2841 n = read_internal_locktmp(str, &iis);
2842 if (n < 0) {
2843 int e = errno;
2844 if (!nonblock && fptr_wait_readable(fptr))
2845 goto again;
2846 if (nonblock && (e == EWOULDBLOCK || e == EAGAIN)) {
2847 if (no_exception)
2848 return sym_wait_readable;
2849 else
2850 rb_readwrite_syserr_fail(RB_IO_WAIT_READABLE,
2851 e, "read would block");
2852 }
2853 rb_syserr_fail_path(e, fptr->pathv);
2854 }
2855 }
2856 io_set_read_length(str, n, shrinkable);
2857
2858 if (n == 0)
2859 return Qnil;
2860 else
2861 return str;
2862 }
2863
2864 /*
2865 * call-seq:
2866 * ios.readpartial(maxlen) -> string
2867 * ios.readpartial(maxlen, outbuf) -> outbuf
2868 *
2869 * Reads at most <i>maxlen</i> bytes from the I/O stream.
2870 * It blocks only if <em>ios</em> has no data immediately available.
2871 * It doesn't block if some data available.
2872 *
2873 * If the optional _outbuf_ argument is present,
2874 * it must reference a String, which will receive the data.
2875 * The _outbuf_ will contain only the received data after the method call
2876 * even if it is not empty at the beginning.
2877 *
2878 * It raises EOFError on end of file.
2879 *
2880 * readpartial is designed for streams such as pipe, socket, tty, etc.
2881 * It blocks only when no data immediately available.
2882 * This means that it blocks only when following all conditions hold.
2883 * * the byte buffer in the IO object is empty.
2884 * * the content of the stream is empty.
2885 * * the stream is not reached to EOF.
2886 *
2887 * When readpartial blocks, it waits data or EOF on the stream.
2888 * If some data is reached, readpartial returns with the data.
2889 * If EOF is reached, readpartial raises EOFError.
2890 *
2891 * When readpartial doesn't blocks, it returns or raises immediately.
2892 * If the byte buffer is not empty, it returns the data in the buffer.
2893 * Otherwise if the stream has some content,
2894 * it returns the data in the stream.
2895 * Otherwise if the stream is reached to EOF, it raises EOFError.
2896 *
2897 * r, w = IO.pipe # buffer pipe content
2898 * w << "abc" # "" "abc".
2899 * r.readpartial(4096) #=> "abc" "" ""
2900 * r.readpartial(4096) # blocks because buffer and pipe is empty.
2901 *
2902 * r, w = IO.pipe # buffer pipe content
2903 * w << "abc" # "" "abc"
2904 * w.close # "" "abc" EOF
2905 * r.readpartial(4096) #=> "abc" "" EOF
2906 * r.readpartial(4096) # raises EOFError
2907 *
2908 * r, w = IO.pipe # buffer pipe content
2909 * w << "abc\ndef\n" # "" "abc\ndef\n"
2910 * r.gets #=> "abc\n" "def\n" ""
2911 * w << "ghi\n" # "def\n" "ghi\n"
2912 * r.readpartial(4096) #=> "def\n" "" "ghi\n"
2913 * r.readpartial(4096) #=> "ghi\n" "" ""
2914 *
2915 * Note that readpartial behaves similar to sysread.
2916 * The differences are:
2917 * * If the byte buffer is not empty, read from the byte buffer
2918 * instead of "sysread for buffered IO (IOError)".
2919 * * It doesn't cause Errno::EWOULDBLOCK and Errno::EINTR. When
2920 * readpartial meets EWOULDBLOCK and EINTR by read system call,
2921 * readpartial retry the system call.
2922 *
2923 * The latter means that readpartial is nonblocking-flag insensitive.
2924 * It blocks on the situation IO#sysread causes Errno::EWOULDBLOCK as
2925 * if the fd is blocking mode.
2926 *
2927 */
2928
2929 static VALUE
2930 io_readpartial(int argc, VALUE *argv, VALUE io)
2931 {
2932 VALUE ret;
2933
2934 ret = io_getpartial(argc, argv, io, Qnil, 0);
2935 if (NIL_P(ret))
2936 rb_eof_error();
2937 return ret;
2938 }
2939
2940 static VALUE
2941 io_nonblock_eof(int no_exception)
2942 {
2943 if (!no_exception) {
2944 rb_eof_error();
2945 }
2946 return Qnil;
2947 }
2948
2949 /* :nodoc: */
2950 static VALUE
2951 io_read_nonblock(rb_execution_context_t *ec, VALUE io, VALUE length, VALUE str, VALUE ex)
2952 {
2953 rb_io_t *fptr;
2954 long n, len;
2955 struct io_internal_read_struct iis;
2956 int shrinkable;
2957
2958 if ((len = NUM2LONG(length)) < 0) {
2959 rb_raise(rb_eArgError, "negative length %ld given", len);
2960 }
2961
2962 shrinkable = io_setstrbuf(&str, len);
2963 rb_bool_expected(ex, "exception");
2964
2965 GetOpenFile(io, fptr);
2966 rb_io_check_byte_readable(fptr);
2967
2968 if (len == 0)
2969 return str;
2970
2971 n = read_buffered_data(RSTRING_PTR(str), len, fptr);
2972 if (n <= 0) {
2973 rb_io_set_nonblock(fptr);
2974 shrinkable |= io_setstrbuf(&str, len);
2975 iis.fd = fptr->fd;
2976 iis.nonblock = 1;
2977 iis.buf = RSTRING_PTR(str);
2978 iis.capa = len;
2979 n = read_internal_locktmp(str, &iis);
2980 if (n < 0) {
2981 int e = errno;
2982 if ((e == EWOULDBLOCK || e == EAGAIN)) {
2983 if (!ex) return sym_wait_readable;
2984 rb_readwrite_syserr_fail(RB_IO_WAIT_READABLE,
2985 e, "read would block");
2986 }
2987 rb_syserr_fail_path(e, fptr->pathv);
2988 }
2989 }
2990 io_set_read_length(str, n, shrinkable);
2991
2992 if (n == 0) {
2993 if (!ex) return Qnil;
2994 rb_eof_error();
2995 }
2996
2997 return str;
2998 }
2999
3000 /* :nodoc: */
3001 static VALUE
3002 io_write_nonblock(rb_execution_context_t *ec, VALUE io, VALUE str, VALUE ex)
3003 {
3004 rb_io_t *fptr;
3005 long n;
3006
3007 if (!RB_TYPE_P(str, T_STRING))
3008 str = rb_obj_as_string(str);
3009 rb_bool_expected(ex, "exception");
3010
3011 io = GetWriteIO(io);
3012 GetOpenFile(io, fptr);
3013 rb_io_check_writable(fptr);
3014
3015 if (io_fflush(fptr) < 0)
3016 rb_sys_fail(0);
3017
3018 rb_io_set_nonblock(fptr);
3019 n = write(fptr->fd, RSTRING_PTR(str), RSTRING_LEN(str));
3020 RB_GC_GUARD(str);
3021
3022 if (n < 0) {
3023 int e = errno;
3024 if (e == EWOULDBLOCK || e == EAGAIN) {
3025 if (!ex) {
3026 return sym_wait_writable;
3027 }
3028 else {
3029 rb_readwrite_syserr_fail(RB_IO_WAIT_WRITABLE, e, "write would block");
3030 }
3031 }
3032 rb_syserr_fail_path(e, fptr->pathv);
3033 }
3034
3035 return LONG2FIX(n);
3036 }
3037
3038 /*
3039 * call-seq:
3040 * ios.read([length [, outbuf]]) -> string, outbuf, or nil
3041 *
3042 * Reads _length_ bytes from the I/O stream.
3043 *
3044 * _length_ must be a non-negative integer or +nil+.
3045 *
3046 * If _length_ is a positive integer, +read+ tries to read
3047 * _length_ bytes without any conversion (binary mode).
3048 * It returns +nil+ if an EOF is encountered before anything can be read.
3049 * Fewer than _length_ bytes are returned if an EOF is encountered during
3050 * the read.
3051 * In the case of an integer _length_, the resulting string is always
3052 * in ASCII-8BIT encoding.
3053 *
3054 * If _length_ is omitted or is +nil+, it reads until EOF
3055 * and the encoding conversion is applied, if applicable.
3056 * A string is returned even if EOF is encountered before any data is read.
3057 *
3058 * If _length_ is zero, it returns an empty string (<code>""</code>).
3059 *
3060 * If the optional _outbuf_ argument is present,
3061 * it must reference a String, which will receive the data.
3062 * The _outbuf_ will contain only the received data after the method call
3063 * even if it is not empty at the beginning.
3064 *
3065 * When this method is called at end of file, it returns +nil+
3066 * or <code>""</code>, depending on _length_:
3067 * +read+, <code>read(nil)</code>, and <code>read(0)</code> return
3068 * <code>""</code>,
3069 * <code>read(<i>positive_integer</i>)</code> returns +nil+.
3070 *
3071 * f = File.new("testfile")
3072 * f.read(16) #=> "This is line one"
3073 *
3074 * # read whole file
3075 * open("file") do |f|
3076 * data = f.read # This returns a string even if the file is empty.
3077 * # ...
3078 * end
3079 *
3080 * # iterate over fixed length records
3081 * open("fixed-record-file") do |f|
3082 * while record = f.read(256)
3083 * # ...
3084 * end
3085 * end
3086 *
3087 * # iterate over variable length records,
3088 * # each record is prefixed by its 32-bit length
3089 * open("variable-record-file") do |f|
3090 * while len = f.read(4)
3091 * len = len.unpack("N")[0] # 32-bit length
3092 * record = f.read(len) # This returns a string even if len is 0.
3093 * end
3094 * end
3095 *
3096 * Note that this method behaves like the fread() function in C.
3097 * This means it retries to invoke read(2) system calls to read data
3098 * with the specified length (or until EOF).
3099 * This behavior is preserved even if <i>ios</i> is in non-blocking mode.
3100 * (This method is non-blocking flag insensitive as other methods.)
3101 * If you need the behavior like a single read(2) system call,
3102 * consider #readpartial, #read_nonblock, and #sysread.
3103 */
3104
3105 static VALUE
3106 io_read(int argc, VALUE *argv, VALUE io)
3107 {
3108 rb_io_t *fptr;
3109 long n, len;
3110 VALUE length, str;
3111 int shrinkable;
3112 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
3113 int previous_mode;
3114 #endif
3115
3116 rb_scan_args(argc, argv, "02", &length, &str);
3117
3118 if (NIL_P(length)) {
3119 GetOpenFile(io, fptr);
3120 rb_io_check_char_readable(fptr);
3121 return read_all(fptr, remain_size(fptr), str);
3122 }
3123 len = NUM2LONG(length);
3124 if (len < 0) {
3125 rb_raise(rb_eArgError, "negative length %ld given", len);
3126 }
3127
3128 shrinkable = io_setstrbuf(&str,len);
3129
3130 GetOpenFile(io, fptr);
3131 rb_io_check_byte_readable(fptr);
3132 if (len == 0) {
3133 io_set_read_length(str, 0, shrinkable);
3134 return str;
3135 }
3136
3137 READ_CHECK(fptr);
3138 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
3139 previous_mode = set_binary_mode_with_seek_cur(fptr);
3140 #endif
3141 n = io_fread(str, 0, len, fptr);
3142 io_set_read_length(str, n, shrinkable);
3143 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
3144 if (previous_mode == O_TEXT) {
3145 setmode(fptr->fd, O_TEXT);
3146 }
3147 #endif
3148 if (n == 0) return Qnil;
3149
3150 return str;
3151 }
3152
3153 static void
3154 rscheck(const char *rsptr, long rslen, VALUE rs)
3155 {
3156 if (!rs) return;
3157 if (RSTRING_PTR(rs) != rsptr && RSTRING_LEN(rs) != rslen)
3158 rb_raise(rb_eRuntimeError, "rs modified");
3159 }
3160
3161 static int
3162 appendline(rb_io_t *fptr, int delim, VALUE *strp, long *lp)
3163 {
3164 VALUE str = *strp;
3165 long limit = *lp;
3166
3167 if (NEED_READCONV(fptr)) {
3168 SET_BINARY_MODE(fptr);
3169 make_readconv(fptr, 0);
3170 do {
3171 const char *p, *e;
3172 int searchlen = READ_CHAR_PENDING_COUNT(fptr);
3173 if (searchlen) {
3174 p = READ_CHAR_PENDING_PTR(fptr);
3175 if (0 < limit && limit < searchlen)
3176 searchlen = (int)limit;
3177 e = memchr(p, delim, searchlen);
3178 if (e) {
3179 int len = (int)(e-p+1);
3180 if (NIL_P(str))
3181 *strp = str = rb_str_new(p, len);
3182 else
3183 rb_str_buf_cat(str, p, len);
3184 fptr->cbuf.off += len;
3185 fptr->cbuf.len -= len;
3186 limit -= len;
3187 *lp = limit;
3188 return delim;
3189 }
3190
3191 if (NIL_P(str))
3192 *strp = str = rb_str_new(p, searchlen);
3193 else
3194 rb_str_buf_cat(str, p, searchlen);
3195 fptr->cbuf.off += searchlen;
3196 fptr->cbuf.len -= searchlen;
3197 limit -= searchlen;
3198
3199 if (limit == 0) {
3200 *lp = limit;
3201 return (unsigned char)RSTRING_PTR(str)[RSTRING_LEN(str)-1];
3202 }
3203 }
3204 } while (more_char(fptr) != MORE_CHAR_FINISHED);
3205 clear_readconv(fptr);
3206 *lp = limit;
3207 return EOF;
3208 }
3209
3210 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
3211 do {
3212 long pending = READ_DATA_PENDING_COUNT(fptr);
3213 if (pending > 0) {
3214 const char *p = READ_DATA_PENDING_PTR(fptr);
3215 const char *e;
3216 long last;
3217
3218 if (limit > 0 && pending > limit) pending = limit;
3219 e = memchr(p, delim, pending);
3220 if (e) pending = e - p + 1;
3221 if (!NIL_P(str)) {
3222 last = RSTRING_LEN(str);
3223 rb_str_resize(str, last + pending);
3224 }
3225 else {
3226 last = 0;
3227 *strp = str = rb_str_buf_new(pending);
3228 rb_str_set_len(str, pending);
3229 }
3230 read_buffered_data(RSTRING_PTR(str) + last, pending, fptr); /* must not fail */
3231 limit -= pending;
3232 *lp = limit;
3233 if (e) return delim;
3234 if (limit == 0)
3235 return (unsigned char)RSTRING_PTR(str)[RSTRING_LEN(str)-1];
3236 }
3237 READ_CHECK(fptr);
3238 } while (io_fillbuf(fptr) >= 0);
3239 *lp = limit;
3240 return EOF;
3241 }
3242
3243 static inline int
3244 swallow(rb_io_t *fptr, int term)
3245 {
3246 if (NEED_READCONV(fptr)) {
3247 rb_encoding *enc = io_read_encoding(fptr);
3248 int needconv = rb_enc_mbminlen(enc) != 1;
3249 SET_BINARY_MODE(fptr);
3250 make_readconv(fptr, 0);
3251 do {
3252 size_t cnt;
3253 while ((cnt = READ_CHAR_PENDING_COUNT(fptr)) > 0) {
3254 const char *p = READ_CHAR_PENDING_PTR(fptr);
3255 int i;
3256 if (!needconv) {
3257 if (*p != term) return TRUE;
3258 i = (int)cnt;
3259 while (--i && *++p == term);
3260 }
3261 else {
3262 const char *e = p + cnt;
3263 if (rb_enc_ascget(p, e, &i, enc) != term) return TRUE;
3264 while ((p += i) < e && rb_enc_ascget(p, e, &i, enc) == term);
3265 i = (int)(e - p);
3266 }
3267 io_shift_cbuf(fptr, (int)cnt - i, NULL);
3268 }
3269 } while (more_char(fptr) != MORE_CHAR_FINISHED);
3270 return FALSE;
3271 }
3272
3273 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
3274 do {
3275 size_t cnt;
3276 while ((cnt = READ_DATA_PENDING_COUNT(fptr)) > 0) {
3277 char buf[1024];
3278 const char *p = READ_DATA_PENDING_PTR(fptr);
3279 int i;
3280 if (cnt > sizeof buf) cnt = sizeof buf;
3281 if (*p != term) return TRUE;
3282 i = (int)cnt;
3283 while (--i && *++p == term);
3284 if (!read_buffered_data(buf, cnt - i, fptr)) /* must not fail */
3285 rb_sys_fail_path(fptr->pathv);
3286 }
3287 READ_CHECK(fptr);
3288 } while (io_fillbuf(fptr) == 0);
3289 return FALSE;
3290 }
3291
3292 static VALUE
3293 rb_io_getline_fast(rb_io_t *fptr, rb_encoding *enc, int chomp)
3294 {
3295 VALUE str = Qnil;
3296 int len = 0;
3297 long pos = 0;
3298 int cr = 0;
3299
3300 do {
3301 int pending = READ_DATA_PENDING_COUNT(fptr);
3302
3303 if (pending > 0) {
3304 const char *p = READ_DATA_PENDING_PTR(fptr);
3305 const char *e;
3306 int chomplen = 0;
3307
3308 e = memchr(p, '\n', pending);
3309 if (e) {
3310 pending = (int)(e - p + 1);
3311 if (chomp) {
3312 chomplen = (pending > 1 && *(e-1) == '\r') + 1;
3313 }
3314 }
3315 if (NIL_P(str)) {
3316 str = rb_str_new(p, pending - chomplen);
3317 fptr->rbuf.off += pending;
3318 fptr->rbuf.len -= pending;
3319 }
3320 else {
3321 rb_str_resize(str, len + pending - chomplen);
3322 read_buffered_data(RSTRING_PTR(str)+len, pending - chomplen, fptr);
3323 fptr->rbuf.off += chomplen;
3324 fptr->rbuf.len -= chomplen;
3325 if (pending == 1 && chomplen == 1 && len > 0) {
3326 if (RSTRING_PTR(str)[len-1] == '\r') {
3327 rb_str_resize(str, --len);
3328 break;
3329 }
3330 }
3331 }
3332 len += pending - chomplen;
3333 if (cr != ENC_CODERANGE_BROKEN)
3334 pos += rb_str_coderange_scan_restartable(RSTRING_PTR(str) + pos, RSTRING_PTR(str) + len, enc, &cr);
3335 if (e) break;
3336 }
3337 READ_CHECK(fptr);
3338 } while (io_fillbuf(fptr) >= 0);
3339 if (NIL_P(str)) return Qnil;
3340
3341 str = io_enc_str(str, fptr);
3342 ENC_CODERANGE_SET(str, cr);
3343 fptr->lineno++;
3344
3345 return str;
3346 }
3347
3348 struct getline_arg {
3349 VALUE io;
3350 VALUE rs;
3351 long limit;
3352 unsigned int chomp: 1;
3353 };
3354
3355 static void
3356 extract_getline_opts(VALUE opts, struct getline_arg *args)
3357 {
3358 int chomp = FALSE;
3359 if (!NIL_P(opts)) {
3360 static ID kwds[1];
3361 VALUE vchomp;
3362 if (!kwds[0]) {
3363 kwds[0] = rb_intern_const("chomp");
3364 }
3365 rb_get_kwargs(opts, kwds, 0, -2, &vchomp);
3366 chomp = (vchomp != Qundef) && RTEST(vchomp);
3367 }
3368 args->chomp = chomp;
3369 }
3370
3371 static void
3372 extract_getline_args(int argc, VALUE *argv, struct getline_arg *args)
3373 {
3374 VALUE rs = rb_rs, lim = Qnil;
3375
3376 if (argc == 1) {
3377 VALUE tmp = Qnil;
3378
3379 if (NIL_P(argv[0]) || !NIL_P(tmp = rb_check_string_type(argv[0]))) {
3380 rs = tmp;
3381 }
3382 else {
3383 lim = argv[0];
3384 }
3385 }
3386 else if (2 <= argc) {
3387 rs = argv[0], lim = argv[1];
3388 if (!NIL_P(rs))
3389 StringValue(rs);
3390 }
3391 args->rs = rs;
3392 args->limit = NIL_P(lim) ? -1L : NUM2LONG(lim);
3393 }
3394
3395 static void
3396 check_getline_args(VALUE *rsp, long *limit, VALUE io)
3397 {
3398 rb_io_t *fptr;
3399 VALUE rs = *rsp;
3400
3401 if (!NIL_P(rs)) {
3402 rb_encoding *enc_rs, *enc_io;
3403
3404 GetOpenFile(io, fptr);
3405 enc_rs = rb_enc_get(rs);
3406 enc_io = io_read_encoding(fptr);
3407 if (enc_io != enc_rs &&
3408 (rb_enc_str_coderange(rs) != ENC_CODERANGE_7BIT ||
3409 (RSTRING_LEN(rs) > 0 && !rb_enc_asciicompat(enc_io)))) {
3410 if (rs == rb_default_rs) {
3411 rs = rb_enc_str_new(0, 0, enc_io);
3412 rb_str_buf_cat_ascii(rs, "\n");
3413 *rsp = rs;
3414 }
3415 else {
3416 rb_raise(rb_eArgError, "encoding mismatch: %s IO with %s RS",
3417 rb_enc_name(enc_io),
3418 rb_enc_name(enc_rs));
3419 }
3420 }
3421 }
3422 }
3423
3424 static void
3425 prepare_getline_args(int argc, VALUE *argv, struct getline_arg *args, VALUE io)
3426 {
3427 VALUE opts;
3428 argc = rb_scan_args(argc, argv, "02:", NULL, NULL, &opts);
3429 extract_getline_args(argc, argv, args);
3430 extract_getline_opts(opts, args);
3431 check_getline_args(&args->rs, &args->limit, io);
3432 }
3433
3434 static VALUE
3435 rb_io_getline_0(VALUE rs, long limit, int chomp, rb_io_t *fptr)
3436 {
3437 VALUE str = Qnil;
3438 int nolimit = 0;
3439 rb_encoding *enc;
3440
3441 rb_io_check_char_readable(fptr);
3442 if (NIL_P(rs) && limit < 0) {
3443 str = read_all(fptr, 0, Qnil);
3444 if (RSTRING_LEN(str) == 0) return Qnil;
3445 if (chomp) rb_str_chomp_string(str, rb_default_rs);
3446 }
3447 else if (limit == 0) {
3448 return rb_enc_str_new(0, 0, io_read_encoding(fptr));
3449 }
3450 else if (rs == rb_default_rs && limit < 0 && !NEED_READCONV(fptr) &&
3451 rb_enc_asciicompat(enc = io_read_encoding(fptr))) {
3452 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
3453 return rb_io_getline_fast(fptr, enc, chomp);
3454 }
3455 else {
3456 int c, newline = -1;
3457 const char *rsptr = 0;
3458 long rslen = 0;
3459 int rspara = 0;
3460 int extra_limit = 16;
3461 int chomp_cr = chomp;
3462
3463 SET_BINARY_MODE(fptr);
3464 enc = io_read_encoding(fptr);
3465
3466 if (!NIL_P(rs)) {
3467 rslen = RSTRING_LEN(rs);
3468 if (rslen == 0) {
3469 rsptr = "\n\n";
3470 rslen = 2;
3471 rspara = 1;
3472 swallow(fptr, '\n');
3473 rs = 0;
3474 if (!rb_enc_asciicompat(enc)) {
3475 rs = rb_usascii_str_new(rsptr, rslen);
3476 rs = rb_str_encode(rs, rb_enc_from_encoding(enc), 0, Qnil);
3477 OBJ_FREEZE(rs);
3478 rsptr = RSTRING_PTR(rs);
3479 rslen = RSTRING_LEN(rs);
3480 }
3481 }
3482 else {
3483 rsptr = RSTRING_PTR(rs);
3484 }
3485 newline = (unsigned char)rsptr[rslen - 1];
3486 chomp_cr = chomp && rslen == 1 && newline == '\n';
3487 }
3488
3489 /* MS - Optimization */
3490 while ((c = appendline(fptr, newline, &str, &limit)) != EOF) {
3491 const char *s, *p, *pp, *e;
3492
3493 if (c == newline) {
3494 if (RSTRING_LEN(str) < rslen) continue;
3495 s = RSTRING_PTR(str);
3496 e = RSTRING_END(str);
3497 p = e - rslen;
3498 pp = rb_enc_left_char_head(s, p, e, enc);
3499 if (pp != p) continue;
3500 if (!rspara) rscheck(rsptr, rslen, rs);
3501 if (memcmp(p, rsptr, rslen) == 0) {
3502 if (chomp) {
3503 if (chomp_cr && p > s && *(p-1) == '\r') --p;
3504 rb_str_set_len(str, p - s);
3505 }
3506 break;
3507 }
3508 }
3509 if (limit == 0) {
3510 s = RSTRING_PTR(str);
3511 p = RSTRING_END(str);
3512 pp = rb_enc_left_char_head(s, p-1, p, enc);
3513 if (extra_limit &&
3514 MBCLEN_NEEDMORE_P(rb_enc_precise_mbclen(pp, p, enc))) {
3515 /* relax the limit while incomplete character.
3516 * extra_limit limits the relax length */
3517 limit = 1;
3518 extra_limit--;
3519 }
3520 else {
3521 nolimit = 1;
3522 break;
3523 }
3524 }
3525 }
3526
3527 if (rspara && c != EOF)
3528 swallow(fptr, '\n');
3529 if (!NIL_P(str))
3530 str = io_enc_str(str, fptr);
3531 }
3532
3533 if (!NIL_P(str) && !nolimit) {
3534 fptr->lineno++;
3535 }
3536
3537 return str;
3538 }
3539
3540 static VALUE
3541 rb_io_getline_1(VALUE rs, long limit, int chomp, VALUE io)
3542 {
3543 rb_io_t *fptr;
3544 int old_lineno, new_lineno;
3545 VALUE str;
3546
3547 GetOpenFile(io, fptr);
3548 old_lineno = fptr->lineno;
3549 str = rb_io_getline_0(rs, limit, chomp, fptr);
3550 if (!NIL_P(str) && (new_lineno = fptr->lineno) != old_lineno) {
3551 if (io == ARGF.current_file) {
3552 ARGF.lineno += new_lineno - old_lineno;
3553 ARGF.last_lineno = ARGF.lineno;
3554 }
3555 else {
3556 ARGF.last_lineno = new_lineno;
3557 }
3558 }
3559
3560 return str;
3561 }
3562
3563 static VALUE
3564 rb_io_getline(int argc, VALUE *argv, VALUE io)
3565 {
3566 struct getline_arg args;
3567
3568 prepare_getline_args(argc, argv, &args, io);
3569 return rb_io_getline_1(args.rs, args.limit, args.chomp, io);
3570 }
3571
3572 VALUE
3573 rb_io_gets(VALUE io)
3574 {
3575 return rb_io_getline_1(rb_default_rs, -1, FALSE, io);
3576 }
3577
3578 VALUE
3579 rb_io_gets_internal(VALUE io)
3580 {
3581 rb_io_t *fptr;
3582 GetOpenFile(io, fptr);
3583 return rb_io_getline_0(rb_default_rs, -1, FALSE, fptr);
3584 }
3585
3586 /*
3587 * call-seq:
3588 * ios.gets(sep=$/ [, getline_args]) -> string or nil
3589 * ios.gets(limit [, getline_args]) -> string or nil
3590 * ios.gets(sep, limit [, getline_args]) -> string or nil
3591 *
3592 * Reads the next ``line'' from the I/O stream; lines are separated by
3593 * <i>sep</i>. A separator of +nil+ reads the entire
3594 * contents, and a zero-length separator reads the input a paragraph at
3595 * a time (two successive newlines in the input separate paragraphs).
3596 * The stream must be opened for reading or an IOError will be raised.
3597 * The line read in will be returned and also assigned to
3598 * <code>$_</code>. Returns +nil+ if called at end of file. If the
3599 * first argument is an integer, or optional second argument is given,
3600 * the returning string would not be longer than the given value in
3601 * bytes.
3602 *
3603 * File.new("testfile").gets #=> "This is line one\n"
3604 * $_ #=> "This is line one\n"
3605 *
3606 * File.new("testfile").gets(4)#=> "This"
3607 *
3608 * If IO contains multibyte characters byte then <code>gets(1)</code>
3609 * returns character entirely:
3610 *
3611 * # Russian characters take 2 bytes
3612 * File.write("testfile", "\u{442 435 441 442}")
3613 * File.open("testfile") {|f|f.gets(1)} #=> "\u0442"
3614 * File.open("testfile") {|f|f.gets(2)} #=> "\u0442"
3615 * File.open("testfile") {|f|f.gets(3)} #=> "\u0442\u0435"
3616 * File.open("testfile") {|f|f.gets(4)} #=> "\u0442\u0435"
3617 */
3618
3619 static VALUE
3620 rb_io_gets_m(int argc, VALUE *argv, VALUE io)
3621 {
3622 VALUE str;
3623
3624 str = rb_io_getline(argc, argv, io);
3625 rb_lastline_set(str);
3626
3627 return str;
3628 }
3629
3630 /*
3631 * call-seq:
3632 * ios.lineno -> integer
3633 *
3634 * Returns the current line number in <em>ios</em>. The stream must be
3635 * opened for reading. #lineno counts the number of times #gets is called
3636 * rather than the number of newlines encountered. The two values will
3637 * differ if #gets is called with a separator other than newline.
3638 *
3639 * Methods that use <code>$/</code> like #each, #lines and #readline will
3640 * also increment #lineno.
3641 *
3642 * See also the <code>$.</code> variable.
3643 *
3644 * f = File.new("testfile")
3645 * f.lineno #=> 0
3646 * f.gets #=> "This is line one\n"
3647 * f.lineno #=> 1
3648 * f.gets #=> "This is line two\n"
3649 * f.lineno #=> 2
3650 */
3651
3652 static VALUE
3653 rb_io_lineno(VALUE io)
3654 {
3655 rb_io_t *fptr;
3656
3657 GetOpenFile(io, fptr);
3658 rb_io_check_char_readable(fptr);
3659 return INT2NUM(fptr->lineno);
3660 }
3661
3662 /*
3663 * call-seq:
3664 * ios.lineno = integer -> integer
3665 *
3666 * Manually sets the current line number to the given value.
3667 * <code>$.</code> is updated only on the next read.
3668 *
3669 * f = File.new("testfile")
3670 * f.gets #=> "This is line one\n"
3671 * $. #=> 1
3672 * f.lineno = 1000
3673 * f.lineno #=> 1000
3674 * $. #=> 1 # lineno of last read
3675 * f.gets #=> "This is line two\n"
3676 * $. #=> 1001 # lineno of last read
3677 */
3678
3679 static VALUE
3680 rb_io_set_lineno(VALUE io, VALUE lineno)
3681 {
3682 rb_io_t *fptr;
3683
3684 GetOpenFile(io, fptr);
3685 rb_io_check_char_readable(fptr);
3686 fptr->lineno = NUM2INT(lineno);
3687 return lineno;
3688 }
3689
3690 /*
3691 * call-seq:
3692 * ios.readline(sep=$/ [, getline_args]) -> string
3693 * ios.readline(limit [, getline_args]) -> string
3694 * ios.readline(sep, limit [, getline_args]) -> string
3695 *
3696 * Reads a line as with IO#gets, but raises an EOFError on end of file.
3697 */
3698
3699 static VALUE
3700 rb_io_readline(int argc, VALUE *argv, VALUE io)
3701 {
3702 VALUE line = rb_io_gets_m(argc, argv, io);
3703
3704 if (NIL_P(line)) {
3705 rb_eof_error();
3706 }
3707 return line;
3708 }
3709
3710 static VALUE io_readlines(const struct getline_arg *arg, VALUE io);
3711
3712 /*
3713 * call-seq:
3714 * ios.readlines(sep=$/ [, getline_args]) -> array
3715 * ios.readlines(limit [, getline_args]) -> array
3716 * ios.readlines(sep, limit [, getline_args]) -> array
3717 *
3718 * Reads all of the lines in <em>ios</em>, and returns them in
3719 * an array. Lines are separated by the optional <i>sep</i>. If
3720 * <i>sep</i> is +nil+, the rest of the stream is returned
3721 * as a single record.
3722 * If the first argument is an integer, or an
3723 * optional second argument is given, the returning string would not be
3724 * longer than the given value in bytes. The stream must be opened for
3725 * reading or an IOError will be raised.
3726 *
3727 * f = File.new("testfile")
3728 * f.readlines[0] #=> "This is line one\n"
3729 *
3730 * f = File.new("testfile", chomp: true)
3731 * f.readlines[0] #=> "This is line one"
3732 *
3733 * See IO.readlines for details about getline_args.
3734 */
3735
3736 static VALUE
3737 rb_io_readlines(int argc, VALUE *argv, VALUE io)
3738 {
3739 struct getline_arg args;
3740
3741 prepare_getline_args(argc, argv, &args, io);
3742 return io_readlines(&args, io);
3743 }
3744
3745 static VALUE
3746 io_readlines(const struct getline_arg *arg, VALUE io)
3747 {
3748 VALUE line, ary;
3749
3750 if (arg->limit == 0)
3751 rb_raise(rb_eArgError, "invalid limit: 0 for readlines");
3752 ary = rb_ary_new();
3753 while (!NIL_P(line = rb_io_getline_1(arg->rs, arg->limit, arg->chomp, io))) {
3754 rb_ary_push(ary, line);
3755 }
3756 return ary;
3757 }
3758
3759 /*
3760 * call-seq:
3761 * ios.each(sep=$/ [, getline_args]) {|line| block } -> ios
3762 * ios.each(limit [, getline_args]) {|line| block } -> ios
3763 * ios.each(sep, limit [, getline_args]) {|line| block } -> ios
3764 * ios.each(...) -> an_enumerator
3765 *
3766 * ios.each_line(sep=$/ [, getline_args]) {|line| block } -> ios
3767 * ios.each_line(limit [, getline_args]) {|line| block } -> ios
3768 * ios.each_line(sep, limit [, getline_args]) {|line| block } -> ios
3769 * ios.each_line(...) -> an_enumerator
3770 *
3771 * Executes the block for every line in <em>ios</em>, where lines are
3772 * separated by <i>sep</i>. <em>ios</em> must be opened for
3773 * reading or an IOError will be raised.
3774 *
3775 * If no block is given, an enumerator is returned instead.
3776 *
3777 * f = File.new("testfile")
3778 * f.each {|line| puts "#{f.lineno}: #{line}" }
3779 *
3780 * <em>produces:</em>
3781 *
3782 * 1: This is line one
3783 * 2: This is line two
3784 * 3: This is line three
3785 * 4: And so on...
3786 *
3787 * See IO.readlines for details about getline_args.
3788 */
3789
3790 static VALUE
3791 rb_io_each_line(int argc, VALUE *argv, VALUE io)
3792 {
3793 VALUE str;
3794 struct getline_arg args;
3795
3796 RETURN_ENUMERATOR(io, argc, argv);
3797 prepare_getline_args(argc, argv, &args, io);
3798 if (args.limit == 0)
3799 rb_raise(rb_eArgError, "invalid limit: 0 for each_line");
3800 while (!NIL_P(str = rb_io_getline_1(args.rs, args.limit, args.chomp, io))) {
3801 rb_yield(str);
3802 }
3803 return io;
3804 }
3805
3806 /*
3807 * This is a deprecated alias for #each_line.
3808 */
3809
3810 static VALUE
3811 rb_io_lines(int argc, VALUE *argv, VALUE io)
3812 {
3813 rb_warn_deprecated("IO#lines", "#each_line");
3814 if (!rb_block_given_p())
3815 return rb_enumeratorize(io, ID2SYM(rb_intern("each_line")), argc, argv);
3816 return rb_io_each_line(argc, argv, io);
3817 }
3818
3819 /*
3820 * call-seq:
3821 * ios.each_byte {|byte| block } -> ios
3822 * ios.each_byte -> an_enumerator
3823 *
3824 * Calls the given block once for each byte (0..255) in <em>ios</em>,
3825 * passing the byte as an argument. The stream must be opened for
3826 * reading or an IOError will be raised.
3827 *
3828 * If no block is given, an enumerator is returned instead.
3829 *
3830 * f = File.new("testfile")
3831 * checksum = 0
3832 * f.each_byte {|x| checksum ^= x } #=> #<File:testfile>
3833 * checksum #=> 12
3834 */
3835
3836 static VALUE
3837 rb_io_each_byte(VALUE io)
3838 {
3839 rb_io_t *fptr;
3840
3841 RETURN_ENUMERATOR(io, 0, 0);
3842 GetOpenFile(io, fptr);
3843
3844 do {
3845 while (fptr->rbuf.len > 0) {
3846 char *p = fptr->rbuf.ptr + fptr->rbuf.off++;
3847 fptr->rbuf.len--;
3848 rb_yield(INT2FIX(*p & 0xff));
3849 errno = 0;
3850 }
3851 rb_io_check_byte_readable(fptr);
3852 READ_CHECK(fptr);
3853 } while (io_fillbuf(fptr) >= 0);
3854 return io;
3855 }
3856
3857 /*
3858 * This is a deprecated alias for #each_byte.
3859 */
3860
3861 static VALUE
3862 rb_io_bytes(VALUE io)
3863 {
3864 rb_warn_deprecated("IO#bytes", "#each_byte");
3865 if (!rb_block_given_p())
3866 return rb_enumeratorize(io, ID2SYM(rb_intern("each_byte")), 0, 0);
3867 return rb_io_each_byte(io);
3868 }
3869
3870 static VALUE
3871 io_getc(rb_io_t *fptr, rb_encoding *enc)
3872 {
3873 int r, n, cr = 0;
3874 VALUE str;
3875
3876 if (NEED_READCONV(fptr)) {
3877 rb_encoding *read_enc = io_read_encoding(fptr);
3878
3879 str = Qnil;
3880 SET_BINARY_MODE(fptr);
3881 make_readconv(fptr, 0);
3882
3883 while (1) {
3884 if (fptr->cbuf.len) {
3885 r = rb_enc_precise_mbclen(fptr->cbuf.ptr+fptr->cbuf.off,
3886 fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
3887 read_enc);
3888 if (!MBCLEN_NEEDMORE_P(r))
3889 break;
3890 if (fptr->cbuf.len == fptr->cbuf.capa) {
3891 rb_raise(rb_eIOError, "too long character");
3892 }
3893 }
3894
3895 if (more_char(fptr) == MORE_CHAR_FINISHED) {
3896 if (fptr->cbuf.len == 0) {
3897 clear_readconv(fptr);
3898 return Qnil;
3899 }
3900 /* return an unit of an incomplete character just before EOF */
3901 str = rb_enc_str_new(fptr->cbuf.ptr+fptr->cbuf.off, 1, read_enc);
3902 fptr->cbuf.off += 1;
3903 fptr->cbuf.len -= 1;
3904 if (fptr->cbuf.len == 0) clear_readconv(fptr);
3905 ENC_CODERANGE_SET(str, ENC_CODERANGE_BROKEN);
3906 return str;
3907 }
3908 }
3909 if (MBCLEN_INVALID_P(r)) {
3910 r = rb_enc_mbclen(fptr->cbuf.ptr+fptr->cbuf.off,
3911 fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
3912 read_enc);
3913 io_shift_cbuf(fptr, r, &str);
3914 cr = ENC_CODERANGE_BROKEN;
3915 }
3916 else {
3917 io_shift_cbuf(fptr, MBCLEN_CHARFOUND_LEN(r), &str);
3918 cr = ENC_CODERANGE_VALID;
3919 if (MBCLEN_CHARFOUND_LEN(r) == 1 && rb_enc_asciicompat(read_enc) &&
3920 ISASCII(RSTRING_PTR(str)[0])) {
3921 cr = ENC_CODERANGE_7BIT;
3922 }
3923 }
3924 str = io_enc_str(str, fptr);
3925 ENC_CODERANGE_SET(str, cr);
3926 return str;
3927 }
3928
3929 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
3930 if (io_fillbuf(fptr) < 0) {
3931 return Qnil;
3932 }
3933 if (rb_enc_asciicompat(enc) && ISASCII(fptr->rbuf.ptr[fptr->rbuf.off])) {
3934 str = rb_str_new(fptr->rbuf.ptr+fptr->rbuf.off, 1);
3935 fptr->rbuf.off += 1;
3936 fptr->rbuf.len -= 1;
3937 cr = ENC_CODERANGE_7BIT;
3938 }
3939 else {
3940 r = rb_enc_precise_mbclen(fptr->rbuf.ptr+fptr->rbuf.off, fptr->rbuf.ptr+fptr->rbuf.off+fptr->rbuf.len, enc);
3941 if (MBCLEN_CHARFOUND_P(r) &&
3942 (n = MBCLEN_CHARFOUND_LEN(r)) <= fptr->rbuf.len) {
3943 str = rb_str_new(fptr->rbuf.ptr+fptr->rbuf.off, n);
3944 fptr->rbuf.off += n;
3945 fptr->rbuf.len -= n;
3946 cr = ENC_CODERANGE_VALID;
3947 }
3948 else if (MBCLEN_NEEDMORE_P(r)) {
3949 str = rb_str_new(fptr->rbuf.ptr+fptr->rbuf.off, fptr->rbuf.len);
3950 fptr->rbuf.len = 0;
3951 getc_needmore:
3952 if (io_fillbuf(fptr) != -1) {
3953 rb_str_cat(str, fptr->rbuf.ptr+fptr->rbuf.off, 1);
3954 fptr->rbuf.off++;
3955 fptr->rbuf.len--;
3956 r = rb_enc_precise_mbclen(RSTRING_PTR(str), RSTRING_PTR(str)+RSTRING_LEN(str), enc);
3957 if (MBCLEN_NEEDMORE_P(r)) {
3958 goto getc_needmore;
3959 }
3960 else if (MBCLEN_CHARFOUND_P(r)) {
3961 cr = ENC_CODERANGE_VALID;
3962 }
3963 }
3964 }
3965 else {
3966 str = rb_str_new(fptr->rbuf.ptr+fptr->rbuf.off, 1);
3967 fptr->rbuf.off++;
3968 fptr->rbuf.len--;
3969 }
3970 }
3971 if (!cr) cr = ENC_CODERANGE_BROKEN;
3972 str = io_enc_str(str, fptr);
3973 ENC_CODERANGE_SET(str, cr);
3974 return str;
3975 }
3976
3977 /*
3978 * call-seq:
3979 * ios.each_char {|c| block } -> ios
3980 * ios.each_char -> an_enumerator
3981 *
3982 * Calls the given block once for each character in <em>ios</em>,
3983 * passing the character as an argument. The stream must be opened for
3984 * reading or an IOError will be raised.
3985 *
3986 * If no block is given, an enumerator is returned instead.
3987 *
3988 * f = File.new("testfile")
3989 * f.each_char {|c| print c, ' ' } #=> #<File:testfile>
3990 */
3991
3992 static VALUE
3993 rb_io_each_char(VALUE io)
3994 {
3995 rb_io_t *fptr;
3996 rb_encoding *enc;
3997 VALUE c;
3998
3999 RETURN_ENUMERATOR(io, 0, 0);
4000 GetOpenFile(io, fptr);
4001 rb_io_check_char_readable(fptr);
4002
4003 enc = io_input_encoding(fptr);
4004 READ_CHECK(fptr);
4005 while (!NIL_P(c = io_getc(fptr, enc))) {
4006 rb_yield(c);
4007 }
4008 return io;
4009 }
4010
4011 /*
4012 * This is a deprecated alias for #each_char.
4013 */
4014
4015 static VALUE
4016 rb_io_chars(VALUE io)
4017 {
4018 rb_warn_deprecated("IO#chars", "#each_char");
4019 if (!rb_block_given_p())
4020 return rb_enumeratorize(io, ID2SYM(rb_intern("each_char")), 0, 0);
4021 return rb_io_each_char(io);
4022 }
4023
4024
4025 /*
4026 * call-seq:
4027 * ios.each_codepoint {|c| block } -> ios
4028 * ios.codepoints {|c| block } -> ios
4029 * ios.each_codepoint -> an_enumerator
4030 * ios.codepoints -> an_enumerator
4031 *
4032 * Passes the Integer ordinal of each character in <i>ios</i>,
4033 * passing the codepoint as an argument. The stream must be opened for
4034 * reading or an IOError will be raised.
4035 *
4036 * If no block is given, an enumerator is returned instead.
4037 *
4038 */
4039
4040 static VALUE
4041 rb_io_each_codepoint(VALUE io)
4042 {
4043 rb_io_t *fptr;
4044 rb_encoding *enc;
4045 unsigned int c;
4046 int r, n;
4047
4048 RETURN_ENUMERATOR(io, 0, 0);
4049 GetOpenFile(io, fptr);
4050 rb_io_check_char_readable(fptr);
4051
4052 READ_CHECK(fptr);
4053 if (NEED_READCONV(fptr)) {
4054 SET_BINARY_MODE(fptr);
4055 r = 1; /* no invalid char yet */
4056 for (;;) {
4057 make_readconv(fptr, 0);
4058 for (;;) {
4059 if (fptr->cbuf.len) {
4060 if (fptr->encs.enc)
4061 r = rb_enc_precise_mbclen(fptr->cbuf.ptr+fptr->cbuf.off,
4062 fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
4063 fptr->encs.enc);
4064 else
4065 r = ONIGENC_CONSTRUCT_MBCLEN_CHARFOUND(1);
4066 if (!MBCLEN_NEEDMORE_P(r))
4067 break;
4068 if (fptr->cbuf.len == fptr->cbuf.capa) {
4069 rb_raise(rb_eIOError, "too long character");
4070 }
4071 }
4072 if (more_char(fptr) == MORE_CHAR_FINISHED) {
4073 clear_readconv(fptr);
4074 if (!MBCLEN_CHARFOUND_P(r)) {
4075 enc = fptr->encs.enc;
4076 goto invalid;
4077 }
4078 return io;
4079 }
4080 }
4081 if (MBCLEN_INVALID_P(r)) {
4082 enc = fptr->encs.enc;
4083 goto invalid;
4084 }
4085 n = MBCLEN_CHARFOUND_LEN(r);
4086 if (fptr->encs.enc) {
4087 c = rb_enc_codepoint(fptr->cbuf.ptr+fptr->cbuf.off,
4088 fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
4089 fptr->encs.enc);
4090 }
4091 else {
4092 c = (unsigned char)fptr->cbuf.ptr[fptr->cbuf.off];
4093 }
4094 fptr->cbuf.off += n;
4095 fptr->cbuf.len -= n;
4096 rb_yield(UINT2NUM(c));
4097 }
4098 }
4099 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
4100 enc = io_input_encoding(fptr);
4101 while (io_fillbuf(fptr) >= 0) {
4102 r = rb_enc_precise_mbclen(fptr->rbuf.ptr+fptr->rbuf.off,
4103 fptr->rbuf.ptr+fptr->rbuf.off+fptr->rbuf.len, enc);
4104 if (MBCLEN_CHARFOUND_P(r) &&
4105 (n = MBCLEN_CHARFOUND_LEN(r)) <= fptr->rbuf.len) {
4106 c = rb_enc_codepoint(fptr->rbuf.ptr+fptr->rbuf.off,
4107 fptr->rbuf.ptr+fptr->rbuf.off+fptr->rbuf.len, enc);
4108 fptr->rbuf.off += n;
4109 fptr->rbuf.len -= n;
4110 rb_yield(UINT2NUM(c));
4111 }
4112 else if (MBCLEN_INVALID_P(r)) {
4113 invalid:
4114 rb_raise(rb_eArgError, "invalid byte sequence in %s", rb_enc_name(enc));
4115 }
4116 else if (MBCLEN_NEEDMORE_P(r)) {
4117 char cbuf[8], *p = cbuf;
4118 int more = MBCLEN_NEEDMORE_LEN(r);
4119 if (more > numberof(cbuf)) goto invalid;
4120 more += n = fptr->rbuf.len;
4121 if (more > numberof(cbuf)) goto invalid;
4122 while ((n = (int)read_buffered_data(p, more, fptr)) > 0 &&
4123 (p += n, (more -= n) > 0)) {
4124 if (io_fillbuf(fptr) < 0) goto invalid;
4125 if ((n = fptr->rbuf.len) > more) n = more;
4126 }
4127 r = rb_enc_precise_mbclen(cbuf, p, enc);
4128 if (!MBCLEN_CHARFOUND_P(r)) goto invalid;
4129 c = rb_enc_codepoint(cbuf, p, enc);
4130 rb_yield(UINT2NUM(c));
4131 }
4132 else {
4133 continue;
4134 }
4135 }
4136 return io;
4137 }
4138
4139 /*
4140 * This is a deprecated alias for #each_codepoint.
4141 */
4142
4143 static VALUE
4144 rb_io_codepoints(VALUE io)
4145 {
4146 rb_warn_deprecated("IO#codepoints", "#each_codepoint");
4147 if (!rb_block_given_p())
4148 return rb_enumeratorize(io, ID2SYM(rb_intern("each_codepoint")), 0, 0);
4149 return rb_io_each_codepoint(io);
4150 }
4151
4152
4153 /*
4154 * call-seq:
4155 * ios.getc -> string or nil
4156 *
4157 * Reads a one-character string from <em>ios</em>. Returns
4158 * +nil+ if called at end of file.
4159 *
4160 * f = File.new("testfile")
4161 * f.getc #=> "h"
4162 * f.getc #=> "e"
4163 */
4164
4165 static VALUE
4166 rb_io_getc(VALUE io)
4167 {
4168 rb_io_t *fptr;
4169 rb_encoding *enc;
4170
4171 GetOpenFile(io, fptr);
4172 rb_io_check_char_readable(fptr);
4173
4174 enc = io_input_encoding(fptr);
4175 READ_CHECK(fptr);
4176 return io_getc(fptr, enc);
4177 }
4178
4179 /*
4180 * call-seq:
4181 * ios.readchar -> string
4182 *
4183 * Reads a one-character string from <em>ios</em>. Raises an
4184 * EOFError on end of file.
4185 *
4186 * f = File.new("testfile")
4187 * f.readchar #=> "h"
4188 * f.readchar #=> "e"
4189 */
4190
4191 static VALUE
4192 rb_io_readchar(VALUE io)
4193 {
4194 VALUE c = rb_io_getc(io);
4195
4196 if (NIL_P(c)) {
4197 rb_eof_error();
4198 }
4199 return c;
4200 }
4201
4202 /*
4203 * call-seq:
4204 * ios.getbyte -> integer or nil
4205 *
4206 * Gets the next 8-bit byte (0..255) from <em>ios</em>. Returns
4207 * +nil+ if called at end of file.
4208 *
4209 * f = File.new("testfile")
4210 * f.getbyte #=> 84
4211 * f.getbyte #=> 104
4212 */
4213
4214 VALUE
4215 rb_io_getbyte(VALUE io)
4216 {
4217 rb_io_t *fptr;
4218 int c;
4219
4220 GetOpenFile(io, fptr);
4221 rb_io_check_byte_readable(fptr);
4222 READ_CHECK(fptr);
4223 if (fptr->fd == 0 && (fptr->mode & FMODE_TTY) && RB_TYPE_P(rb_stdout, T_FILE)) {
4224 rb_io_t *ofp;
4225 GetOpenFile(rb_stdout, ofp);
4226 if (ofp->mode & FMODE_TTY) {
4227 rb_io_flush(rb_stdout);
4228 }
4229 }
4230 if (io_fillbuf(fptr) < 0) {
4231 return Qnil;
4232 }
4233 fptr->rbuf.off++;
4234 fptr->rbuf.len--;
4235 c = (unsigned char)fptr->rbuf.ptr[fptr->rbuf.off-1];
4236 return INT2FIX(c & 0xff);
4237 }
4238
4239 /*
4240 * call-seq:
4241 * ios.readbyte -> integer
4242 *
4243 * Reads a byte as with IO#getbyte, but raises an EOFError on end of
4244 * file.
4245 */
4246
4247 static VALUE
4248 rb_io_readbyte(VALUE io)
4249 {
4250 VALUE c = rb_io_getbyte(io);
4251
4252 if (NIL_P(c)) {
4253 rb_eof_error();
4254 }
4255 return c;
4256 }
4257
4258 /*
4259 * call-seq:
4260 * ios.ungetbyte(string) -> nil
4261 * ios.ungetbyte(integer) -> nil
4262 *
4263 * Pushes back bytes (passed as a parameter) onto <em>ios</em>,
4264 * such that a subsequent buffered read will return it. Only one byte
4265 * may be pushed back before a subsequent read operation (that is,
4266 * you will be able to read only the last of several bytes that have been pushed
4267 * back). Has no effect with unbuffered reads (such as IO#sysread).
4268 *
4269 * f = File.new("testfile") #=> #<File:testfile>
4270 * b = f.getbyte #=> 0x38
4271 * f.ungetbyte(b) #=> nil
4272 * f.getbyte #=> 0x38
4273 */
4274
4275 VALUE
4276 rb_io_ungetbyte(VALUE io, VALUE b)
4277 {
4278 rb_io_t *fptr;
4279
4280 GetOpenFile(io, fptr);
4281 rb_io_check_byte_readable(fptr);
4282 switch (TYPE(b)) {
4283 case T_NIL:
4284 return Qnil;
4285 case T_FIXNUM:
4286 case T_BIGNUM: ;
4287 VALUE v = rb_int_modulo(b, INT2FIX(256));
4288 unsigned char c = NUM2INT(v) & 0xFF;
4289 b = rb_str_new((const char *)&c, 1);
4290 break;
4291 default:
4292 SafeStringValue(b);
4293 }
4294 io_ungetbyte(b, fptr);
4295 return Qnil;
4296 }
4297
4298 /*
4299 * call-seq:
4300 * ios.ungetc(string) -> nil
4301 *
4302 * Pushes back one character (passed as a parameter) onto <em>ios</em>,
4303 * such that a subsequent buffered character read will return it. Only one character
4304 * may be pushed back before a subsequent read operation (that is,
4305 * you will be able to read only the last of several characters that have been pushed
4306 * back). Has no effect with unbuffered reads (such as IO#sysread).
4307 *
4308 * f = File.new("testfile") #=> #<File:testfile>
4309 * c = f.getc #=> "8"
4310 * f.ungetc(c) #=> nil
4311 * f.getc #=> "8"
4312 */
4313
4314 VALUE
4315 rb_io_ungetc(VALUE io, VALUE c)
4316 {
4317 rb_io_t *fptr;
4318 long len;
4319
4320 GetOpenFile(io, fptr);
4321 rb_io_check_char_readable(fptr);
4322 if (NIL_P(c)) return Qnil;
4323 if (FIXNUM_P(c)) {
4324 c = rb_enc_uint_chr(FIX2UINT(c), io_read_encoding(fptr));
4325 }
4326 else if (RB_TYPE_P(c, T_BIGNUM)) {
4327 c = rb_enc_uint_chr(NUM2UINT(c), io_read_encoding(fptr));
4328 }
4329 else {
4330 SafeStringValue(c);
4331 }
4332 if (NEED_READCONV(fptr)) {
4333 SET_BINARY_MODE(fptr);
4334 len = RSTRING_LEN(c);
4335 #if SIZEOF_LONG > SIZEOF_INT
4336 if (len > INT_MAX)
4337 rb_raise(rb_eIOError, "ungetc failed");
4338 #endif
4339 make_readconv(fptr, (int)len);
4340 if (fptr->cbuf.capa - fptr->cbuf.len < len)
4341 rb_raise(rb_eIOError, "ungetc failed");
4342 if (fptr->cbuf.off < len) {
4343 MEMMOVE(fptr->cbuf.ptr+fptr->cbuf.capa-fptr->cbuf.len,
4344 fptr->cbuf.ptr+fptr->cbuf.off,
4345 char, fptr->cbuf.len);
4346 fptr->cbuf.off = fptr->cbuf.capa-fptr->cbuf.len;
4347 }
4348 fptr->cbuf.off -= (int)len;
4349 fptr->cbuf.len += (int)len;
4350 MEMMOVE(fptr->cbuf.ptr+fptr->cbuf.off, RSTRING_PTR(c), char, len);
4351 }
4352 else {
4353 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
4354 io_ungetbyte(c, fptr);
4355 }
4356 return Qnil;
4357 }
4358
4359 /*
4360 * call-seq:
4361 * ios.isatty -> true or false
4362 * ios.tty? -> true or false
4363 *
4364 * Returns <code>true</code> if <em>ios</em> is associated with a
4365 * terminal device (tty), <code>false</code> otherwise.
4366 *
4367 * File.new("testfile").isatty #=> false
4368 * File.new("/dev/tty").isatty #=> true
4369 */
4370
4371 static VALUE
4372 rb_io_isatty(VALUE io)
4373 {
4374 rb_io_t *fptr;
4375
4376 GetOpenFile(io, fptr);
4377 if (isatty(fptr->fd) == 0)
4378 return Qfalse;
4379 return Qtrue;
4380 }
4381
4382 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
4383 /*
4384 * call-seq:
4385 * ios.close_on_exec? -> true or false
4386 *
4387 * Returns <code>true</code> if <em>ios</em> will be closed on exec.
4388 *
4389 * f = open("/dev/null")
4390 * f.close_on_exec? #=> false
4391 * f.close_on_exec = true
4392 * f.close_on_exec? #=> true
4393 * f.close_on_exec = false
4394 * f.close_on_exec? #=> false
4395 */
4396
4397 static VALUE
4398 rb_io_close_on_exec_p(VALUE io)
4399 {
4400 rb_io_t *fptr;
4401 VALUE write_io;
4402 int fd, ret;
4403
4404 write_io = GetWriteIO(io);
4405 if (io != write_io) {
4406 GetOpenFile(write_io, fptr);
4407 if (fptr && 0 <= (fd = fptr->fd)) {
4408 if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
4409 if (!(ret & FD_CLOEXEC)) return Qfalse;
4410 }
4411 }
4412
4413 GetOpenFile(io, fptr);
4414 if (fptr && 0 <= (fd = fptr->fd)) {
4415 if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
4416 if (!(ret & FD_CLOEXEC)) return Qfalse;
4417 }
4418 return Qtrue;
4419 }
4420 #else
4421 #define rb_io_close_on_exec_p rb_f_notimplement
4422 #endif
4423
4424 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
4425 /*
4426 * call-seq:
4427 * ios.close_on_exec = bool -> true or false
4428 *
4429 * Sets a close-on-exec flag.
4430 *
4431 * f = open("/dev/null")
4432 * f.close_on_exec = true
4433 * system("cat", "/proc/self/fd/#{f.fileno}") # cat: /proc/self/fd/3: No such file or directory
4434 * f.closed? #=> false
4435 *
4436 * Ruby sets close-on-exec flags of all file descriptors by default
4437 * since Ruby 2.0.0.
4438 * So you don't need to set by yourself.
4439 * Also, unsetting a close-on-exec flag can cause file descriptor leak
4440 * if another thread use fork() and exec() (via system() method for example).
4441 * If you really needs file descriptor inheritance to child process,
4442 * use spawn()'s argument such as fd=>fd.
4443 */
4444
4445 static VALUE
4446 rb_io_set_close_on_exec(VALUE io, VALUE arg)
4447 {
4448 int flag = RTEST(arg) ? FD_CLOEXEC : 0;
4449 rb_io_t *fptr;
4450 VALUE write_io;
4451 int fd, ret;
4452
4453 write_io = GetWriteIO(io);
4454 if (io != write_io) {
4455 GetOpenFile(write_io, fptr);
4456 if (fptr && 0 <= (fd = fptr->fd)) {
4457 if ((ret = fcntl(fptr->fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
4458 if ((ret & FD_CLOEXEC) != flag) {
4459 ret = (ret & ~FD_CLOEXEC) | flag;
4460 ret = fcntl(fd, F_SETFD, ret);
4461 if (ret != 0) rb_sys_fail_path(fptr->pathv);
4462 }
4463 }
4464
4465 }
4466
4467 GetOpenFile(io, fptr);
4468 if (fptr && 0 <= (fd = fptr->fd)) {
4469 if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
4470 if ((ret & FD_CLOEXEC) != flag) {
4471 ret = (ret & ~FD_CLOEXEC) | flag;
4472 ret = fcntl(fd, F_SETFD, ret);
4473 if (ret != 0) rb_sys_fail_path(fptr->pathv);
4474 }
4475 }
4476 return Qnil;
4477 }
4478 #else
4479 #define rb_io_set_close_on_exec rb_f_notimplement
4480 #endif
4481
4482 #define FMODE_PREP (1<<16)
4483 #define IS_PREP_STDIO(f) ((f)->mode & FMODE_PREP)
4484 #define PREP_STDIO_NAME(f) (RSTRING_PTR((f)->pathv))
4485
4486 static VALUE
4487 finish_writeconv(rb_io_t *fptr, int noalloc)
4488 {
4489 unsigned char *ds, *dp, *de;
4490 rb_econv_result_t res;
4491
4492 if (!fptr->wbuf.ptr) {
4493 unsigned char buf[1024];
4494 long r;
4495
4496 res = econv_destination_buffer_full;
4497 while (res == econv_destination_buffer_full) {
4498 ds = dp = buf;
4499 de = buf + sizeof(buf);
4500 res = rb_econv_convert(fptr->writeconv, NULL, NULL, &dp, de, 0);
4501 while (dp-ds) {
4502 retry:
4503 if (fptr->write_lock && rb_mutex_owned_p(fptr->write_lock))
4504 r = rb_write_internal2(fptr->fd, ds, dp-ds);
4505 else
4506 r = rb_write_internal(fptr->fd, ds, dp-ds);
4507 if (r == dp-ds)
4508 break;
4509 if (0 <= r) {
4510 ds += r;
4511 }
4512 if (rb_io_wait_writable(fptr->fd)) {
4513 if (fptr->fd < 0)
4514 return noalloc ? Qtrue : rb_exc_new3(rb_eIOError, rb_str_new_cstr(closed_stream));
4515 goto retry;
4516 }
4517 return noalloc ? Qtrue : INT2NUM(errno);
4518 }
4519 if (res == econv_invalid_byte_sequence ||
4520 res == econv_incomplete_input ||
4521 res == econv_undefined_conversion) {
4522 return noalloc ? Qtrue : rb_econv_make_exception(fptr->writeconv);
4523 }
4524 }
4525
4526 return Qnil;
4527 }
4528
4529 res = econv_destination_buffer_full;
4530 while (res == econv_destination_buffer_full) {
4531 if (fptr->wbuf.len == fptr->wbuf.capa) {
4532 if (io_fflush(fptr) < 0)
4533 return noalloc ? Qtrue : INT2NUM(errno);
4534 }
4535
4536 ds = dp = (unsigned char *)fptr->wbuf.ptr + fptr->wbuf.off + fptr->wbuf.len;
4537 de = (unsigned char *)fptr->wbuf.ptr + fptr->wbuf.capa;
4538 res = rb_econv_convert(fptr->writeconv, NULL, NULL, &dp, de, 0);
4539 fptr->wbuf.len += (int)(dp - ds);
4540 if (res == econv_invalid_byte_sequence ||
4541 res == econv_incomplete_input ||
4542 res == econv_undefined_conversion) {
4543 return noalloc ? Qtrue : rb_econv_make_exception(fptr->writeconv);
4544 }
4545 }
4546 return Qnil;
4547 }
4548
4549 struct finish_writeconv_arg {
4550 rb_io_t *fptr;
4551 int noalloc;
4552 };
4553
4554 static VALUE
4555 finish_writeconv_sync(VALUE arg)
4556 {
4557 struct finish_writeconv_arg *p = (struct finish_writeconv_arg *)arg;
4558 return finish_writeconv(p->fptr, p->noalloc);
4559 }
4560
4561 static void*
4562 nogvl_close(void *ptr)
4563 {
4564 int *fd = ptr;
4565
4566 return (void*)(intptr_t)close(*fd);
4567 }
4568
4569 static int
4570 maygvl_close(int fd, int keepgvl)
4571 {
4572 if (keepgvl)
4573 return close(fd);
4574
4575 /*
4576 * close() may block for certain file types (NFS, SO_LINGER sockets,
4577 * inotify), so let other threads run.
4578 */
4579 return (int)(intptr_t)rb_thread_call_without_gvl(nogvl_close, &fd, RUBY_UBF_IO, 0);
4580 }
4581
4582 static void*
4583 nogvl_fclose(void *ptr)
4584 {
4585 FILE *file = ptr;
4586
4587 return (void*)(intptr_t)fclose(file);
4588 }
4589
4590 static int
4591 maygvl_fclose(FILE *file, int keepgvl)
4592 {
4593 if (keepgvl)
4594 return fclose(file);
4595
4596 return (int)(intptr_t)rb_thread_call_without_gvl(nogvl_fclose, file, RUBY_UBF_IO, 0);
4597 }
4598
4599 static void free_io_buffer(rb_io_buffer_t *buf);
4600 static void clear_codeconv(rb_io_t *fptr);
4601
4602 static void
4603 fptr_finalize_flush(rb_io_t *fptr, int noraise, int keepgvl,
4604 struct list_head *busy)
4605 {
4606 VALUE err = Qnil;
4607 int fd = fptr->fd;
4608 FILE *stdio_file = fptr->stdio_file;
4609 int mode = fptr->mode;
4610
4611 if (fptr->writeconv) {
4612 if (fptr->write_lock && !noraise) {
4613 struct finish_writeconv_arg arg;
4614 arg.fptr = fptr;
4615 arg.noalloc = noraise;
4616 err = rb_mutex_synchronize(fptr->write_lock, finish_writeconv_sync, (VALUE)&arg);
4617 }
4618 else {
4619 err = finish_writeconv(fptr, noraise);
4620 }
4621 }
4622 if (fptr->wbuf.len) {
4623 if (noraise) {
4624 io_flush_buffer_sync(fptr);
4625 }
4626 else {
4627 if (io_fflush(fptr) < 0 && NIL_P(err))
4628 err = INT2NUM(errno);
4629 }
4630 }
4631
4632 fptr->fd = -1;
4633 fptr->stdio_file = 0;
4634 fptr->mode &= ~(FMODE_READABLE|FMODE_WRITABLE);
4635
4636 /*
4637 * ensure waiting_fd users do not hit EBADF, wait for them
4638 * to exit before we call close().
4639 */
4640 if (busy) {
4641 do rb_thread_schedule(); while (!list_empty(busy));
4642 }
4643
4644 if (IS_PREP_STDIO(fptr) || fd <= 2) {
4645 /* need to keep FILE objects of stdin, stdout and stderr */
4646 }
4647 else if (stdio_file) {
4648 /* stdio_file is deallocated anyway
4649 * even if fclose failed. */
4650 if ((maygvl_fclose(stdio_file, noraise) < 0) && NIL_P(err))
4651 if (!noraise) err = INT2NUM(errno);
4652 }
4653 else if (0 <= fd) {
4654 /* fptr->fd may be closed even if close fails.
4655 * POSIX doesn't specify it.
4656 * We assumes it is closed. */
4657
4658
4659 keepgvl |= !(mode & FMODE_WRITABLE);
4660 keepgvl |= noraise;
4661 if ((maygvl_close(fd, keepgvl) < 0) && NIL_P(err))
4662 if (!noraise) err = INT2NUM(errno);
4663 }
4664
4665 if (!NIL_P(err) && !noraise) {
4666 if (RB_INTEGER_TYPE_P(err))
4667 rb_syserr_fail_path(NUM2INT(err), fptr->pathv);
4668 else
4669 rb_exc_raise(err);
4670 }
4671 }
4672
4673 static void
4674 fptr_finalize(rb_io_t *fptr, int noraise)
4675 {
4676 fptr_finalize_flush(fptr, noraise, FALSE, 0);
4677 free_io_buffer(&fptr->rbuf);
4678 free_io_buffer(&fptr->wbuf);
4679 clear_codeconv(fptr);
4680 }
4681
4682 static void
4683 rb_io_fptr_cleanup(rb_io_t *fptr, int noraise)
4684 {
4685 if (fptr->finalize) {
4686 (*fptr->finalize)(fptr, noraise);
4687 }
4688 else {
4689 fptr_finalize(fptr, noraise);
4690 }
4691 }
4692
4693 static void
4694 free_io_buffer(rb_io_buffer_t *buf)
4695 {
4696 if (buf->ptr) {
4697 ruby_sized_xfree(buf->ptr, (size_t)buf->capa);
4698 buf->ptr = NULL;
4699 }
4700 }
4701
4702 static void
4703 clear_readconv(rb_io_t *fptr)
4704 {
4705 if (fptr->readconv) {
4706 rb_econv_close(fptr->readconv);
4707 fptr->readconv = NULL;
4708 }
4709 free_io_buffer(&fptr->cbuf);
4710 }
4711
4712 static void
4713 clear_writeconv(rb_io_t *fptr)
4714 {
4715 if (fptr->writeconv) {
4716 rb_econv_close(fptr->writeconv);
4717 fptr->writeconv = NULL;
4718 }
4719 fptr->writeconv_initialized = 0;
4720 }
4721
4722 static void
4723 clear_codeconv(rb_io_t *fptr)
4724 {
4725 clear_readconv(fptr);
4726 clear_writeconv(fptr);
4727 }
4728
4729 void
4730 rb_io_fptr_finalize_internal(void *ptr)
4731 {
4732 rb_io_t *fptr = ptr;
4733
4734 if (!ptr) return;
4735 fptr->pathv = Qnil;
4736 if (0 <= fptr->fd)
4737 rb_io_fptr_cleanup(fptr, TRUE);
4738 fptr->write_lock = 0;
4739 free_io_buffer(&fptr->rbuf);
4740 free_io_buffer(&fptr->wbuf);
4741 clear_codeconv(fptr);
4742 free(fptr);
4743 }
4744
4745 #undef rb_io_fptr_finalize
4746 int
4747 rb_io_fptr_finalize(rb_io_t *fptr)
4748 {
4749 if (!fptr) {
4750 return 0;
4751 }
4752 else {
4753 rb_io_fptr_finalize_internal(fptr);
4754 return 1;
4755 }
4756 }
4757 #define rb_io_fptr_finalize(fptr) rb_io_fptr_finalize_internal(fptr)
4758
4759 RUBY_FUNC_EXPORTED size_t
4760 rb_io_memsize(const rb_io_t *fptr)
4761 {
4762 size_t size = sizeof(rb_io_t);
4763 size += fptr->rbuf.capa;
4764 size += fptr->wbuf.capa;
4765 size += fptr->cbuf.capa;
4766 if (fptr->readconv) size += rb_econv_memsize(fptr->readconv);
4767 if (fptr->writeconv) size += rb_econv_memsize(fptr->writeconv);
4768 return size;
4769 }
4770
4771 #ifdef _WIN32
4772 /* keep GVL while closing to prevent crash on Windows */
4773 # define KEEPGVL TRUE
4774 #else
4775 # define KEEPGVL FALSE
4776 #endif
4777
4778 int rb_notify_fd_close(int fd, struct list_head *);
4779 static rb_io_t *
4780 io_close_fptr(VALUE io)
4781 {
4782 rb_io_t *fptr;
4783 VALUE write_io;
4784 rb_io_t *write_fptr;
4785 struct list_head busy;
4786
4787 list_head_init(&busy);
4788 write_io = GetWriteIO(io);
4789 if (io != write_io) {
4790 write_fptr = RFILE(write_io)->fptr;
4791 if (write_fptr && 0 <= write_fptr->fd) {
4792 rb_io_fptr_cleanup(write_fptr, TRUE);
4793 }
4794 }
4795
4796 fptr = RFILE(io)->fptr;
4797 if (!fptr) return 0;
4798 if (fptr->fd < 0) return 0;
4799
4800 if (rb_notify_fd_close(fptr->fd, &busy)) {
4801 /* calls close(fptr->fd): */
4802 fptr_finalize_flush(fptr, FALSE, KEEPGVL, &busy);
4803 }
4804 rb_io_fptr_cleanup(fptr, FALSE);
4805 return fptr;
4806 }
4807
4808 static void
4809 fptr_waitpid(rb_io_t *fptr, int nohang)
4810 {
4811 int status;
4812 if (fptr->pid) {
4813 rb_last_status_clear();
4814 rb_waitpid(fptr->pid, &status, nohang ? WNOHANG : 0);
4815 fptr->pid = 0;
4816 }
4817 }
4818
4819 VALUE
4820 rb_io_close(VALUE io)
4821 {
4822 rb_io_t *fptr = io_close_fptr(io);
4823 if (fptr) fptr_waitpid(fptr, 0);
4824 return Qnil;
4825 }
4826
4827 /*
4828 * call-seq:
4829 * ios.close -> nil
4830 *
4831 * Closes <em>ios</em> and flushes any pending writes to the operating
4832 * system. The stream is unavailable for any further data operations;
4833 * an IOError is raised if such an attempt is made. I/O streams are
4834 * automatically closed when they are claimed by the garbage collector.
4835 *
4836 * If <em>ios</em> is opened by IO.popen, #close sets
4837 * <code>$?</code>.
4838 *
4839 * Calling this method on closed IO object is just ignored since Ruby 2.3.
4840 */
4841
4842 static VALUE
4843 rb_io_close_m(VALUE io)
4844 {
4845 rb_io_t *fptr = rb_io_get_fptr(io);
4846 if (fptr->fd < 0) {
4847 return Qnil;
4848 }
4849 rb_io_close(io);
4850 return Qnil;
4851 }
4852
4853 static VALUE
4854 io_call_close(VALUE io)
4855 {
4856 rb_check_funcall(io, rb_intern("close"), 0, 0);
4857 return io;
4858 }
4859
4860 static VALUE
4861 ignore_closed_stream(VALUE io, VALUE exc)
4862 {
4863 enum {mesg_len = sizeof(closed_stream)-1};
4864 VALUE mesg = rb_attr_get(exc, idMesg);
4865 if (!RB_TYPE_P(mesg, T_STRING) ||
4866 RSTRING_LEN(mesg) != mesg_len ||
4867 memcmp(RSTRING_PTR(mesg), closed_stream, mesg_len)) {
4868 rb_exc_raise(exc);
4869 }
4870 return io;
4871 }
4872
4873 static VALUE
4874 io_close(VALUE io)
4875 {
4876 VALUE closed = rb_check_funcall(io, rb_intern("closed?"), 0, 0);
4877 if (closed != Qundef && RTEST(closed)) return io;
4878 rb_rescue2(io_call_close, io, ignore_closed_stream, io,
4879 rb_eIOError, (VALUE)0);
4880 return io;
4881 }
4882
4883 /*
4884 * call-seq:
4885 * ios.closed? -> true or false
4886 *
4887 * Returns <code>true</code> if <em>ios</em> is completely closed (for
4888 * duplex streams, both reader and writer), <code>false</code>
4889 * otherwise.
4890 *
4891 * f = File.new("testfile")
4892 * f.close #=> nil
4893 * f.closed? #=> true
4894 * f = IO.popen("/bin/sh","r+")
4895 * f.close_write #=> nil
4896 * f.closed? #=> false
4897 * f.close_read #=> nil
4898 * f.closed? #=> true
4899 */
4900
4901
4902 static VALUE
4903 rb_io_closed(VALUE io)
4904 {
4905 rb_io_t *fptr;
4906 VALUE write_io;
4907 rb_io_t *write_fptr;
4908
4909 write_io = GetWriteIO(io);
4910 if (io != write_io) {
4911 write_fptr = RFILE(write_io)->fptr;
4912 if (write_fptr && 0 <= write_fptr->fd) {
4913 return Qfalse;
4914 }
4915 }
4916
4917 fptr = rb_io_get_fptr(io);
4918 return 0 <= fptr->fd ? Qfalse : Qtrue;
4919 }
4920
4921 /*
4922 * call-seq:
4923 * ios.close_read -> nil
4924 *
4925 * Closes the read end of a duplex I/O stream (i.e., one that contains
4926 * both a read and a write stream, such as a pipe). Will raise an
4927 * IOError if the stream is not duplexed.
4928 *
4929 * f = IO.popen("/bin/sh","r+")
4930 * f.close_read
4931 * f.readlines
4932 *
4933 * <em>produces:</em>
4934 *
4935 * prog.rb:3:in `readlines': not opened for reading (IOError)
4936 * from prog.rb:3
4937 *
4938 * Calling this method on closed IO object is just ignored since Ruby 2.3.
4939 */
4940
4941 static VALUE
4942 rb_io_close_read(VALUE io)
4943 {
4944 rb_io_t *fptr;
4945 VALUE write_io;
4946
4947 fptr = rb_io_get_fptr(rb_io_taint_check(io));
4948 if (fptr->fd < 0) return Qnil;
4949 if (is_socket(fptr->fd, fptr->pathv)) {
4950 #ifndef SHUT_RD
4951 # define SHUT_RD 0
4952 #endif
4953 if (shutdown(fptr->fd, SHUT_RD) < 0)
4954 rb_sys_fail_path(fptr->pathv);
4955 fptr->mode &= ~FMODE_READABLE;
4956 if (!(fptr->mode & FMODE_WRITABLE))
4957 return rb_io_close(io);
4958 return Qnil;
4959 }
4960
4961 write_io = GetWriteIO(io);
4962 if (io != write_io) {
4963 rb_io_t *wfptr;
4964 wfptr = rb_io_get_fptr(rb_io_taint_check(write_io));
4965 wfptr->pid = fptr->pid;
4966 fptr->pid = 0;
4967 RFILE(io)->fptr = wfptr;
4968 /* bind to write_io temporarily to get rid of memory/fd leak */
4969 fptr->tied_io_for_writing = 0;
4970 RFILE(write_io)->fptr = fptr;
4971 rb_io_fptr_cleanup(fptr, FALSE);
4972 /* should not finalize fptr because another thread may be reading it */
4973 return Qnil;
4974 }
4975
4976 if ((fptr->mode & (FMODE_DUPLEX|FMODE_WRITABLE)) == FMODE_WRITABLE) {
4977 rb_raise(rb_eIOError, "closing non-duplex IO for reading");
4978 }
4979 return rb_io_close(io);
4980 }
4981
4982 /*
4983 * call-seq:
4984 * ios.close_write -> nil
4985 *
4986 * Closes the write end of a duplex I/O stream (i.e., one that contains
4987 * both a read and a write stream, such as a pipe). Will raise an
4988 * IOError if the stream is not duplexed.
4989 *
4990 * f = IO.popen("/bin/sh","r+")
4991 * f.close_write
4992 * f.print "nowhere"
4993 *
4994 * <em>produces:</em>
4995 *
4996 * prog.rb:3:in `write': not opened for writing (IOError)
4997 * from prog.rb:3:in `print'
4998 * from prog.rb:3
4999 *
5000 * Calling this method on closed IO object is just ignored since Ruby 2.3.
5001 */
5002
5003 static VALUE
5004 rb_io_close_write(VALUE io)
5005 {
5006 rb_io_t *fptr;
5007 VALUE write_io;
5008
5009 write_io = GetWriteIO(io);
5010 fptr = rb_io_get_fptr(rb_io_taint_check(write_io));
5011 if (fptr->fd < 0) return Qnil;
5012 if (is_socket(fptr->fd, fptr->pathv)) {
5013 #ifndef SHUT_WR
5014 # define SHUT_WR 1
5015 #endif
5016 if (shutdown(fptr->fd, SHUT_WR) < 0)
5017 rb_sys_fail_path(fptr->pathv);
5018 fptr->mode &= ~FMODE_WRITABLE;
5019 if (!(fptr->mode & FMODE_READABLE))
5020 return rb_io_close(write_io);
5021 return Qnil;
5022 }
5023
5024 if ((fptr->mode & (FMODE_DUPLEX|FMODE_READABLE)) == FMODE_READABLE) {
5025 rb_raise(rb_eIOError, "closing non-duplex IO for writing");
5026 }
5027
5028 if (io != write_io) {
5029 fptr = rb_io_get_fptr(rb_io_taint_check(io));
5030 fptr->tied_io_for_writing = 0;
5031 }
5032 rb_io_close(write_io);
5033 return Qnil;
5034 }
5035
5036 /*
5037 * call-seq:
5038 * ios.sysseek(offset, whence=IO::SEEK_SET) -> integer
5039 *
5040 * Seeks to a given <i>offset</i> in the stream according to the value
5041 * of <i>whence</i> (see IO#seek for values of <i>whence</i>). Returns
5042 * the new offset into the file.
5043 *
5044 * f = File.new("testfile")
5045 * f.sysseek(-13, IO::SEEK_END) #=> 53
5046 * f.sysread(10) #=> "And so on."
5047 */
5048
5049 static VALUE
5050 rb_io_sysseek(int argc, VALUE *argv, VALUE io)
5051 {
5052 VALUE offset, ptrname;
5053 int whence = SEEK_SET;
5054 rb_io_t *fptr;
5055 off_t pos;
5056
5057 if (rb_scan_args(argc, argv, "11", &offset, &ptrname) == 2) {
5058 whence = interpret_seek_whence(ptrname);
5059 }
5060 pos = NUM2OFFT(offset);
5061 GetOpenFile(io, fptr);
5062 if ((fptr->mode & FMODE_READABLE) &&
5063 (READ_DATA_BUFFERED(fptr) || READ_CHAR_PENDING(fptr))) {
5064 rb_raise(rb_eIOError, "sysseek for buffered IO");
5065 }
5066 if ((fptr->mode & FMODE_WRITABLE) && fptr->wbuf.len) {
5067 rb_warn("sysseek for buffered IO");
5068 }
5069 errno = 0;
5070 pos = lseek(fptr->fd, pos, whence);
5071 if (pos < 0 && errno) rb_sys_fail_path(fptr->pathv);
5072
5073 return OFFT2NUM(pos);
5074 }
5075
5076 /*
5077 * call-seq:
5078 * ios.syswrite(string) -> integer
5079 *
5080 * Writes the given string to <em>ios</em> using a low-level write.
5081 * Returns the number of bytes written. Do not mix with other methods
5082 * that write to <em>ios</em> or you may get unpredictable results.
5083 * Raises SystemCallError on error.
5084 *
5085 * f = File.new("out", "w")
5086 * f.syswrite("ABCDEF") #=> 6
5087 */
5088
5089 static VALUE
5090 rb_io_syswrite(VALUE io, VALUE str)
5091 {
5092 VALUE tmp;
5093 rb_io_t *fptr;
5094 long n, len;
5095 const char *ptr;
5096
5097 if (!RB_TYPE_P(str, T_STRING))
5098 str = rb_obj_as_string(str);
5099
5100 io = GetWriteIO(io);
5101 GetOpenFile(io, fptr);
5102 rb_io_check_writable(fptr);
5103
5104 if (fptr->wbuf.len) {
5105 rb_warn("syswrite for buffered IO");
5106 }
5107
5108 tmp = rb_str_tmp_frozen_acquire(str);
5109 RSTRING_GETMEM(tmp, ptr, len);
5110 n = rb_write_internal(fptr->fd, ptr, len);
5111 if (n < 0) rb_sys_fail_path(fptr->pathv);
5112 rb_str_tmp_frozen_release(str, tmp);
5113
5114 return LONG2FIX(n);
5115 }
5116
5117 /*
5118 * call-seq:
5119 * ios.sysread(maxlen[, outbuf]) -> string
5120 *
5121 * Reads <i>maxlen</i> bytes from <em>ios</em> using a low-level
5122 * read and returns them as a string. Do not mix with other methods
5123 * that read from <em>ios</em> or you may get unpredictable results.
5124 *
5125 * If the optional _outbuf_ argument is present,
5126 * it must reference a String, which will receive the data.
5127 * The _outbuf_ will contain only the received data after the method call
5128 * even if it is not empty at the beginning.
5129 *
5130 * Raises SystemCallError on error and EOFError at end of file.
5131 *
5132 * f = File.new("testfile")
5133 * f.sysread(16) #=> "This is line one"
5134 */
5135
5136 static VALUE
5137 rb_io_sysread(int argc, VALUE *argv, VALUE io)
5138 {
5139 VALUE len, str;
5140 rb_io_t *fptr;
5141 long n, ilen;
5142 struct io_internal_read_struct iis;
5143 int shrinkable;
5144
5145 rb_scan_args(argc, argv, "11", &len, &str);
5146 ilen = NUM2LONG(len);
5147
5148 shrinkable = io_setstrbuf(&str, ilen);
5149 if (ilen == 0) return str;
5150
5151 GetOpenFile(io, fptr);
5152 rb_io_check_byte_readable(fptr);
5153
5154 if (READ_DATA_BUFFERED(fptr)) {
5155 rb_raise(rb_eIOError, "sysread for buffered IO");
5156 }
5157
5158 /*
5159 * FIXME: removing rb_thread_wait_fd() here changes sysread semantics
5160 * on non-blocking IOs. However, it's still currently possible
5161 * for sysread to raise Errno::EAGAIN if another thread read()s
5162 * the IO after we return from rb_thread_wait_fd() but before
5163 * we call read()
5164 */
5165 rb_thread_wait_fd(fptr->fd);
5166
5167 rb_io_check_closed(fptr);
5168
5169 io_setstrbuf(&str, ilen);
5170 iis.fd = fptr->fd;
5171 iis.nonblock = 1; /* for historical reasons, maybe (see above) */
5172 iis.buf = RSTRING_PTR(str);
5173 iis.capa = ilen;
5174 n = read_internal_locktmp(str, &iis);
5175
5176 if (n < 0) {
5177 rb_sys_fail_path(fptr->pathv);
5178 }
5179 io_set_read_length(str, n, shrinkable);
5180 if (n == 0 && ilen > 0) {
5181 rb_eof_error();
5182 }
5183
5184 return str;
5185 }
5186
5187 #if defined(HAVE_PREAD) || defined(HAVE_PWRITE)
5188 struct prdwr_internal_arg {
5189 int fd;
5190 void *buf;
5191 size_t count;
5192 off_t offset;
5193 };
5194 #endif /* HAVE_PREAD || HAVE_PWRITE */
5195
5196 #if defined(HAVE_PREAD)
5197 static VALUE
5198 internal_pread_func(void *arg)
5199 {
5200 struct prdwr_internal_arg *p = arg;
5201 return (VALUE)pread(p->fd, p->buf, p->count, p->offset);
5202 }
5203
5204 static VALUE
5205 pread_internal_call(VALUE arg)
5206 {
5207 struct prdwr_internal_arg *p = (struct prdwr_internal_arg *)arg;
5208 return rb_thread_io_blocking_region(internal_pread_func, p, p->fd);
5209 }
5210
5211 /*
5212 * call-seq:
5213 * ios.pread(maxlen, offset[, outbuf]) -> string
5214 *
5215 * Reads <i>maxlen</i> bytes from <em>ios</em> using the pread system call
5216 * and returns them as a string without modifying the underlying
5217 * descriptor offset. This is advantageous compared to combining IO#seek
5218 * and IO#read in that it is atomic, allowing multiple threads/process to
5219 * share the same IO object for reading the file at various locations.
5220 * This bypasses any userspace buffering of the IO layer.
5221 * If the optional <i>outbuf</i> argument is present, it must
5222 * reference a String, which will receive the data.
5223 * Raises SystemCallError on error, EOFError at end of file and
5224 * NotImplementedError if platform does not implement the system call.
5225 *
5226 * File.write("testfile", "This is line one\nThis is line two\n")
5227 * File.open("testfile") do |f|
5228 * p f.read # => "This is line one\nThis is line two\n"
5229 * p f.pread(12, 0) # => "This is line"
5230 * p f.pread(9, 8) # => "line one\n"
5231 * end
5232 */
5233 static VALUE
5234 rb_io_pread(int argc, VALUE *argv, VALUE io)
5235 {
5236 VALUE len, offset, str;
5237 rb_io_t *fptr;
5238 ssize_t n;
5239 struct prdwr_internal_arg arg;
5240 int shrinkable;
5241
5242 rb_scan_args(argc, argv, "21", &len, &offset, &str);
5243 arg.count = NUM2SIZET(len);
5244 arg.offset = NUM2OFFT(offset);
5245
5246 shrinkable = io_setstrbuf(&str, (long)arg.count);
5247 if (arg.count == 0) return str;
5248 arg.buf = RSTRING_PTR(str);
5249
5250 GetOpenFile(io, fptr);
5251 rb_io_check_byte_readable(fptr);
5252
5253 arg.fd = fptr->fd;
5254 rb_io_check_closed(fptr);
5255
5256 rb_str_locktmp(str);
5257 n = (ssize_t)rb_ensure(pread_internal_call, (VALUE)&arg, rb_str_unlocktmp, str);
5258
5259 if (n < 0) {
5260 rb_sys_fail_path(fptr->pathv);
5261 }
5262 io_set_read_length(str, n, shrinkable);
5263 if (n == 0 && arg.count > 0) {
5264 rb_eof_error();
5265 }
5266
5267 return str;
5268 }
5269 #else
5270 # define rb_io_pread rb_f_notimplement
5271 #endif /* HAVE_PREAD */
5272
5273 #if defined(HAVE_PWRITE)
5274 static VALUE
5275 internal_pwrite_func(void *ptr)
5276 {
5277 struct prdwr_internal_arg *arg = ptr;
5278
5279 return (VALUE)pwrite(arg->fd, arg->buf, arg->count, arg->offset);
5280 }
5281
5282 /*
5283 * call-seq:
5284 * ios.pwrite(string, offset) -> integer
5285 *
5286 * Writes the given string to <em>ios</em> at <i>offset</i> using pwrite()
5287 * system call. This is advantageous to combining IO#seek and IO#write
5288 * in that it is atomic, allowing multiple threads/process to share the
5289 * same IO object for reading the file at various locations.
5290 * This bypasses any userspace buffering of the IO layer.
5291 * Returns the number of bytes written.
5292 * Raises SystemCallError on error and NotImplementedError
5293 * if platform does not implement the system call.
5294 *
5295 * File.open("out", "w") do |f|
5296 * f.pwrite("ABCDEF", 3) #=> 6
5297 * end
5298 *
5299 * File.read("out") #=> "\u0000\u0000\u0000ABCDEF"
5300 */
5301 static VALUE
5302 rb_io_pwrite(VALUE io, VALUE str, VALUE offset)
5303 {
5304 rb_io_t *fptr;
5305 ssize_t n;
5306 struct prdwr_internal_arg arg;
5307 VALUE tmp;
5308
5309 if (!RB_TYPE_P(str, T_STRING))
5310 str = rb_obj_as_string(str);
5311
5312 arg.offset = NUM2OFFT(offset);
5313
5314 io = GetWriteIO(io);
5315 GetOpenFile(io, fptr);
5316 rb_io_check_writable(fptr);
5317 arg.fd = fptr->fd;
5318
5319 tmp = rb_str_tmp_frozen_acquire(str);
5320 arg.buf = RSTRING_PTR(tmp);
5321 arg.count = (size_t)RSTRING_LEN(tmp);
5322
5323 n = (ssize_t)rb_thread_io_blocking_region(internal_pwrite_func, &arg, fptr->fd);
5324 if (n < 0) rb_sys_fail_path(fptr->pathv);
5325 rb_str_tmp_frozen_release(str, tmp);
5326
5327 return SSIZET2NUM(n);
5328 }
5329 #else
5330 # define rb_io_pwrite rb_f_notimplement
5331 #endif /* HAVE_PWRITE */
5332
5333 VALUE
5334 rb_io_binmode(VALUE io)
5335 {
5336 rb_io_t *fptr;
5337
5338 GetOpenFile(io, fptr);
5339 if (fptr->readconv)
5340 rb_econv_binmode(fptr->readconv);
5341 if (fptr->writeconv)
5342 rb_econv_binmode(fptr->writeconv);
5343 fptr->mode |= FMODE_BINMODE;
5344 fptr->mode &= ~FMODE_TEXTMODE;
5345 fptr->writeconv_pre_ecflags &= ~ECONV_NEWLINE_DECORATOR_MASK;
5346 #ifdef O_BINARY
5347 if (!fptr->readconv) {
5348 SET_BINARY_MODE_WITH_SEEK_CUR(fptr);
5349 }
5350 else {
5351 setmode(fptr->fd, O_BINARY);
5352 }
5353 #endif
5354 return io;
5355 }
5356
5357 static void
5358 io_ascii8bit_binmode(rb_io_t *fptr)
5359 {
5360 if (fptr->readconv) {
5361 rb_econv_close(fptr->readconv);
5362 fptr->readconv = NULL;
5363 }
5364 if (fptr->writeconv) {
5365 rb_econv_close(fptr->writeconv);
5366 fptr->writeconv = NULL;
5367 }
5368 fptr->mode |= FMODE_BINMODE;
5369 fptr->mode &= ~FMODE_TEXTMODE;
5370 SET_BINARY_MODE_WITH_SEEK_CUR(fptr);
5371
5372 fptr->encs.enc = rb_ascii8bit_encoding();
5373 fptr->encs.enc2 = NULL;
5374 fptr->encs.ecflags = 0;
5375 fptr->encs.ecopts = Qnil;
5376 clear_codeconv(fptr);
5377 }
5378
5379 VALUE
5380 rb_io_ascii8bit_binmode(VALUE io)
5381 {
5382 rb_io_t *fptr;
5383
5384 GetOpenFile(io, fptr);
5385 io_ascii8bit_binmode(fptr);
5386
5387 return io;
5388 }
5389
5390 /*
5391 * call-seq:
5392 * ios.binmode -> ios
5393 *
5394 * Puts <em>ios</em> into binary mode.
5395 * Once a stream is in binary mode, it cannot be reset to nonbinary mode.
5396 *
5397 * - newline conversion disabled
5398 * - encoding conversion disabled
5399 * - content is treated as ASCII-8BIT
5400 */
5401
5402 static VALUE
5403 rb_io_binmode_m(VALUE io)
5404 {
5405 VALUE write_io;
5406
5407 rb_io_ascii8bit_binmode(io);
5408
5409 write_io = GetWriteIO(io);
5410 if (write_io != io)
5411 rb_io_ascii8bit_binmode(write_io);
5412 return io;
5413 }
5414
5415 /*
5416 * call-seq:
5417 * ios.binmode? -> true or false
5418 *
5419 * Returns <code>true</code> if <em>ios</em> is binmode.
5420 */
5421 static VALUE
5422 rb_io_binmode_p(VALUE io)
5423 {
5424 rb_io_t *fptr;
5425 GetOpenFile(io, fptr);
5426 return fptr->mode & FMODE_BINMODE ? Qtrue : Qfalse;
5427 }
5428
5429 static const char*
5430 rb_io_fmode_modestr(int fmode)
5431 {
5432 if (fmode & FMODE_APPEND) {
5433 if ((fmode & FMODE_READWRITE) == FMODE_READWRITE) {
5434 return MODE_BTMODE("a+", "ab+", "at+");
5435 }
5436 return MODE_BTMODE("a", "ab", "at");
5437 }
5438 switch (fmode & FMODE_READWRITE) {
5439 default:
5440 rb_raise(rb_eArgError, "invalid access fmode 0x%x", fmode);
5441 case FMODE_READABLE:
5442 return MODE_BTMODE("r", "rb", "rt");
5443 case FMODE_WRITABLE:
5444 return MODE_BTXMODE("w", "wb", "wt", "wx", "wbx", "wtx");
5445 case FMODE_READWRITE:
5446 if (fmode & FMODE_CREATE) {
5447 return MODE_BTXMODE("w+", "wb+", "wt+", "w+x", "wb+x", "wt+x");
5448 }
5449 return MODE_BTMODE("r+", "rb+", "rt+");
5450 }
5451 }
5452
5453 static const char bom_prefix[] = "bom|";
5454 static const char utf_prefix[] = "utf-";
5455 enum {bom_prefix_len = (int)sizeof(bom_prefix) - 1};
5456 enum {utf_prefix_len = (int)sizeof(utf_prefix) - 1};
5457
5458 static int
5459 io_encname_bom_p(const char *name, long len)
5460 {
5461 return len > bom_prefix_len && STRNCASECMP(name, bom_prefix, bom_prefix_len) == 0;
5462 }
5463
5464 int
5465 rb_io_modestr_fmode(const char *modestr)
5466 {
5467 int fmode = 0;
5468 const char *m = modestr, *p = NULL;
5469
5470 switch (*m++) {
5471 case 'r':
5472 fmode |= FMODE_READABLE;
5473 break;
5474 case 'w':
5475 fmode |= FMODE_WRITABLE | FMODE_TRUNC | FMODE_CREATE;
5476 break;
5477 case 'a':
5478 fmode |= FMODE_WRITABLE | FMODE_APPEND | FMODE_CREATE;
5479 break;
5480 default:
5481 error:
5482 rb_raise(rb_eArgError, "invalid access mode %s", modestr);
5483 }
5484
5485 while (*m) {
5486 switch (*m++) {
5487 case 'b':
5488 fmode |= FMODE_BINMODE;
5489 break;
5490 case 't':
5491 fmode |= FMODE_TEXTMODE;
5492 break;
5493 case '+':
5494 fmode |= FMODE_READWRITE;
5495 break;
5496 case 'x':
5497 if (modestr[0] != 'w')
5498 goto error;
5499 fmode |= FMODE_EXCL;
5500 break;
5501 default:
5502 goto error;
5503 case ':':
5504 p = strchr(m, ':');
5505 if (io_encname_bom_p(m, p ? (long)(p - m) : (long)strlen(m)))
5506 fmode |= FMODE_SETENC_BY_BOM;
5507 goto finished;
5508 }
5509 }
5510
5511 finished:
5512 if ((fmode & FMODE_BINMODE) && (fmode & FMODE_TEXTMODE))
5513 goto error;
5514
5515 return fmode;
5516 }
5517
5518 int
5519 rb_io_oflags_fmode(int oflags)
5520 {
5521 int fmode = 0;
5522
5523 switch (oflags & O_ACCMODE) {
5524 case O_RDONLY:
5525 fmode = FMODE_READABLE;
5526 break;
5527 case O_WRONLY:
5528 fmode = FMODE_WRITABLE;
5529 break;
5530 case O_RDWR:
5531 fmode = FMODE_READWRITE;
5532 break;
5533 }
5534
5535 if (oflags & O_APPEND) {
5536 fmode |= FMODE_APPEND;
5537 }
5538 if (oflags & O_TRUNC) {
5539 fmode |= FMODE_TRUNC;
5540 }
5541 if (oflags & O_CREAT) {
5542 fmode |= FMODE_CREATE;
5543 }
5544 if (oflags & O_EXCL) {
5545 fmode |= FMODE_EXCL;
5546 }
5547 #ifdef O_BINARY
5548 if (oflags & O_BINARY) {
5549 fmode |= FMODE_BINMODE;
5550 }
5551 #endif
5552
5553 return fmode;
5554 }
5555
5556 static int
5557 rb_io_fmode_oflags(int fmode)
5558 {
5559 int oflags = 0;
5560
5561 switch (fmode & FMODE_READWRITE) {
5562 case FMODE_READABLE:
5563 oflags |= O_RDONLY;
5564 break;
5565 case FMODE_WRITABLE:
5566 oflags |= O_WRONLY;
5567 break;
5568 case FMODE_READWRITE:
5569 oflags |= O_RDWR;
5570 break;
5571 }
5572
5573 if (fmode & FMODE_APPEND) {
5574 oflags |= O_APPEND;
5575 }
5576 if (fmode & FMODE_TRUNC) {
5577 oflags |= O_TRUNC;
5578 }
5579 if (fmode & FMODE_CREATE) {
5580 oflags |= O_CREAT;
5581 }
5582 if (fmode & FMODE_EXCL) {
5583 oflags |= O_EXCL;
5584 }
5585 #ifdef O_BINARY
5586 if (fmode & FMODE_BINMODE) {
5587 oflags |= O_BINARY;
5588 }
5589 #endif
5590
5591 return oflags;
5592 }
5593
5594 int
5595 rb_io_modestr_oflags(const char *modestr)
5596 {
5597 return rb_io_fmode_oflags(rb_io_modestr_fmode(modestr));
5598 }
5599
5600 static const char*
5601 rb_io_oflags_modestr(int oflags)
5602 {
5603 #ifdef O_BINARY
5604 # define MODE_BINARY(a,b) ((oflags & O_BINARY) ? (b) : (a))
5605 #else
5606 # define MODE_BINARY(a,b) (a)
5607 #endif
5608 int accmode;
5609 if (oflags & O_EXCL) {
5610 rb_raise(rb_eArgError, "exclusive access mode is not supported");
5611 }
5612 accmode = oflags & (O_RDONLY|O_WRONLY|O_RDWR);
5613 if (oflags & O_APPEND) {
5614 if (accmode == O_WRONLY) {
5615 return MODE_BINARY("a", "ab");
5616 }
5617 if (accmode == O_RDWR) {
5618 return MODE_BINARY("a+", "ab+");
5619 }
5620 }
5621 switch (accmode) {
5622 default:
5623 rb_raise(rb_eArgError, "invalid access oflags 0x%x", oflags);
5624 case O_RDONLY:
5625 return MODE_BINARY("r", "rb");
5626 case O_WRONLY:
5627 return MODE_BINARY("w", "wb");
5628 case O_RDWR:
5629 if (oflags & O_TRUNC) {
5630 return MODE_BINARY("w+", "wb+");
5631 }
5632 return MODE_BINARY("r+", "rb+");
5633 }
5634 }
5635
5636 /*
5637 * Convert external/internal encodings to enc/enc2
5638 * NULL => use default encoding
5639 * Qnil => no encoding specified (internal only)
5640 */
5641 static void
5642 rb_io_ext_int_to_encs(rb_encoding *ext, rb_encoding *intern, rb_encoding **enc, rb_encoding **enc2, int fmode)
5643 {
5644 int default_ext = 0;
5645
5646 if (ext == NULL) {
5647 ext = rb_default_external_encoding();
5648 default_ext = 1;
5649 }
5650 if (ext == rb_ascii8bit_encoding()) {
5651 /* If external is ASCII-8BIT, no transcoding */
5652 intern = NULL;
5653 }
5654 else if (intern == NULL) {
5655 intern = rb_default_internal_encoding();
5656 }
5657 if (intern == NULL || intern == (rb_encoding *)Qnil ||
5658 (!(fmode & FMODE_SETENC_BY_BOM) && (intern == ext))) {
5659 /* No internal encoding => use external + no transcoding */
5660 *enc = (default_ext && intern != ext) ? NULL : ext;
5661 *enc2 = NULL;
5662 }
5663 else {
5664 *enc = intern;
5665 *enc2 = ext;
5666 }
5667 }
5668
5669 static void
5670 unsupported_encoding(const char *name, rb_encoding *enc)
5671 {
5672 rb_enc_warn(enc, "Unsupported encoding %s ignored", name);
5673 }
5674
5675 static void
5676 parse_mode_enc(const char *estr, rb_encoding *estr_enc,
5677 rb_encoding **enc_p, rb_encoding **enc2_p, int *fmode_p)
5678 {
5679 const char *p;
5680 char encname[ENCODING_MAXNAMELEN+1];
5681 int idx, idx2;
5682 int fmode = fmode_p ? *fmode_p : 0;
5683 rb_encoding *ext_enc, *int_enc;
5684 long len;
5685
5686 /* parse estr as "enc" or "enc2:enc" or "enc:-" */
5687
5688 p = strrchr(estr, ':');
5689 len = p ? (p++ - estr) : (long)strlen(estr);
5690 if ((fmode & FMODE_SETENC_BY_BOM) || io_encname_bom_p(estr, len)) {
5691 estr += bom_prefix_len;
5692 len -= bom_prefix_len;
5693 if (!STRNCASECMP(estr, utf_prefix, utf_prefix_len)) {
5694 fmode |= FMODE_SETENC_BY_BOM;
5695 }
5696 else {
5697 rb_enc_warn(estr_enc, "BOM with non-UTF encoding %s is nonsense", estr);
5698 fmode &= ~FMODE_SETENC_BY_BOM;
5699 }
5700 }
5701 if (len == 0 || len > ENCODING_MAXNAMELEN) {
5702 idx = -1;
5703 }
5704 else {
5705 if (p) {
5706 memcpy(encname, estr, len);
5707 encname[len] = '\0';
5708 estr = encname;
5709 }
5710 idx = rb_enc_find_index(estr);
5711 }
5712 if (fmode_p) *fmode_p = fmode;
5713
5714 if (idx >= 0)
5715 ext_enc = rb_enc_from_index(idx);
5716 else {
5717 if (idx != -2)
5718 unsupported_encoding(estr, estr_enc);
5719 ext_enc = NULL;
5720 }
5721
5722 int_enc = NULL;
5723 if (p) {
5724 if (*p == '-' && *(p+1) == '\0') {
5725 /* Special case - "-" => no transcoding */
5726 int_enc = (rb_encoding *)Qnil;
5727 }
5728 else {
5729 idx2 = rb_enc_find_index(p);
5730 if (idx2 < 0)
5731 unsupported_encoding(p, estr_enc);
5732 else if (!(fmode & FMODE_SETENC_BY_BOM) && (idx2 == idx)) {
5733 int_enc = (rb_encoding *)Qnil;
5734 }
5735 else
5736 int_enc = rb_enc_from_index(idx2);
5737 }
5738 }
5739
5740 rb_io_ext_int_to_encs(ext_enc, int_enc, enc_p, enc2_p, fmode);
5741 }
5742
5743 int
5744 rb_io_extract_encoding_option(VALUE opt, rb_encoding **enc_p, rb_encoding **enc2_p, int *fmode_p)
5745 {
5746 VALUE encoding=Qnil, extenc=Qundef, intenc=Qundef, tmp;
5747 int extracted = 0;
5748 rb_encoding *extencoding = NULL;
5749 rb_encoding *intencoding = NULL;
5750
5751 if (!NIL_P(opt)) {
5752 VALUE v;
5753 v = rb_hash_lookup2(opt, sym_encoding, Qnil);
5754 if (v != Qnil) encoding = v;
5755 v = rb_hash_lookup2(opt, sym_extenc, Qundef);
5756 if (v != Qnil) extenc = v;
5757 v = rb_hash_lookup2(opt, sym_intenc, Qundef);
5758 if (v != Qundef) intenc = v;
5759 }
5760 if ((extenc != Qundef || intenc != Qundef) && !NIL_P(encoding)) {
5761 if (!NIL_P(ruby_verbose)) {
5762 int idx = rb_to_encoding_index(encoding);
5763 if (idx >= 0) encoding = rb_enc_from_encoding(rb_enc_from_index(idx));
5764 rb_warn("Ignoring encoding parameter '%"PRIsVALUE"': %s_encoding is used",
5765 encoding, extenc == Qundef ? "internal" : "external");
5766 }
5767 encoding = Qnil;
5768 }
5769 if (extenc != Qundef && !NIL_P(extenc)) {
5770 extencoding = rb_to_encoding(extenc);
5771 }
5772 if (intenc != Qundef) {
5773 if (NIL_P(intenc)) {
5774 /* internal_encoding: nil => no transcoding */
5775 intencoding = (rb_encoding *)Qnil;
5776 }
5777 else if (!NIL_P(tmp = rb_check_string_type(intenc))) {
5778 char *p = StringValueCStr(tmp);
5779
5780 if (*p == '-' && *(p+1) == '\0') {
5781 /* Special case - "-" => no transcoding */
5782 intencoding = (rb_encoding *)Qnil;
5783 }
5784 else {
5785 intencoding = rb_to_encoding(intenc);
5786 }
5787 }
5788 else {
5789 intencoding = rb_to_encoding(intenc);
5790 }
5791 if (extencoding == intencoding) {
5792 intencoding = (rb_encoding *)Qnil;
5793 }
5794 }
5795 if (!NIL_P(encoding)) {
5796 extracted = 1;
5797 if (!NIL_P(tmp = rb_check_string_type(encoding))) {
5798 parse_mode_enc(StringValueCStr(tmp), rb_enc_get(tmp),
5799 enc_p, enc2_p, fmode_p);
5800 }
5801 else {
5802 rb_io_ext_int_to_encs(rb_to_encoding(encoding), NULL, enc_p, enc2_p, 0);
5803 }
5804 }
5805 else if (extenc != Qundef || intenc != Qundef) {
5806 extracted = 1;
5807 rb_io_ext_int_to_encs(extencoding, intencoding, enc_p, enc2_p, 0);
5808 }
5809 return extracted;
5810 }
5811
5812 typedef struct rb_io_enc_t convconfig_t;
5813
5814 static void
5815 validate_enc_binmode(int *fmode_p, int ecflags, rb_encoding *enc, rb_encoding *enc2)
5816 {
5817 int fmode = *fmode_p;
5818
5819 if ((fmode & FMODE_READABLE) &&
5820 !enc2 &&
5821 !(fmode & FMODE_BINMODE) &&
5822 !rb_enc_asciicompat(enc ? enc : rb_default_external_encoding()))
5823 rb_raise(rb_eArgError, "ASCII incompatible encoding needs binmode");
5824
5825 if ((fmode & FMODE_BINMODE) && (ecflags & ECONV_NEWLINE_DECORATOR_MASK)) {
5826 rb_raise(rb_eArgError, "newline decorator with binary mode");
5827 }
5828 if (!(fmode & FMODE_BINMODE) &&
5829 (DEFAULT_TEXTMODE || (ecflags & ECONV_NEWLINE_DECORATOR_MASK))) {
5830 fmode |= FMODE_TEXTMODE;
5831 *fmode_p = fmode;
5832 }
5833 #if !DEFAULT_TEXTMODE
5834 else if (!(ecflags & ECONV_NEWLINE_DECORATOR_MASK)) {
5835 fmode &= ~FMODE_TEXTMODE;
5836 *fmode_p = fmode;
5837 }
5838 #endif
5839 }
5840
5841 static void
5842 extract_binmode(VALUE opthash, int *fmode)
5843 {
5844 if (!NIL_P(opthash)) {
5845 VALUE v;
5846 v = rb_hash_aref(opthash, sym_textmode);
5847 if (!NIL_P(v)) {
5848 if (*fmode & FMODE_TEXTMODE)
5849 rb_raise(rb_eArgError, "textmode specified twice");
5850 if (*fmode & FMODE_BINMODE)
5851 rb_raise(rb_eArgError, "both textmode and binmode specified");
5852 if (RTEST(v))
5853 *fmode |= FMODE_TEXTMODE;
5854 }
5855 v = rb_hash_aref(opthash, sym_binmode);
5856 if (!NIL_P(v)) {
5857 if (*fmode & FMODE_BINMODE)
5858 rb_raise(rb_eArgError, "binmode specified twice");
5859 if (*fmode & FMODE_TEXTMODE)
5860 rb_raise(rb_eArgError, "both textmode and binmode specified");
5861 if (RTEST(v))
5862 *fmode |= FMODE_BINMODE;
5863 }
5864
5865 if ((*fmode & FMODE_BINMODE) && (*fmode & FMODE_TEXTMODE))
5866 rb_raise(rb_eArgError, "both textmode and binmode specified");
5867 }
5868 }
5869
5870 void
5871 rb_io_extract_modeenc(VALUE *vmode_p, VALUE *vperm_p, VALUE opthash,
5872 int *oflags_p, int *fmode_p, convconfig_t *convconfig_p)
5873 {
5874 VALUE vmode;
5875 int oflags, fmode;
5876 rb_encoding *enc, *enc2;
5877 int ecflags;
5878 VALUE ecopts;
5879 int has_enc = 0, has_vmode = 0;
5880 VALUE intmode;
5881
5882 vmode = *vmode_p;
5883
5884 /* Set to defaults */
5885 rb_io_ext_int_to_encs(NULL, NULL, &enc, &enc2, 0);
5886
5887 vmode_handle:
5888 if (NIL_P(vmode)) {
5889 fmode = FMODE_READABLE;
5890 oflags = O_RDONLY;
5891 }
5892 else if (!NIL_P(intmode = rb_check_to_integer(vmode, "to_int"))) {
5893 vmode = intmode;
5894 oflags = NUM2INT(intmode);
5895 fmode = rb_io_oflags_fmode(oflags);
5896 }
5897 else {
5898 const char *p;
5899
5900 SafeStringValue(vmode);
5901 p = StringValueCStr(vmode);
5902 fmode = rb_io_modestr_fmode(p);
5903 oflags = rb_io_fmode_oflags(fmode);
5904 p = strchr(p, ':');
5905 if (p) {
5906 has_enc = 1;
5907 parse_mode_enc(p+1, rb_enc_get(vmode), &enc, &enc2, &fmode);
5908 }
5909 else {
5910 rb_encoding *e;
5911
5912 e = (fmode & FMODE_BINMODE) ? rb_ascii8bit_encoding() : NULL;
5913 rb_io_ext_int_to_encs(e, NULL, &enc, &enc2, fmode);
5914 }
5915 }
5916
5917 if (NIL_P(opthash)) {
5918 ecflags = (fmode & FMODE_READABLE) ?
5919 MODE_BTMODE(ECONV_DEFAULT_NEWLINE_DECORATOR,
5920 0, ECONV_UNIVERSAL_NEWLINE_DECORATOR) : 0;
5921 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
5922 ecflags |= (fmode & FMODE_WRITABLE) ?
5923 MODE_BTMODE(TEXTMODE_NEWLINE_DECORATOR_ON_WRITE,
5924 0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE) : 0;
5925 #endif
5926 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
5927 ecopts = Qnil;
5928 }
5929 else {
5930 VALUE v;
5931 if (!has_vmode) {
5932 v = rb_hash_aref(opthash, sym_mode);
5933 if (!NIL_P(v)) {
5934 if (!NIL_P(vmode)) {
5935 rb_raise(rb_eArgError, "mode specified twice");
5936 }
5937 has_vmode = 1;
5938 vmode = v;
5939 goto vmode_handle;
5940 }
5941 }
5942 v = rb_hash_aref(opthash, sym_flags);
5943 if (!NIL_P(v)) {
5944 v = rb_to_int(v);
5945 oflags |= NUM2INT(v);
5946 vmode = INT2NUM(oflags);
5947 fmode = rb_io_oflags_fmode(oflags);
5948 }
5949 extract_binmode(opthash, &fmode);
5950 if (fmode & FMODE_BINMODE) {
5951 #ifdef O_BINARY
5952 oflags |= O_BINARY;
5953 #endif
5954 if (!has_enc)
5955 rb_io_ext_int_to_encs(rb_ascii8bit_encoding(), NULL, &enc, &enc2, fmode);
5956 }
5957 #if DEFAULT_TEXTMODE
5958 else if (NIL_P(vmode)) {
5959 fmode |= DEFAULT_TEXTMODE;
5960 }
5961 #endif
5962 v = rb_hash_aref(opthash, sym_perm);
5963 if (!NIL_P(v)) {
5964 if (vperm_p) {
5965 if (!NIL_P(*vperm_p)) {
5966 rb_raise(rb_eArgError, "perm specified twice");
5967 }
5968 *vperm_p = v;
5969 }
5970 else {
5971 /* perm no use, just ignore */
5972 }
5973 }
5974 ecflags = (fmode & FMODE_READABLE) ?
5975 MODE_BTMODE(ECONV_DEFAULT_NEWLINE_DECORATOR,
5976 0, ECONV_UNIVERSAL_NEWLINE_DECORATOR) : 0;
5977 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
5978 ecflags |= (fmode & FMODE_WRITABLE) ?
5979 MODE_BTMODE(TEXTMODE_NEWLINE_DECORATOR_ON_WRITE,
5980 0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE) : 0;
5981 #endif
5982
5983 if (rb_io_extract_encoding_option(opthash, &enc, &enc2, &fmode)) {
5984 if (has_enc) {
5985 rb_raise(rb_eArgError, "encoding specified twice");
5986 }
5987 }
5988 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
5989 ecflags = rb_econv_prepare_options(opthash, &ecopts, ecflags);
5990 }
5991
5992 validate_enc_binmode(&fmode, ecflags, enc, enc2);
5993
5994 *vmode_p = vmode;
5995
5996 *oflags_p = oflags;
5997 *fmode_p = fmode;
5998 convconfig_p->enc = enc;
5999 convconfig_p->enc2 = enc2;
6000 convconfig_p->ecflags = ecflags;
6001 convconfig_p->ecopts = ecopts;
6002 }
6003
6004 struct sysopen_struct {
6005 VALUE fname;
6006 int oflags;
6007 mode_t perm;
6008 };
6009
6010 static void *
6011 sysopen_func(void *ptr)
6012 {
6013 const struct sysopen_struct *data = ptr;
6014 const char *fname = RSTRING_PTR(data->fname);
6015 return (void *)(VALUE)rb_cloexec_open(fname, data->oflags, data->perm);
6016 }
6017
6018 static inline int
6019 rb_sysopen_internal(struct sysopen_struct *data)
6020 {
6021 int fd;
6022 fd = (int)(VALUE)rb_thread_call_without_gvl(sysopen_func, data, RUBY_UBF_IO, 0);
6023 if (0 <= fd)
6024 rb_update_max_fd(fd);
6025 return fd;
6026 }
6027
6028 static int
6029 rb_sysopen(VALUE fname, int oflags, mode_t perm)
6030 {
6031 int fd;
6032 struct sysopen_struct data;
6033
6034 data.fname = rb_str_encode_ospath(fname);
6035 StringValueCStr(data.fname);
6036 data.oflags = oflags;
6037 data.perm = perm;
6038
6039 fd = rb_sysopen_internal(&data);
6040 if (fd < 0) {
6041 int e = errno;
6042 if (rb_gc_for_fd(e)) {
6043 fd = rb_sysopen_internal(&data);
6044 }
6045 if (fd < 0) {
6046 rb_syserr_fail_path(e, fname);
6047 }
6048 }
6049 return fd;
6050 }
6051
6052 FILE *
6053 rb_fdopen(int fd, const char *modestr)
6054 {
6055 FILE *file;
6056
6057 #if defined(__sun)
6058 errno = 0;
6059 #endif
6060 file = fdopen(fd, modestr);
6061 if (!file) {
6062 int e = errno;
6063 #if defined(__sun)
6064 if (e == 0) {
6065 rb_gc();
6066 errno = 0;
6067 file = fdopen(fd, modestr);
6068 }
6069 else
6070 #endif
6071 if (rb_gc_for_fd(e)) {
6072 file = fdopen(fd, modestr);
6073 }
6074 if (!file) {
6075 #ifdef _WIN32
6076 if (e == 0) e = EINVAL;
6077 #elif defined(__sun)
6078 if (e == 0) e = EMFILE;
6079 #endif
6080 rb_syserr_fail(e, 0);
6081 }
6082 }
6083
6084 /* xxx: should be _IONBF? A buffer in FILE may have trouble. */
6085 #ifdef USE_SETVBUF
6086 if (setvbuf(file, NULL, _IOFBF, 0) != 0)
6087 rb_warn("setvbuf() can't be honoured (fd=%d)", fd);
6088 #endif
6089 return file;
6090 }
6091
6092 static int
6093 io_check_tty(rb_io_t *fptr)
6094 {
6095 int t = isatty(fptr->fd);
6096 if (t)
6097 fptr->mode |= FMODE_TTY|FMODE_DUPLEX;
6098 return t;
6099 }
6100
6101 static VALUE rb_io_internal_encoding(VALUE);
6102 static void io_encoding_set(rb_io_t *, VALUE, VALUE, VALUE);
6103
6104 static int
6105 io_strip_bom(VALUE io)
6106 {
6107 VALUE b1, b2, b3, b4;
6108 rb_io_t *fptr;
6109
6110 GetOpenFile(io, fptr);
6111 if (!(fptr->mode & FMODE_READABLE)) return 0;
6112 if (NIL_P(b1 = rb_io_getbyte(io))) return 0;
6113 switch (b1) {
6114 case INT2FIX(0xEF):
6115 if (NIL_P(b2 = rb_io_getbyte(io))) break;
6116 if (b2 == INT2FIX(0xBB) && !NIL_P(b3 = rb_io_getbyte(io))) {
6117 if (b3 == INT2FIX(0xBF)) {
6118 return rb_utf8_encindex();
6119 }
6120 rb_io_ungetbyte(io, b3);
6121 }
6122 rb_io_ungetbyte(io, b2);
6123 break;
6124
6125 case INT2FIX(0xFE):
6126 if (NIL_P(b2 = rb_io_getbyte(io))) break;
6127 if (b2 == INT2FIX(0xFF)) {
6128 return ENCINDEX_UTF_16BE;
6129 }
6130 rb_io_ungetbyte(io, b2);
6131 break;
6132
6133 case INT2FIX(0xFF):
6134 if (NIL_P(b2 = rb_io_getbyte(io))) break;
6135 if (b2 == INT2FIX(0xFE)) {
6136 b3 = rb_io_getbyte(io);
6137 if (b3 == INT2FIX(0) && !NIL_P(b4 = rb_io_getbyte(io))) {
6138 if (b4 == INT2FIX(0)) {
6139 return ENCINDEX_UTF_32LE;
6140 }
6141 rb_io_ungetbyte(io, b4);
6142 }
6143 rb_io_ungetbyte(io, b3);
6144 return ENCINDEX_UTF_16LE;
6145 }
6146 rb_io_ungetbyte(io, b2);
6147 break;
6148
6149 case INT2FIX(0):
6150 if (NIL_P(b2 = rb_io_getbyte(io))) break;
6151 if (b2 == INT2FIX(0) && !NIL_P(b3 = rb_io_getbyte(io))) {
6152 if (b3 == INT2FIX(0xFE) && !NIL_P(b4 = rb_io_getbyte(io))) {
6153 if (b4 == INT2FIX(0xFF)) {
6154 return ENCINDEX_UTF_32BE;
6155 }
6156 rb_io_ungetbyte(io, b4);
6157 }
6158 rb_io_ungetbyte(io, b3);
6159 }
6160 rb_io_ungetbyte(io, b2);
6161 break;
6162 }
6163 rb_io_ungetbyte(io, b1);
6164 return 0;
6165 }
6166
6167 static rb_encoding *
6168 io_set_encoding_by_bom(VALUE io)
6169 {
6170 int idx = io_strip_bom(io);
6171 rb_io_t *fptr;
6172 rb_encoding *extenc = NULL;
6173
6174 GetOpenFile(io, fptr);
6175 if (idx) {
6176 extenc = rb_enc_from_index(idx);
6177 io_encoding_set(fptr, rb_enc_from_encoding(extenc),
6178 rb_io_internal_encoding(io), Qnil);
6179 }
6180 else {
6181 fptr->encs.enc2 = NULL;
6182 }
6183 return extenc;
6184 }
6185
6186 static VALUE
6187 rb_file_open_generic(VALUE io, VALUE filename, int oflags, int fmode,
6188 const convconfig_t *convconfig, mode_t perm)
6189 {
6190 VALUE pathv;
6191 rb_io_t *fptr;
6192 convconfig_t cc;
6193 if (!convconfig) {
6194 /* Set to default encodings */
6195 rb_io_ext_int_to_encs(NULL, NULL, &cc.enc, &cc.enc2, fmode);
6196 cc.ecflags = 0;
6197 cc.ecopts = Qnil;
6198 convconfig = &cc;
6199 }
6200 validate_enc_binmode(&fmode, convconfig->ecflags,
6201 convconfig->enc, convconfig->enc2);
6202
6203 MakeOpenFile(io, fptr);
6204 fptr->mode = fmode;
6205 fptr->encs = *convconfig;
6206 pathv = rb_str_new_frozen(filename);
6207 #ifdef O_TMPFILE
6208 if (!(oflags & O_TMPFILE)) {
6209 fptr->pathv = pathv;
6210 }
6211 #else
6212 fptr->pathv = pathv;
6213 #endif
6214 fptr->fd = rb_sysopen(pathv, oflags, perm);
6215 io_check_tty(fptr);
6216 if (fmode & FMODE_SETENC_BY_BOM) io_set_encoding_by_bom(io);
6217
6218 return io;
6219 }
6220
6221 static VALUE
6222 rb_file_open_internal(VALUE io, VALUE filename, const char *modestr)
6223 {
6224 int fmode = rb_io_modestr_fmode(modestr);
6225 const char *p = strchr(modestr, ':');
6226 convconfig_t convconfig;
6227
6228 if (p) {
6229 parse_mode_enc(p+1, rb_usascii_encoding(),
6230 &convconfig.enc, &convconfig.enc2, &fmode);
6231 convconfig.ecflags = 0;
6232 convconfig.ecopts = Qnil;
6233 }
6234 else {
6235 rb_encoding *e;
6236 /* Set to default encodings */
6237
6238 e = (fmode & FMODE_BINMODE) ? rb_ascii8bit_encoding() : NULL;
6239 rb_io_ext_int_to_encs(e, NULL, &convconfig.enc, &convconfig.enc2, fmode);
6240 convconfig.ecflags = 0;
6241 convconfig.ecopts = Qnil;
6242 }
6243
6244 return rb_file_open_generic(io, filename,
6245 rb_io_fmode_oflags(fmode),
6246 fmode,
6247 &convconfig,
6248 0666);
6249 }
6250
6251 VALUE
6252 rb_file_open_str(VALUE fname, const char *modestr)
6253 {
6254 FilePathValue(fname);
6255 return rb_file_open_internal(io_alloc(rb_cFile), fname, modestr);
6256 }
6257
6258 VALUE
6259 rb_file_open(const char *fname, const char *modestr)
6260 {
6261 return rb_file_open_internal(io_alloc(rb_cFile), rb_str_new_cstr(fname), modestr);
6262 }
6263
6264 #if defined(__CYGWIN__) || !defined(HAVE_WORKING_FORK)
6265 static struct pipe_list {
6266 rb_io_t *fptr;
6267 struct pipe_list *next;
6268 } *pipe_list;
6269
6270 static void
6271 pipe_add_fptr(rb_io_t *fptr)
6272 {
6273 struct pipe_list *list;
6274
6275 list = ALLOC(struct pipe_list);
6276 list->fptr = fptr;
6277 list->next = pipe_list;
6278 pipe_list = list;
6279 }
6280
6281 static void
6282 pipe_del_fptr(rb_io_t *fptr)
6283 {
6284 struct pipe_list **prev = &pipe_list;
6285 struct pipe_list *tmp;
6286
6287 while ((tmp = *prev) != 0) {
6288 if (tmp->fptr == fptr) {
6289 *prev = tmp->next;
6290 free(tmp);
6291 return;
6292 }
6293 prev = &tmp->next;
6294 }
6295 }
6296
6297 #if defined (_WIN32) || defined(__CYGWIN__)
6298 static void
6299 pipe_atexit(void)
6300 {
6301 struct pipe_list *list = pipe_list;
6302 struct pipe_list *tmp;
6303
6304 while (list) {
6305 tmp = list->next;
6306 rb_io_fptr_finalize(list->fptr);
6307 list = tmp;
6308 }
6309 }
6310 #endif
6311
6312 static void
6313 pipe_finalize(rb_io_t *fptr, int noraise)
6314 {
6315 #if !defined(HAVE_WORKING_FORK) && !defined(_WIN32)
6316 int status = 0;
6317 if (fptr->stdio_file) {
6318 status = pclose(fptr->stdio_file);
6319 }
6320 fptr->fd = -1;
6321 fptr->stdio_file = 0;
6322 rb_last_status_set(status, fptr->pid);
6323 #else
6324 fptr_finalize(fptr, noraise);
6325 #endif
6326 pipe_del_fptr(fptr);
6327 }
6328 #endif
6329
6330 static void
6331 fptr_copy_finalizer(rb_io_t *fptr, const rb_io_t *orig)
6332 {
6333 #if defined(__CYGWIN__) || !defined(HAVE_WORKING_FORK)
6334 void (*const old_finalize)(struct rb_io_t*,int) = fptr->finalize;
6335
6336 if (old_finalize == orig->finalize) return;
6337 #endif
6338
6339 fptr->finalize = orig->finalize;
6340
6341 #if defined(__CYGWIN__) || !defined(HAVE_WORKING_FORK)
6342 if (old_finalize != pipe_finalize) {
6343 struct pipe_list *list;
6344 for (list = pipe_list; list; list = list->next) {
6345 if (list->fptr == fptr) break;
6346 }
6347 if (!list) pipe_add_fptr(fptr);
6348 }
6349 else {
6350 pipe_del_fptr(fptr);
6351 }
6352 #endif
6353 }
6354
6355 void
6356 rb_io_synchronized(rb_io_t *fptr)
6357 {
6358 rb_io_check_initialized(fptr);
6359 fptr->mode |= FMODE_SYNC;
6360 }
6361
6362 void
6363 rb_io_unbuffered(rb_io_t *fptr)
6364 {
6365 rb_io_synchronized(fptr);
6366 }
6367
6368 int
6369 rb_pipe(int *pipes)
6370 {
6371 int ret;
6372 ret = rb_cloexec_pipe(pipes);
6373 if (ret < 0) {
6374 if (rb_gc_for_fd(errno)) {
6375 ret = rb_cloexec_pipe(pipes);
6376 }
6377 }
6378 if (ret == 0) {
6379 rb_update_max_fd(pipes[0]);
6380 rb_update_max_fd(pipes[1]);
6381 }
6382 return ret;
6383 }
6384
6385 #ifdef _WIN32
6386 #define HAVE_SPAWNV 1
6387 #define spawnv(mode, cmd, args) rb_w32_uaspawn((mode), (cmd), (args))
6388 #define spawn(mode, cmd) rb_w32_uspawn((mode), (cmd), 0)
6389 #endif
6390
6391 #if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
6392 struct popen_arg {
6393 VALUE execarg_obj;
6394 struct rb_execarg *eargp;
6395 int modef;
6396 int pair[2];
6397 int write_pair[2];
6398 };
6399 #endif
6400
6401 #ifdef HAVE_WORKING_FORK
6402 static void
6403 popen_redirect(struct popen_arg *p)
6404 {
6405 if ((p->modef & FMODE_READABLE) && (p->modef & FMODE_WRITABLE)) {
6406 close(p->write_pair[1]);
6407 if (p->write_pair[0] != 0) {
6408 dup2(p->write_pair[0], 0);
6409 close(p->write_pair[0]);
6410 }
6411 close(p->pair[0]);
6412 if (p->pair[1] != 1) {
6413 dup2(p->pair[1], 1);
6414 close(p->pair[1]);
6415 }
6416 }
6417 else if (p->modef & FMODE_READABLE) {
6418 close(p->pair[0]);
6419 if (p->pair[1] != 1) {
6420 dup2(p->pair[1], 1);
6421 close(p->pair[1]);
6422 }
6423 }
6424 else {
6425 close(p->pair[1]);
6426 if (p->pair[0] != 0) {
6427 dup2(p->pair[0], 0);
6428 close(p->pair[0]);
6429 }
6430 }
6431 }
6432
6433 #if defined(__linux__)
6434 /* Linux /proc/self/status contains a line: "FDSize:\t<nnn>\n"
6435 * Since /proc may not be available, linux_get_maxfd is just a hint.
6436 * This function, linux_get_maxfd, must be async-signal-safe.
6437 * I.e. opendir() is not usable.
6438 *
6439 * Note that memchr() and memcmp is *not* async-signal-safe in POSIX.
6440 * However they are easy to re-implement in async-signal-safe manner.
6441 * (Also note that there is missing/memcmp.c.)
6442 */
6443 static int
6444 linux_get_maxfd(void)
6445 {
6446 int fd;
6447 char buf[4096], *p, *np, *e;
6448 ssize_t ss;
6449 fd = rb_cloexec_open("/proc/self/status", O_RDONLY|O_NOCTTY, 0);
6450 if (fd < 0) return fd;
6451 ss = read(fd, buf, sizeof(buf));
6452 if (ss < 0) goto err;
6453 p = buf;
6454 e = buf + ss;
6455 while ((int)sizeof("FDSize:\t0\n")-1 <= e-p &&
6456 (np = memchr(p, '\n', e-p)) != NULL) {
6457 if (memcmp(p, "FDSize:", sizeof("FDSize:")-1) == 0) {
6458 int fdsize;
6459 p += sizeof("FDSize:")-1;
6460 *np = '\0';
6461 fdsize = (int)ruby_strtoul(p, (char **)NULL, 10);
6462 close(fd);
6463 return fdsize;
6464 }
6465 p = np+1;
6466 }
6467 /* fall through */
6468
6469 err:
6470 close(fd);
6471 return (int)ss;
6472 }
6473 #endif
6474
6475 /* This function should be async-signal-safe. */
6476 void
6477 rb_close_before_exec(int lowfd, int maxhint, VALUE noclose_fds)
6478 {
6479 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
6480 int fd, ret;
6481 int max = (int)max_file_descriptor;
6482 # ifdef F_MAXFD
6483 /* F_MAXFD is available since NetBSD 2.0. */
6484 ret = fcntl(0, F_MAXFD); /* async-signal-safe */
6485 if (ret != -1)
6486 maxhint = max = ret;
6487 # elif defined(__linux__)
6488 ret = linux_get_maxfd();
6489 if (maxhint < ret)
6490 maxhint = ret;
6491 /* maxhint = max = ret; if (ret == -1) abort(); // test */
6492 # endif
6493 if (max < maxhint)
6494 max = maxhint;
6495 for (fd = lowfd; fd <= max; fd++) {
6496 if (!NIL_P(noclose_fds) &&
6497 RTEST(rb_hash_lookup(noclose_fds, INT2FIX(fd)))) /* async-signal-safe */
6498 continue;
6499 ret = fcntl(fd, F_GETFD); /* async-signal-safe */
6500 if (ret != -1 && !(ret & FD_CLOEXEC)) {
6501 fcntl(fd, F_SETFD, ret|FD_CLOEXEC); /* async-signal-safe */
6502 }
6503 # define CONTIGUOUS_CLOSED_FDS 20
6504 if (ret != -1) {
6505 if (max < fd + CONTIGUOUS_CLOSED_FDS)
6506 max = fd + CONTIGUOUS_CLOSED_FDS;
6507 }
6508 }
6509 #endif
6510 }
6511
6512 static int
6513 popen_exec(void *pp, char *errmsg, size_t errmsg_len)
6514 {
6515 struct popen_arg *p = (struct popen_arg*)pp;
6516
6517 return rb_exec_async_signal_safe(p->eargp, errmsg, errmsg_len);
6518 }
6519 #endif
6520
6521 #if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
6522 static VALUE
6523 rb_execarg_fixup_v(VALUE execarg_obj)
6524 {
6525 rb_execarg_parent_start(execarg_obj);
6526 return Qnil;
6527 }
6528 #else
6529 char *rb_execarg_commandline(const struct rb_execarg *eargp, VALUE *prog);
6530 #endif
6531
6532 static VALUE
6533 pipe_open(VALUE execarg_obj, const char *modestr, int fmode,
6534 const convconfig_t *convconfig)
6535 {
6536 struct rb_execarg *eargp = NIL_P(execarg_obj) ? NULL : rb_execarg_get(execarg_obj);
6537 VALUE prog = eargp ? (eargp->use_shell ? eargp->invoke.sh.shell_script : eargp->invoke.cmd.command_name) : Qfalse ;
6538 rb_pid_t pid = 0;
6539 rb_io_t *fptr;
6540 VALUE port;
6541 rb_io_t *write_fptr;
6542 VALUE write_port;
6543 #if defined(HAVE_WORKING_FORK)
6544 int status;
6545 char errmsg[80] = { '\0' };
6546 #endif
6547 #if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
6548 int state;
6549 struct popen_arg arg;
6550 #endif
6551 int e = 0;
6552 #if defined(HAVE_SPAWNV)
6553 # if defined(HAVE_SPAWNVE)
6554 # define DO_SPAWN(cmd, args, envp) ((args) ? \
6555 spawnve(P_NOWAIT, (cmd), (args), (envp)) : \
6556 spawne(P_NOWAIT, (cmd), (envp)))
6557 # else
6558 # define DO_SPAWN(cmd, args, envp) ((args) ? \
6559 spawnv(P_NOWAIT, (cmd), (args)) : \
6560 spawn(P_NOWAIT, (cmd)))
6561 # endif
6562 # if !defined(HAVE_WORKING_FORK)
6563 char **args = NULL;
6564 # if defined(HAVE_SPAWNVE)
6565 char **envp = NULL;
6566 # endif
6567 # endif
6568 #endif
6569 #if !defined(HAVE_WORKING_FORK)
6570 struct rb_execarg sarg, *sargp = &sarg;
6571 #endif
6572 FILE *fp = 0;
6573 int fd = -1;
6574 int write_fd = -1;
6575 #if !defined(HAVE_WORKING_FORK)
6576 const char *cmd = 0;
6577
6578 if (prog)
6579 cmd = StringValueCStr(prog);
6580 #endif
6581
6582 #if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
6583 arg.execarg_obj = execarg_obj;
6584 arg.eargp = eargp;
6585 arg.modef = fmode;
6586 arg.pair[0] = arg.pair[1] = -1;
6587 arg.write_pair[0] = arg.write_pair[1] = -1;
6588 # if !defined(HAVE_WORKING_FORK)
6589 if (eargp && !eargp->use_shell) {
6590 args = ARGVSTR2ARGV(eargp->invoke.cmd.argv_str);
6591 }
6592 # endif
6593 switch (fmode & (FMODE_READABLE|FMODE_WRITABLE)) {
6594 case FMODE_READABLE|FMODE_WRITABLE:
6595 if (rb_pipe(arg.write_pair) < 0)
6596 rb_sys_fail_str(prog);
6597 if (rb_pipe(arg.pair) < 0) {
6598 e = errno;
6599 close(arg.write_pair[0]);
6600 close(arg.write_pair[1]);
6601 rb_syserr_fail_str(e, prog);
6602 }
6603 if (eargp) {
6604 rb_execarg_addopt(execarg_obj, INT2FIX(0), INT2FIX(arg.write_pair[0]));
6605 rb_execarg_addopt(execarg_obj, INT2FIX(1), INT2FIX(arg.pair[1]));
6606 }
6607 break;
6608 case FMODE_READABLE:
6609 if (rb_pipe(arg.pair) < 0)
6610 rb_sys_fail_str(prog);
6611 if (eargp)
6612 rb_execarg_addopt(execarg_obj, INT2FIX(1), INT2FIX(arg.pair[1]));
6613 break;
6614 case FMODE_WRITABLE:
6615 if (rb_pipe(arg.pair) < 0)
6616 rb_sys_fail_str(prog);
6617 if (eargp)
6618 rb_execarg_addopt(execarg_obj, INT2FIX(0), INT2FIX(arg.pair[0]));
6619 break;
6620 default:
6621 rb_sys_fail_str(prog);
6622 }
6623 if (!NIL_P(execarg_obj)) {
6624 rb_protect(rb_execarg_fixup_v, execarg_obj, &state);
6625 if (state) {
6626 if (0 <= arg.write_pair[0]) close(arg.write_pair[0]);
6627 if (0 <= arg.write_pair[1]) close(arg.write_pair[1]);
6628 if (0 <= arg.pair[0]) close(arg.pair[0]);
6629 if (0 <= arg.pair[1]) close(arg.pair[1]);
6630 rb_execarg_parent_end(execarg_obj);
6631 rb_jump_tag(state);
6632 }
6633
6634 # if defined(HAVE_WORKING_FORK)
6635 pid = rb_fork_async_signal_safe(&status, popen_exec, &arg, arg.eargp->redirect_fds, errmsg, sizeof(errmsg));
6636 # else
6637 rb_execarg_run_options(eargp, sargp, NULL, 0);
6638 # if defined(HAVE_SPAWNVE)
6639 if (eargp->envp_str) envp = (char **)RSTRING_PTR(eargp->envp_str);
6640 # endif
6641 while ((pid = DO_SPAWN(cmd, args, envp)) < 0) {
6642 /* exec failed */
6643 switch (e = errno) {
6644 case EAGAIN:
6645 # if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
6646 case EWOULDBLOCK:
6647 # endif
6648 rb_thread_sleep(1);
6649 continue;
6650 }
6651 break;
6652 }
6653 if (eargp)
6654 rb_execarg_run_options(sargp, NULL, NULL, 0);
6655 # endif
6656 rb_execarg_parent_end(execarg_obj);
6657 }
6658 else {
6659 # if defined(HAVE_WORKING_FORK)
6660 pid = rb_fork_ruby(&status);
6661 if (pid == 0) { /* child */
6662 rb_thread_atfork();
6663 popen_redirect(&arg);
6664 rb_io_synchronized(RFILE(orig_stdout)->fptr);
6665 rb_io_synchronized(RFILE(orig_stderr)->fptr);
6666 return Qnil;
6667 }
6668 # else
6669 rb_notimplement();
6670 # endif
6671 }
6672
6673 /* parent */
6674 if (pid < 0) {
6675 # if defined(HAVE_WORKING_FORK)
6676 e = errno;
6677 # endif
6678 close(arg.pair[0]);
6679 close(arg.pair[1]);
6680 if ((fmode & (FMODE_READABLE|FMODE_WRITABLE)) == (FMODE_READABLE|FMODE_WRITABLE)) {
6681 close(arg.write_pair[0]);
6682 close(arg.write_pair[1]);
6683 }
6684 # if defined(HAVE_WORKING_FORK)
6685 if (errmsg[0])
6686 rb_syserr_fail(e, errmsg);
6687 # endif
6688 rb_syserr_fail_str(e, prog);
6689 }
6690 if ((fmode & FMODE_READABLE) && (fmode & FMODE_WRITABLE)) {
6691 close(arg.pair[1]);
6692 fd = arg.pair[0];
6693 close(arg.write_pair[0]);
6694 write_fd = arg.write_pair[1];
6695 }
6696 else if (fmode & FMODE_READABLE) {
6697 close(arg.pair[1]);
6698 fd = arg.pair[0];
6699 }
6700 else {
6701 close(arg.pair[0]);
6702 fd = arg.pair[1];
6703 }
6704 #else
6705 cmd = rb_execarg_commandline(eargp, &prog);
6706 if (!NIL_P(execarg_obj)) {
6707 rb_execarg_parent_start(execarg_obj);
6708 rb_execarg_run_options(eargp, sargp, NULL, 0);
6709 }
6710 fp = popen(cmd, modestr);
6711 e = errno;
6712 if (eargp) {
6713 rb_execarg_parent_end(execarg_obj);
6714 rb_execarg_run_options(sargp, NULL, NULL, 0);
6715 }
6716 if (!fp) rb_syserr_fail_path(e, prog);
6717 fd = fileno(fp);
6718 #endif
6719
6720 port = io_alloc(rb_cIO);
6721 MakeOpenFile(port, fptr);
6722 fptr->fd = fd;
6723 fptr->stdio_file = fp;
6724 fptr->mode = fmode | FMODE_SYNC|FMODE_DUPLEX;
6725 if (convconfig) {
6726 fptr->encs = *convconfig;
6727 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
6728 if (fptr->encs.ecflags & ECONV_DEFAULT_NEWLINE_DECORATOR) {
6729 fptr->encs.ecflags |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;
6730 }
6731 #endif
6732 }
6733 else {
6734 if (NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {
6735 fptr->encs.ecflags |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;
6736 }
6737 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
6738 if (NEED_NEWLINE_DECORATOR_ON_WRITE(fptr)) {
6739 fptr->encs.ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
6740 }
6741 #endif
6742 }
6743 fptr->pid = pid;
6744
6745 if (0 <= write_fd) {
6746 write_port = io_alloc(rb_cIO);
6747 MakeOpenFile(write_port, write_fptr);
6748 write_fptr->fd = write_fd;
6749 write_fptr->mode = (fmode & ~FMODE_READABLE)| FMODE_SYNC|FMODE_DUPLEX;
6750 fptr->mode &= ~FMODE_WRITABLE;
6751 fptr->tied_io_for_writing = write_port;
6752 rb_ivar_set(port, rb_intern("@tied_io_for_writing"), write_port);
6753 }
6754
6755 #if defined (__CYGWIN__) || !defined(HAVE_WORKING_FORK)
6756 fptr->finalize = pipe_finalize;
6757 pipe_add_fptr(fptr);
6758 #endif
6759 return port;
6760 }
6761
6762 static int
6763 is_popen_fork(VALUE prog)
6764 {
6765 if (RSTRING_LEN(prog) == 1 && RSTRING_PTR(prog)[0] == '-') {
6766 #if !defined(HAVE_WORKING_FORK)
6767 rb_raise(rb_eNotImpError,
6768 "fork() function is unimplemented on this machine");
6769 #else
6770 return TRUE;
6771 #endif
6772 }
6773 return FALSE;
6774 }
6775
6776 static VALUE
6777 pipe_open_s(VALUE prog, const char *modestr, int fmode,
6778 const convconfig_t *convconfig)
6779 {
6780 int argc = 1;
6781 VALUE *argv = &prog;
6782 VALUE execarg_obj = Qnil;
6783
6784 if (!is_popen_fork(prog))
6785 execarg_obj = rb_execarg_new(argc, argv, TRUE, FALSE);
6786 return pipe_open(execarg_obj, modestr, fmode, convconfig);
6787 }
6788
6789 static VALUE
6790 pipe_close(VALUE io)
6791 {
6792 rb_io_t *fptr = io_close_fptr(io);
6793 if (fptr) {
6794 fptr_waitpid(fptr, rb_thread_to_be_killed(rb_thread_current()));
6795 }
6796 return Qnil;
6797 }
6798
6799 /*
6800 * call-seq:
6801 * IO.popen([env,] cmd, mode="r" [, opt]) -> io
6802 * IO.popen([env,] cmd, mode="r" [, opt]) {|io| block } -> obj
6803 *
6804 * Runs the specified command as a subprocess; the subprocess's
6805 * standard input and output will be connected to the returned
6806 * IO object.
6807 *
6808 * The PID of the started process can be obtained by IO#pid method.
6809 *
6810 * _cmd_ is a string or an array as follows.
6811 *
6812 * cmd:
6813 * "-" : fork
6814 * commandline : command line string which is passed to a shell
6815 * [env, cmdname, arg1, ..., opts] : command name and zero or more arguments (no shell)
6816 * [env, [cmdname, argv0], arg1, ..., opts] : command name, argv[0] and zero or more arguments (no shell)
6817 * (env and opts are optional.)
6818 *
6819 * If _cmd_ is a +String+ ``<code>-</code>'',
6820 * then a new instance of Ruby is started as the subprocess.
6821 *
6822 * If <i>cmd</i> is an +Array+ of +String+,
6823 * then it will be used as the subprocess's +argv+ bypassing a shell.
6824 * The array can contain a hash at first for environments and
6825 * a hash at last for options similar to #spawn.
6826 *
6827 * The default mode for the new file object is ``r'',
6828 * but <i>mode</i> may be set to any of the modes listed in the description for class IO.
6829 * The last argument <i>opt</i> qualifies <i>mode</i>.
6830 *
6831 * # set IO encoding
6832 * IO.popen("nkf -e filename", :external_encoding=>"EUC-JP") {|nkf_io|
6833 * euc_jp_string = nkf_io.read
6834 * }
6835 *
6836 * # merge standard output and standard error using
6837 * # spawn option. See the document of Kernel.spawn.
6838 * IO.popen(["ls", "/", :err=>[:child, :out]]) {|ls_io|
6839 * ls_result_with_error = ls_io.read
6840 * }
6841 *
6842 * # spawn options can be mixed with IO options
6843 * IO.popen(["ls", "/"], :err=>[:child, :out]) {|ls_io|
6844 * ls_result_with_error = ls_io.read
6845 * }
6846 *
6847 * Raises exceptions which IO.pipe and Kernel.spawn raise.
6848 *
6849 * If a block is given, Ruby will run the command as a child connected
6850 * to Ruby with a pipe. Ruby's end of the pipe will be passed as a
6851 * parameter to the block.
6852 * At the end of block, Ruby closes the pipe and sets <code>$?</code>.
6853 * In this case IO.popen returns the value of the block.
6854 *
6855 * If a block is given with a _cmd_ of ``<code>-</code>'',
6856 * the block will be run in two separate processes: once in the parent,
6857 * and once in a child. The parent process will be passed the pipe
6858 * object as a parameter to the block, the child version of the block
6859 * will be passed +nil+, and the child's standard in and
6860 * standard out will be connected to the parent through the pipe. Not
6861 * available on all platforms.
6862 *
6863 * f = IO.popen("uname")
6864 * p f.readlines
6865 * f.close
6866 * puts "Parent is #{Process.pid}"
6867 * IO.popen("date") {|f| puts f.gets }
6868 * IO.popen("-") {|f| $stderr.puts "#{Process.pid} is here, f is #{f.inspect}"}
6869 * p $?
6870 * IO.popen(%w"sed -e s|^|<foo>| -e s&$&;zot;&", "r+") {|f|
6871 * f.puts "bar"; f.close_write; puts f.gets
6872 * }
6873 *
6874 * <em>produces:</em>
6875 *
6876 * ["Linux\n"]
6877 * Parent is 21346
6878 * Thu Jan 15 22:41:19 JST 2009
6879 * 21346 is here, f is #<IO:fd 3>
6880 * 21352 is here, f is nil
6881 * #<Process::Status: pid 21352 exit 0>
6882 * <foo>bar;zot;
6883 */
6884
6885 static VALUE
6886 rb_io_s_popen(int argc, VALUE *argv, VALUE klass)
6887 {
6888 const char *modestr;
6889 VALUE pname, pmode = Qnil, port, tmp, opt = Qnil, env = Qnil, execarg_obj = Qnil;
6890 int oflags, fmode;
6891 convconfig_t convconfig;
6892
6893 if (argc > 1 && !NIL_P(opt = rb_check_hash_type(argv[argc-1]))) --argc;
6894 if (argc > 1 && !NIL_P(env = rb_check_hash_type(argv[0]))) --argc, ++argv;
6895 switch (argc) {
6896 case 2:
6897 pmode = argv[1];
6898 case 1:
6899 pname = argv[0];
6900 break;
6901 default:
6902 {
6903 int ex = !NIL_P(opt);
6904 rb_error_arity(argc + ex, 1 + ex, 2 + ex);
6905 }
6906 }
6907
6908 tmp = rb_check_array_type(pname);
6909 if (!NIL_P(tmp)) {
6910 long len = RARRAY_LEN(tmp);
6911 #if SIZEOF_LONG > SIZEOF_INT
6912 if (len > INT_MAX) {
6913 rb_raise(rb_eArgError, "too many arguments");
6914 }
6915 #endif
6916 execarg_obj = rb_execarg_new((int)len, RARRAY_CONST_PTR(tmp), FALSE, FALSE);
6917 RB_GC_GUARD(tmp);
6918 }
6919 else {
6920 SafeStringValue(pname);
6921 execarg_obj = Qnil;
6922 if (!is_popen_fork(pname))
6923 execarg_obj = rb_execarg_new(1, &pname, TRUE, FALSE);
6924 }
6925 if (!NIL_P(execarg_obj)) {
6926 if (!NIL_P(opt))
6927 opt = rb_execarg_extract_options(execarg_obj, opt);
6928 if (!NIL_P(env))
6929 rb_execarg_setenv(execarg_obj, env);
6930 }
6931 rb_io_extract_modeenc(&pmode, 0, opt, &oflags, &fmode, &convconfig);
6932 modestr = rb_io_oflags_modestr(oflags);
6933
6934 port = pipe_open(execarg_obj, modestr, fmode, &convconfig);
6935 if (NIL_P(port)) {
6936 /* child */
6937 if (rb_block_given_p()) {
6938 rb_yield(Qnil);
6939 rb_io_flush(rb_stdout);
6940 rb_io_flush(rb_stderr);
6941 _exit(0);
6942 }
6943 return Qnil;
6944 }
6945 RBASIC_SET_CLASS(port, klass);
6946 if (rb_block_given_p()) {
6947 return rb_ensure(rb_yield, port, pipe_close, port);
6948 }
6949 return port;
6950 }
6951
6952 static void
6953 rb_scan_open_args(int argc, const VALUE *argv,
6954 VALUE *fname_p, int *oflags_p, int *fmode_p,
6955 convconfig_t *convconfig_p, mode_t *perm_p)
6956 {
6957 VALUE opt, fname, vmode, vperm;
6958 int oflags, fmode;
6959 mode_t perm;
6960
6961 argc = rb_scan_args(argc, argv, "12:", &fname, &vmode, &vperm, &opt);
6962 FilePathValue(fname);
6963
6964 rb_io_extract_modeenc(&vmode, &vperm, opt, &oflags, &fmode, convconfig_p);
6965
6966 perm = NIL_P(vperm) ? 0666 : NUM2MODET(vperm);
6967
6968 *fname_p = fname;
6969 *oflags_p = oflags;
6970 *fmode_p = fmode;
6971 *perm_p = perm;
6972 }
6973
6974 static VALUE
6975 rb_open_file(int argc, const VALUE *argv, VALUE io)
6976 {
6977 VALUE fname;
6978 int oflags, fmode;
6979 convconfig_t convconfig;
6980 mode_t perm;
6981
6982 rb_scan_open_args(argc, argv, &fname, &oflags, &fmode, &convconfig, &perm);
6983 rb_file_open_generic(io, fname, oflags, fmode, &convconfig, perm);
6984
6985 return io;
6986 }
6987
6988
6989 /*
6990 * Document-method: File::open
6991 *
6992 * call-seq:
6993 * File.open(filename, mode="r" [, opt]) -> file
6994 * File.open(filename [, mode [, perm]] [, opt]) -> file
6995 * File.open(filename, mode="r" [, opt]) {|file| block } -> obj
6996 * File.open(filename [, mode [, perm]] [, opt]) {|file| block } -> obj
6997 *
6998 * With no associated block, File.open is a synonym for
6999 * File.new. If the optional code block is given, it will
7000 * be passed the opened +file+ as an argument and the File object will
7001 * automatically be closed when the block terminates. The value of the block
7002 * will be returned from File.open.
7003 *
7004 * If a file is being created, its initial permissions may be set using the
7005 * +perm+ parameter. See File.new for further discussion.
7006 *
7007 * See IO.new for a description of the +mode+ and +opt+ parameters.
7008 */
7009
7010 /*
7011 * Document-method: IO::open
7012 *
7013 * call-seq:
7014 * IO.open(fd, mode="r" [, opt]) -> io
7015 * IO.open(fd, mode="r" [, opt]) {|io| block } -> obj
7016 *
7017 * With no associated block, IO.open is a synonym for IO.new. If
7018 * the optional code block is given, it will be passed +io+ as an argument,
7019 * and the IO object will automatically be closed when the block terminates.
7020 * In this instance, IO.open returns the value of the block.
7021 *
7022 * See IO.new for a description of the +fd+, +mode+ and +opt+ parameters.
7023 */
7024
7025 static VALUE
7026 rb_io_s_open(int argc, VALUE *argv, VALUE klass)
7027 {
7028 VALUE io = rb_class_new_instance_kw(argc, argv, klass, RB_PASS_CALLED_KEYWORDS);
7029
7030 if (rb_block_given_p()) {
7031 return rb_ensure(rb_yield, io, io_close, io);
7032 }
7033
7034 return io;
7035 }
7036
7037 /*
7038 * call-seq:
7039 * IO.sysopen(path, [mode, [perm]]) -> integer
7040 *
7041 * Opens the given path, returning the underlying file descriptor as a
7042 * Integer.
7043 *
7044 * IO.sysopen("testfile") #=> 3
7045 */
7046
7047 static VALUE
7048 rb_io_s_sysopen(int argc, VALUE *argv, VALUE _)
7049 {
7050 VALUE fname, vmode, vperm;
7051 VALUE intmode;
7052 int oflags, fd;
7053 mode_t perm;
7054
7055 rb_scan_args(argc, argv, "12", &fname, &vmode, &vperm);
7056 FilePathValue(fname);
7057
7058 if (NIL_P(vmode))
7059 oflags = O_RDONLY;
7060 else if (!NIL_P(intmode = rb_check_to_integer(vmode, "to_int")))
7061 oflags = NUM2INT(intmode);
7062 else {
7063 SafeStringValue(vmode);
7064 oflags = rb_io_modestr_oflags(StringValueCStr(vmode));
7065 }
7066 if (NIL_P(vperm)) perm = 0666;
7067 else perm = NUM2MODET(vperm);
7068
7069 RB_GC_GUARD(fname) = rb_str_new4(fname);
7070 fd = rb_sysopen(fname, oflags, perm);
7071 return INT2NUM(fd);
7072 }
7073
7074 static VALUE
7075 check_pipe_command(VALUE filename_or_command)
7076 {
7077 char *s = RSTRING_PTR(filename_or_command);
7078 long l = RSTRING_LEN(filename_or_command);
7079 char *e = s + l;
7080 int chlen;
7081
7082 if (rb_enc_ascget(s, e, &chlen, rb_enc_get(filename_or_command)) == '|') {
7083 VALUE cmd = rb_str_new(s+chlen, l-chlen);
7084 return cmd;
7085 }
7086 return Qnil;
7087 }
7088
7089 /*
7090 * call-seq:
7091 * open(path [, mode [, perm]] [, opt]) -> io or nil
7092 * open(path [, mode [, perm]] [, opt]) {|io| block } -> obj
7093 *
7094 * Creates an IO object connected to the given stream, file, or subprocess.
7095 *
7096 * If +path+ does not start with a pipe character (<code>|</code>), treat it
7097 * as the name of a file to open using the specified mode (defaulting to
7098 * "r").
7099 *
7100 * The +mode+ is either a string or an integer. If it is an integer, it
7101 * must be bitwise-or of open(2) flags, such as File::RDWR or File::EXCL. If
7102 * it is a string, it is either "fmode", "fmode:ext_enc", or
7103 * "fmode:ext_enc:int_enc".
7104 *
7105 * See the documentation of IO.new for full documentation of the +mode+ string
7106 * directives.
7107 *
7108 * If a file is being created, its initial permissions may be set using the
7109 * +perm+ parameter. See File.new and the open(2) and chmod(2) man pages for
7110 * a description of permissions.
7111 *
7112 * If a block is specified, it will be invoked with the IO object as a
7113 * parameter, and the IO will be automatically closed when the block
7114 * terminates. The call returns the value of the block.
7115 *
7116 * If +path+ starts with a pipe character (<code>"|"</code>), a subprocess is
7117 * created, connected to the caller by a pair of pipes. The returned IO
7118 * object may be used to write to the standard input and read from the
7119 * standard output of this subprocess.
7120 *
7121 * If the command following the pipe is a single minus sign
7122 * (<code>"|-"</code>), Ruby forks, and this subprocess is connected to the
7123 * parent. If the command is not <code>"-"</code>, the subprocess runs the
7124 * command.
7125 *
7126 * When the subprocess is Ruby (opened via <code>"|-"</code>), the +open+
7127 * call returns +nil+. If a block is associated with the open call, that
7128 * block will run twice --- once in the parent and once in the child.
7129 *
7130 * The block parameter will be an IO object in the parent and +nil+ in the
7131 * child. The parent's +IO+ object will be connected to the child's $stdin
7132 * and $stdout. The subprocess will be terminated at the end of the block.
7133 *
7134 * === Examples
7135 *
7136 * Reading from "testfile":
7137 *
7138 * open("testfile") do |f|
7139 * print f.gets
7140 * end
7141 *
7142 * Produces:
7143 *
7144 * This is line one
7145 *
7146 * Open a subprocess and read its output:
7147 *
7148 * cmd = open("|date")
7149 * print cmd.gets
7150 * cmd.close
7151 *
7152 * Produces:
7153 *
7154 * Wed Apr 9 08:56:31 CDT 2003
7155 *
7156 * Open a subprocess running the same Ruby program:
7157 *
7158 * f = open("|-", "w+")
7159 * if f.nil?
7160 * puts "in Child"
7161 * exit
7162 * else
7163 * puts "Got: #{f.gets}"
7164 * end
7165 *
7166 * Produces:
7167 *
7168 * Got: in Child
7169 *
7170 * Open a subprocess using a block to receive the IO object:
7171 *
7172 * open "|-" do |f|
7173 * if f then
7174 * # parent process
7175 * puts "Got: #{f.gets}"
7176 * else
7177 * # child process
7178 * puts "in Child"
7179 * end
7180 * end
7181 *
7182 * Produces:
7183 *
7184 * Got: in Child
7185 */
7186
7187 static VALUE
7188 rb_f_open(int argc, VALUE *argv, VALUE _)
7189 {
7190 ID to_open = 0;
7191 int redirect = FALSE;
7192
7193 if (argc >= 1) {
7194 CONST_ID(to_open, "to_open");
7195 if (rb_respond_to(argv[0], to_open)) {
7196 redirect = TRUE;
7197 }
7198 else {
7199 VALUE tmp = argv[0];
7200 FilePathValue(tmp);
7201 if (NIL_P(tmp)) {
7202 redirect = TRUE;
7203 }
7204 else {
7205 VALUE cmd = check_pipe_command(tmp);
7206 if (!NIL_P(cmd)) {
7207 argv[0] = cmd;
7208 return rb_io_s_popen(argc, argv, rb_cIO);
7209 }
7210 }
7211 }
7212 }
7213 if (redirect) {
7214 VALUE io = rb_funcallv_kw(argv[0], to_open, argc-1, argv+1, RB_PASS_CALLED_KEYWORDS);
7215
7216 if (rb_block_given_p()) {
7217 return rb_ensure(rb_yield, io, io_close, io);
7218 }
7219 return io;
7220 }
7221 return rb_io_s_open(argc, argv, rb_cFile);
7222 }
7223
7224 static VALUE rb_io_open_generic(VALUE, VALUE, int, int, const convconfig_t *, mode_t);
7225
7226 static VALUE
7227 rb_io_open(VALUE io, VALUE filename, VALUE vmode, VALUE vperm, VALUE opt)
7228 {
7229 int oflags, fmode;
7230 convconfig_t convconfig;
7231 mode_t perm;
7232
7233 rb_io_extract_modeenc(&vmode, &vperm, opt, &oflags, &fmode, &convconfig);
7234 perm = NIL_P(vperm) ? 0666 : NUM2MODET(vperm);
7235 return rb_io_open_generic(io, filename, oflags, fmode, &convconfig, perm);
7236 }
7237
7238 static VALUE
7239 rb_io_open_generic(VALUE klass, VALUE filename, int oflags, int fmode,
7240 const convconfig_t *convconfig, mode_t perm)
7241 {
7242 VALUE cmd;
7243 if (klass == rb_cIO && !NIL_P(cmd = check_pipe_command(filename))) {
7244 return pipe_open_s(cmd, rb_io_oflags_modestr(oflags), fmode, convconfig);
7245 }
7246 else {
7247 return rb_file_open_generic(io_alloc(klass), filename,
7248 oflags, fmode, convconfig, perm);
7249 }
7250 }
7251
7252 static VALUE
7253 io_reopen(VALUE io, VALUE nfile)
7254 {
7255 rb_io_t *fptr, *orig;
7256 int fd, fd2;
7257 off_t pos = 0;
7258
7259 nfile = rb_io_get_io(nfile);
7260 GetOpenFile(io, fptr);
7261 GetOpenFile(nfile, orig);
7262
7263 if (fptr == orig) return io;
7264 if (IS_PREP_STDIO(fptr)) {
7265 if ((fptr->stdio_file == stdin && !(orig->mode & FMODE_READABLE)) ||
7266 (fptr->stdio_file == stdout && !(orig->mode & FMODE_WRITABLE)) ||
7267 (fptr->stdio_file == stderr && !(orig->mode & FMODE_WRITABLE))) {
7268 rb_raise(rb_eArgError,
7269 "%s can't change access mode from \"%s\" to \"%s\"",
7270 PREP_STDIO_NAME(fptr), rb_io_fmode_modestr(fptr->mode),
7271 rb_io_fmode_modestr(orig->mode));
7272 }
7273 }
7274 if (fptr->mode & FMODE_WRITABLE) {
7275 if (io_fflush(fptr) < 0)
7276 rb_sys_fail(0);
7277 }
7278 else {
7279 flush_before_seek(fptr);
7280 }
7281 if (orig->mode & FMODE_READABLE) {
7282 pos = io_tell(orig);
7283 }
7284 if (orig->mode & FMODE_WRITABLE) {
7285 if (io_fflush(orig) < 0)
7286 rb_sys_fail(0);
7287 }
7288
7289 /* copy rb_io_t structure */
7290 fptr->mode = orig->mode | (fptr->mode & FMODE_PREP);
7291 fptr->pid = orig->pid;
7292 fptr->lineno = orig->lineno;
7293 if (RTEST(orig->pathv)) fptr->pathv = orig->pathv;
7294 else if (!IS_PREP_STDIO(fptr)) fptr->pathv = Qnil;
7295 fptr_copy_finalizer(fptr, orig);
7296
7297 fd = fptr->fd;
7298 fd2 = orig->fd;
7299 if (fd != fd2) {
7300 if (IS_PREP_STDIO(fptr) || fd <= 2 || !fptr->stdio_file) {
7301 /* need to keep FILE objects of stdin, stdout and stderr */
7302 if (rb_cloexec_dup2(fd2, fd) < 0)
7303 rb_sys_fail_path(orig->pathv);
7304 rb_update_max_fd(fd);
7305 }
7306 else {
7307 fclose(fptr->stdio_file);
7308 fptr->stdio_file = 0;
7309 fptr->fd = -1;
7310 if (rb_cloexec_dup2(fd2, fd) < 0)
7311 rb_sys_fail_path(orig->pathv);
7312 rb_update_max_fd(fd);
7313 fptr->fd = fd;
7314 }
7315 rb_thread_fd_close(fd);
7316 if ((orig->mode & FMODE_READABLE) && pos >= 0) {
7317 if (io_seek(fptr, pos, SEEK_SET) < 0 && errno) {
7318 rb_sys_fail_path(fptr->pathv);
7319 }
7320 if (io_seek(orig, pos, SEEK_SET) < 0 && errno) {
7321 rb_sys_fail_path(orig->pathv);
7322 }
7323 }
7324 }
7325
7326 if (fptr->mode & FMODE_BINMODE) {
7327 rb_io_binmode(io);
7328 }
7329
7330 RBASIC_SET_CLASS(io, rb_obj_class(nfile));
7331 return io;
7332 }
7333
7334 #ifdef _WIN32
7335 int rb_freopen(VALUE fname, const char *mode, FILE *fp);
7336 #else
7337 static int
7338 rb_freopen(VALUE fname, const char *mode, FILE *fp)
7339 {
7340 if (!freopen(RSTRING_PTR(fname), mode, fp)) {
7341 RB_GC_GUARD(fname);
7342 return errno;
7343 }
7344 return 0;
7345 }
7346 #endif
7347
7348 /*
7349 * call-seq:
7350 * ios.reopen(other_IO) -> ios
7351 * ios.reopen(path, mode [, opt]) -> ios
7352 *
7353 * Reassociates <em>ios</em> with the I/O stream given in
7354 * <i>other_IO</i> or to a new stream opened on <i>path</i>. This may
7355 * dynamically change the actual class of this stream.
7356 * The +mode+ and +opt+ parameters accept the same values as IO.open.
7357 *
7358 * f1 = File.new("testfile")
7359 * f2 = File.new("testfile")
7360 * f2.readlines[0] #=> "This is line one\n"
7361 * f2.reopen(f1) #=> #<File:testfile>
7362 * f2.readlines[0] #=> "This is line one\n"
7363 */
7364
7365 static VALUE
7366 rb_io_reopen(int argc, VALUE *argv, VALUE file)
7367 {
7368 VALUE fname, nmode, opt;
7369 int oflags;
7370 rb_io_t *fptr;
7371
7372 if (rb_scan_args(argc, argv, "11:", &fname, &nmode, &opt) == 1) {
7373 VALUE tmp = rb_io_check_io(fname);
7374 if (!NIL_P(tmp)) {
7375 return io_reopen(file, tmp);
7376 }
7377 }
7378
7379 FilePathValue(fname);
7380 rb_io_taint_check(file);
7381 fptr = RFILE(file)->fptr;
7382 if (!fptr) {
7383 fptr = RFILE(file)->fptr = ZALLOC(rb_io_t);
7384 }
7385
7386 if (!NIL_P(nmode) || !NIL_P(opt)) {
7387 int fmode;
7388 convconfig_t convconfig;
7389
7390 rb_io_extract_modeenc(&nmode, 0, opt, &oflags, &fmode, &convconfig);
7391 if (IS_PREP_STDIO(fptr) &&
7392 ((fptr->mode & FMODE_READWRITE) & (fmode & FMODE_READWRITE)) !=
7393 (fptr->mode & FMODE_READWRITE)) {
7394 rb_raise(rb_eArgError,
7395 "%s can't change access mode from \"%s\" to \"%s\"",
7396 PREP_STDIO_NAME(fptr), rb_io_fmode_modestr(fptr->mode),
7397 rb_io_fmode_modestr(fmode));
7398 }
7399 fptr->mode = fmode;
7400 fptr->encs = convconfig;
7401 }
7402 else {
7403 oflags = rb_io_fmode_oflags(fptr->mode);
7404 }
7405
7406 fptr->pathv = fname;
7407 if (fptr->fd < 0) {
7408 fptr->fd = rb_sysopen(fptr->pathv, oflags, 0666);
7409 fptr->stdio_file = 0;
7410 return file;
7411 }
7412
7413 if (fptr->mode & FMODE_WRITABLE) {
7414 if (io_fflush(fptr) < 0)
7415 rb_sys_fail(0);
7416 }
7417 fptr->rbuf.off = fptr->rbuf.len = 0;
7418
7419 if (fptr->stdio_file) {
7420 int e = rb_freopen(rb_str_encode_ospath(fptr->pathv),
7421 rb_io_oflags_modestr(oflags),
7422 fptr->stdio_file);
7423 if (e) rb_syserr_fail_path(e, fptr->pathv);
7424 fptr->fd = fileno(fptr->stdio_file);
7425 rb_fd_fix_cloexec(fptr->fd);
7426 #ifdef USE_SETVBUF
7427 if (setvbuf(fptr->stdio_file, NULL, _IOFBF, 0) != 0)
7428 rb_warn("setvbuf() can't be honoured for %"PRIsVALUE, fptr->pathv);
7429 #endif
7430 if (fptr->stdio_file == stderr) {
7431 if (setvbuf(fptr->stdio_file, NULL, _IONBF, BUFSIZ) != 0)
7432 rb_warn("setvbuf() can't be honoured for %"PRIsVALUE, fptr->pathv);
7433 }
7434 else if (fptr->stdio_file == stdout && isatty(fptr->fd)) {
7435 if (setvbuf(fptr->stdio_file, NULL, _IOLBF, BUFSIZ) != 0)
7436 rb_warn("setvbuf() can't be honoured for %"PRIsVALUE, fptr->pathv);
7437 }
7438 }
7439 else {
7440 int tmpfd = rb_sysopen(fptr->pathv, oflags, 0666);
7441 int err = 0;
7442 if (rb_cloexec_dup2(tmpfd, fptr->fd) < 0)
7443 err = errno;
7444 (void)close(tmpfd);
7445 if (err) {
7446 rb_syserr_fail_path(err, fptr->pathv);
7447 }
7448 }
7449
7450 return file;
7451 }
7452
7453 /* :nodoc: */
7454 static VALUE
7455 rb_io_init_copy(VALUE dest, VALUE io)
7456 {
7457 rb_io_t *fptr, *orig;
7458 int fd;
7459 VALUE write_io;
7460 off_t pos;
7461
7462 io = rb_io_get_io(io);
7463 if (!OBJ_INIT_COPY(dest, io)) return dest;
7464 GetOpenFile(io, orig);
7465 MakeOpenFile(dest, fptr);
7466
7467 rb_io_flush(io);
7468
7469 /* copy rb_io_t structure */
7470 fptr->mode = orig->mode & ~FMODE_PREP;
7471 fptr->encs = orig->encs;
7472 fptr->pid = orig->pid;
7473 fptr->lineno = orig->lineno;
7474 if (!NIL_P(orig->pathv)) fptr->pathv = orig->pathv;
7475 fptr_copy_finalizer(fptr, orig);
7476
7477 fd = ruby_dup(orig->fd);
7478 fptr->fd = fd;
7479 pos = io_tell(orig);
7480 if (0 <= pos)
7481 io_seek(fptr, pos, SEEK_SET);
7482 if (fptr->mode & FMODE_BINMODE) {
7483 rb_io_binmode(dest);
7484 }
7485
7486 write_io = GetWriteIO(io);
7487 if (io != write_io) {
7488 write_io = rb_obj_dup(write_io);
7489 fptr->tied_io_for_writing = write_io;
7490 rb_ivar_set(dest, rb_intern("@tied_io_for_writing"), write_io);
7491 }
7492
7493 return dest;
7494 }
7495
7496 /*
7497 * call-seq:
7498 * ios.printf(format_string [, obj, ...]) -> nil
7499 *
7500 * Formats and writes to <em>ios</em>, converting parameters under
7501 * control of the format string. See Kernel#sprintf for details.
7502 */
7503
7504 VALUE
7505 rb_io_printf(int argc, const VALUE *argv, VALUE out)
7506 {
7507 rb_io_write(out, rb_f_sprintf(argc, argv));
7508 return Qnil;
7509 }
7510
7511 /*
7512 * call-seq:
7513 * printf(io, string [, obj ... ]) -> nil
7514 * printf(string [, obj ... ]) -> nil
7515 *
7516 * Equivalent to:
7517 * io.write(sprintf(string, obj, ...))
7518 * or
7519 * $stdout.write(sprintf(string, obj, ...))
7520 */
7521
7522 static VALUE
7523 rb_f_printf(int argc, VALUE *argv, VALUE _)
7524 {
7525 VALUE out;
7526
7527 if (argc == 0) return Qnil;
7528 if (RB_TYPE_P(argv[0], T_STRING)) {
7529 out = rb_stdout;
7530 }
7531 else {
7532 out = argv[0];
7533 argv++;
7534 argc--;
7535 }
7536 rb_io_write(out, rb_f_sprintf(argc, argv));
7537
7538 return Qnil;
7539 }
7540
7541 static void
7542 rb_output_fs_setter(VALUE val, ID id, VALUE *var)
7543 {
7544 rb_str_setter(val, id, &val);
7545 if (!NIL_P(val)) {
7546 rb_warn_deprecated("`$,'", NULL);
7547 }
7548 *var = val;
7549 }
7550
7551 /*
7552 * call-seq:
7553 * ios.print -> nil
7554 * ios.print(obj, ...) -> nil
7555 *
7556 * Writes the given object(s) to <em>ios</em>. Returns +nil+.
7557 *
7558 * The stream must be opened for writing.
7559 * Each given object that isn't a string will be converted by calling
7560 * its <code>to_s</code> method.
7561 * When called without arguments, prints the contents of <code>$_</code>.
7562 *
7563 * If the output field separator (<code>$,</code>) is not +nil+,
7564 * it is inserted between objects.
7565 * If the output record separator (<code>$\</code>) is not +nil+,
7566 * it is appended to the output.
7567 *
7568 * $stdout.print("This is ", 100, " percent.\n")
7569 *
7570 * <em>produces:</em>
7571 *
7572 * This is 100 percent.
7573 */
7574
7575 VALUE
7576 rb_io_print(int argc, const VALUE *argv, VALUE out)
7577 {
7578 int i;
7579 VALUE line;
7580
7581 /* if no argument given, print `$_' */
7582 if (argc == 0) {
7583 argc = 1;
7584 line = rb_lastline_get();
7585 argv = &line;
7586 }
7587 for (i=0; i<argc; i++) {
7588 if (!NIL_P(rb_output_fs) && i>0) {
7589 rb_io_write(out, rb_output_fs);
7590 }
7591 rb_io_write(out, argv[i]);
7592 }
7593 if (argc > 0 && !NIL_P(rb_output_rs)) {
7594 rb_io_write(out, rb_output_rs);
7595 }
7596
7597 return Qnil;
7598 }
7599
7600 /*
7601 * call-seq:
7602 * print(obj, ...) -> nil
7603 *
7604 * Prints each object in turn to <code>$stdout</code>. If the output
7605 * field separator (<code>$,</code>) is not +nil+, its
7606 * contents will appear between each field. If the output record
7607 * separator (<code>$\</code>) is not +nil+, it will be
7608 * appended to the output. If no arguments are given, prints
7609 * <code>$_</code>. Objects that aren't strings will be converted by
7610 * calling their <code>to_s</code> method.
7611 *
7612 * print "cat", [1,2,3], 99, "\n"
7613 * $, = ", "
7614 * $\ = "\n"
7615 * print "cat", [1,2,3], 99
7616 *
7617 * <em>produces:</em>
7618 *
7619 * cat12399
7620 * cat, 1, 2, 3, 99
7621 */
7622
7623 static VALUE
7624 rb_f_print(int argc, const VALUE *argv, VALUE _)
7625 {
7626 rb_io_print(argc, argv, rb_stdout);
7627 return Qnil;
7628 }
7629
7630 /*
7631 * call-seq:
7632 * ios.putc(obj) -> obj
7633 *
7634 * If <i>obj</i> is Numeric, write the character whose code is the
7635 * least-significant byte of <i>obj</i>. If <i>obj</i> is String,
7636 * write the first character of <i>obj</i> to <em>ios</em>. Otherwise,
7637 * raise TypeError.
7638 *
7639 * $stdout.putc "A"
7640 * $stdout.putc 65
7641 *
7642 * <em>produces:</em>
7643 *
7644 * AA
7645 */
7646
7647 static VALUE
7648 rb_io_putc(VALUE io, VALUE ch)
7649 {
7650 VALUE str;
7651 if (RB_TYPE_P(ch, T_STRING)) {
7652 str = rb_str_substr(ch, 0, 1);
7653 }
7654 else {
7655 char c = NUM2CHR(ch);
7656 str = rb_str_new(&c, 1);
7657 }
7658 rb_io_write(io, str);
7659 return ch;
7660 }
7661
7662 /*
7663 * call-seq:
7664 * putc(int) -> int
7665 *
7666 * Equivalent to:
7667 *
7668 * $stdout.putc(int)
7669 *
7670 * Refer to the documentation for IO#putc for important information regarding
7671 * multi-byte characters.
7672 */
7673
7674 static VALUE
7675 rb_f_putc(VALUE recv, VALUE ch)
7676 {
7677 if (recv == rb_stdout) {
7678 return rb_io_putc(recv, ch);
7679 }
7680 return rb_funcallv(rb_stdout, rb_intern("putc"), 1, &ch);
7681 }
7682
7683
7684 int
7685 rb_str_end_with_asciichar(VALUE str, int c)
7686 {
7687 long len = RSTRING_LEN(str);
7688 const char *ptr = RSTRING_PTR(str);
7689 rb_encoding *enc = rb_enc_from_index(ENCODING_GET(str));
7690 int n;
7691
7692 if (len == 0) return 0;
7693 if ((n = rb_enc_mbminlen(enc)) == 1) {
7694 return ptr[len - 1] == c;
7695 }
7696 return rb_enc_ascget(ptr + ((len - 1) / n) * n, ptr + len, &n, enc) == c;
7697 }
7698
7699 static VALUE
7700 io_puts_ary(VALUE ary, VALUE out, int recur)
7701 {
7702 VALUE tmp;
7703 long i;
7704
7705 if (recur) {
7706 tmp = rb_str_new2("[...]");
7707 rb_io_puts(1, &tmp, out);
7708 return Qtrue;
7709 }
7710 ary = rb_check_array_type(ary);
7711 if (NIL_P(ary)) return Qfalse;
7712 for (i=0; i<RARRAY_LEN(ary); i++) {
7713 tmp = RARRAY_AREF(ary, i);
7714 rb_io_puts(1, &tmp, out);
7715 }
7716 return Qtrue;
7717 }
7718
7719 /*
7720 * call-seq:
7721 * ios.puts(obj, ...) -> nil
7722 *
7723 * Writes the given object(s) to <em>ios</em>.
7724 * Writes a newline after any that do not already end
7725 * with a newline sequence. Returns +nil+.
7726 *
7727 * The stream must be opened for writing.
7728 * If called with an array argument, writes each element on a new line.
7729 * Each given object that isn't a string or array will be converted
7730 * by calling its +to_s+ method.
7731 * If called without arguments, outputs a single newline.
7732 *
7733 * $stdout.puts("this", "is", ["a", "test"])
7734 *
7735 * <em>produces:</em>
7736 *
7737 * this
7738 * is
7739 * a
7740 * test
7741 *
7742 * Note that +puts+ always uses newlines and is not affected
7743 * by the output record separator (<code>$\</code>).
7744 */
7745
7746 VALUE
7747 rb_io_puts(int argc, const VALUE *argv, VALUE out)
7748 {
7749 int i, n;
7750 VALUE line, args[2];
7751
7752 /* if no argument given, print newline. */
7753 if (argc == 0) {
7754 rb_io_write(out, rb_default_rs);
7755 return Qnil;
7756 }
7757 for (i=0; i<argc; i++) {
7758 if (RB_TYPE_P(argv[i], T_STRING)) {
7759 line = argv[i];
7760 goto string;
7761 }
7762 if (rb_exec_recursive(io_puts_ary, argv[i], out)) {
7763 continue;
7764 }
7765 line = rb_obj_as_string(argv[i]);
7766 string:
7767 n = 0;
7768 args[n++] = line;
7769 if (RSTRING_LEN(line) == 0 ||
7770 !rb_str_end_with_asciichar(line, '\n')) {
7771 args[n++] = rb_default_rs;
7772 }
7773 rb_io_writev(out, n, args);
7774 }
7775
7776 return Qnil;
7777 }
7778
7779 /*
7780 * call-seq:
7781 * puts(obj, ...) -> nil
7782 *
7783 * Equivalent to
7784 *
7785 * $stdout.puts(obj, ...)
7786 */
7787
7788 static VALUE
7789 rb_f_puts(int argc, VALUE *argv, VALUE recv)
7790 {
7791 if (recv == rb_stdout) {
7792 return rb_io_puts(argc, argv, recv);
7793 }
7794 return rb_funcallv(rb_stdout, rb_intern("puts"), argc, argv);
7795 }
7796
7797 void
7798 rb_p(VALUE obj) /* for debug print within C code */
7799 {
7800 VALUE args[2];
7801 args[0] = rb_obj_as_string(rb_inspect(obj));
7802 args[1] = rb_default_rs;
7803 if (RB_TYPE_P(rb_stdout, T_FILE) &&
7804 rb_method_basic_definition_p(CLASS_OF(rb_stdout), id_write)) {
7805 io_writev(2, args, rb_stdout);
7806 }
7807 else {
7808 rb_io_writev(rb_stdout, 2, args);
7809 }
7810 }
7811
7812 struct rb_f_p_arg {
7813 int argc;
7814 VALUE *argv;
7815 };
7816
7817 static VALUE
7818 rb_f_p_internal(VALUE arg)
7819 {
7820 struct rb_f_p_arg *arg1 = (struct rb_f_p_arg*)arg;
7821 int argc = arg1->argc;
7822 VALUE *argv = arg1->argv;
7823 int i;
7824 VALUE ret = Qnil;
7825
7826 for (i=0; i<argc; i++) {
7827 rb_p(argv[i]);
7828 }
7829 if (argc == 1) {
7830 ret = argv[0];
7831 }
7832 else if (argc > 1) {
7833 ret = rb_ary_new4(argc, argv);
7834 }
7835 if (RB_TYPE_P(rb_stdout, T_FILE)) {
7836 rb_io_flush(rb_stdout);
7837 }
7838 return ret;
7839 }
7840
7841 /*
7842 * call-seq:
7843 * p(obj) -> obj
7844 * p(obj1, obj2, ...) -> [obj, ...]
7845 * p() -> nil
7846 *
7847 * For each object, directly writes _obj_.+inspect+ followed by a
7848 * newline to the program's standard output.
7849 *
7850 * S = Struct.new(:name, :state)
7851 * s = S['dave', 'TX']
7852 * p s
7853 *
7854 * <em>produces:</em>
7855 *
7856 * #<S name="dave", state="TX">
7857 */
7858
7859 static VALUE
7860 rb_f_p(int argc, VALUE *argv, VALUE self)
7861 {
7862 struct rb_f_p_arg arg;
7863 arg.argc = argc;
7864 arg.argv = argv;
7865
7866 return rb_uninterruptible(rb_f_p_internal, (VALUE)&arg);
7867 }
7868
7869 /*
7870 * call-seq:
7871 * obj.display(port=$>) -> nil
7872 *
7873 * Prints <i>obj</i> on the given port (default <code>$></code>).
7874 * Equivalent to:
7875 *
7876 * def display(port=$>)
7877 * port.write self
7878 * nil
7879 * end
7880 *
7881 * For example:
7882 *
7883 * 1.display
7884 * "cat".display
7885 * [ 4, 5, 6 ].display
7886 * puts
7887 *
7888 * <em>produces:</em>
7889 *
7890 * 1cat[4, 5, 6]
7891 */
7892
7893 static VALUE
7894 rb_obj_display(int argc, VALUE *argv, VALUE self)
7895 {
7896 VALUE out;
7897
7898 out = (!rb_check_arity(argc, 0, 1) ? rb_stdout : argv[0]);
7899 rb_io_write(out, self);
7900
7901 return Qnil;
7902 }
7903
7904 static int
7905 rb_stderr_to_original_p(void)
7906 {
7907 return (rb_stderr == orig_stderr || RFILE(orig_stderr)->fptr->fd < 0);
7908 }
7909
7910 void
7911 rb_write_error2(const char *mesg, long len)
7912 {
7913 if (rb_stderr_to_original_p()) {
7914 #ifdef _WIN32
7915 if (isatty(fileno(stderr))) {
7916 if (rb_w32_write_console(rb_str_new(mesg, len), fileno(stderr)) > 0) return;
7917 }
7918 #endif
7919 if (fwrite(mesg, sizeof(char), (size_t)len, stderr) < (size_t)len) {
7920 /* failed to write to stderr, what can we do? */
7921 return;
7922 }
7923 }
7924 else {
7925 rb_io_write(rb_stderr, rb_str_new(mesg, len));
7926 }
7927 }
7928
7929 void
7930 rb_write_error(const char *mesg)
7931 {
7932 rb_write_error2(mesg, strlen(mesg));
7933 }
7934
7935 void
7936 rb_write_error_str(VALUE mesg)
7937 {
7938 /* a stopgap measure for the time being */
7939 if (rb_stderr_to_original_p()) {
7940 size_t len = (size_t)RSTRING_LEN(mesg);
7941 #ifdef _WIN32
7942 if (isatty(fileno(stderr))) {
7943 if (rb_w32_write_console(mesg, fileno(stderr)) > 0) return;
7944 }
7945 #endif
7946 if (fwrite(RSTRING_PTR(mesg), sizeof(char), len, stderr) < len) {
7947 RB_GC_GUARD(mesg);
7948 return;
7949 }
7950 }
7951 else {
7952 /* may unlock GVL, and */
7953 rb_io_write(rb_stderr, mesg);
7954 }
7955 }
7956
7957 int
7958 rb_stderr_tty_p(void)
7959 {
7960 if (rb_stderr_to_original_p())
7961 return isatty(fileno(stderr));
7962 return 0;
7963 }
7964
7965 static void
7966 must_respond_to(ID mid, VALUE val, ID id)
7967 {
7968 if (!rb_respond_to(val, mid)) {
7969 rb_raise(rb_eTypeError, "%"PRIsVALUE" must have %"PRIsVALUE" method, %"PRIsVALUE" given",
7970 rb_id2str(id), rb_id2str(mid),
7971 rb_obj_class(val));
7972 }
7973 }
7974
7975 static void
7976 stdout_setter(VALUE val, ID id, VALUE *variable)
7977 {
7978 must_respond_to(id_write, val, id);
7979 *variable = val;
7980 }
7981
7982 static VALUE
7983 prep_io(int fd, int fmode, VALUE klass, const char *path)
7984 {
7985 rb_io_t *fp;
7986 VALUE io = io_alloc(klass);
7987
7988 MakeOpenFile(io, fp);
7989 fp->fd = fd;
7990 fp->mode = fmode;
7991 if (!io_check_tty(fp)) {
7992 #ifdef __CYGWIN__
7993 fp->mode |= FMODE_BINMODE;
7994 setmode(fd, O_BINARY);
7995 #endif
7996 }
7997 if (path) fp->pathv = rb_obj_freeze(rb_str_new_cstr(path));
7998 rb_update_max_fd(fd);
7999
8000 return io;
8001 }
8002
8003 VALUE
8004 rb_io_fdopen(int fd, int oflags, const char *path)
8005 {
8006 VALUE klass = rb_cIO;
8007
8008 if (path && strcmp(path, "-")) klass = rb_cFile;
8009 return prep_io(fd, rb_io_oflags_fmode(oflags), klass, path);
8010 }
8011
8012 static VALUE
8013 prep_stdio(FILE *f, int fmode, VALUE klass, const char *path)
8014 {
8015 rb_io_t *fptr;
8016 VALUE io = prep_io(fileno(f), fmode|FMODE_PREP|DEFAULT_TEXTMODE, klass, path);
8017
8018 GetOpenFile(io, fptr);
8019 fptr->encs.ecflags |= ECONV_DEFAULT_NEWLINE_DECORATOR;
8020 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
8021 fptr->encs.ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
8022 if (fmode & FMODE_READABLE) {
8023 fptr->encs.ecflags |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;
8024 }
8025 #endif
8026 fptr->stdio_file = f;
8027
8028 return io;
8029 }
8030
8031 FILE *
8032 rb_io_stdio_file(rb_io_t *fptr)
8033 {
8034 if (!fptr->stdio_file) {
8035 int oflags = rb_io_fmode_oflags(fptr->mode) & ~O_EXCL;
8036 fptr->stdio_file = rb_fdopen(fptr->fd, rb_io_oflags_modestr(oflags));
8037 }
8038 return fptr->stdio_file;
8039 }
8040
8041 static inline void
8042 rb_io_buffer_init(rb_io_buffer_t *buf)
8043 {
8044 buf->ptr = NULL;
8045 buf->off = 0;
8046 buf->len = 0;
8047 buf->capa = 0;
8048 }
8049
8050 static inline rb_io_t *
8051 rb_io_fptr_new(void)
8052 {
8053 rb_io_t *fp = ALLOC(rb_io_t);
8054 fp->fd = -1;
8055 fp->stdio_file = NULL;
8056 fp->mode = 0;
8057 fp->pid = 0;
8058 fp->lineno = 0;
8059 fp->pathv = Qnil;
8060 fp->finalize = 0;
8061 rb_io_buffer_init(&fp->wbuf);
8062 rb_io_buffer_init(&fp->rbuf);
8063 rb_io_buffer_init(&fp->cbuf);
8064 fp->readconv = NULL;
8065 fp->writeconv = NULL;
8066 fp->writeconv_asciicompat = Qnil;
8067 fp->writeconv_pre_ecflags = 0;
8068 fp->writeconv_pre_ecopts = Qnil;
8069 fp->writeconv_initialized = 0;
8070 fp->tied_io_for_writing = 0;
8071 fp->encs.enc = NULL;
8072 fp->encs.enc2 = NULL;
8073 fp->encs.ecflags = 0;
8074 fp->encs.ecopts = Qnil;
8075 fp->write_lock = 0;
8076 return fp;
8077 }
8078
8079 rb_io_t *
8080 rb_io_make_open_file(VALUE obj)
8081 {
8082 rb_io_t *fp = 0;
8083
8084 Check_Type(obj, T_FILE);
8085 if (RFILE(obj)->fptr) {
8086 rb_io_close(obj);
8087 rb_io_fptr_finalize(RFILE(obj)->fptr);
8088 RFILE(obj)->fptr = 0;
8089 }
8090 fp = rb_io_fptr_new();
8091 RFILE(obj)->fptr = fp;
8092 return fp;
8093 }
8094
8095 /*
8096 * call-seq:
8097 * IO.new(fd [, mode] [, opt]) -> io
8098 *
8099 * Returns a new IO object (a stream) for the given integer file descriptor
8100 * +fd+ and +mode+ string. +opt+ may be used to specify parts of +mode+ in a
8101 * more readable fashion. See also IO.sysopen and IO.for_fd.
8102 *
8103 * IO.new is called by various File and IO opening methods such as IO::open,
8104 * Kernel#open, and File::open.
8105 *
8106 * === Open Mode
8107 *
8108 * When +mode+ is an integer it must be combination of the modes defined in
8109 * File::Constants (+File::RDONLY+, <code>File::WRONLY|File::CREAT</code>).
8110 * See the open(2) man page for more information.
8111 *
8112 * When +mode+ is a string it must be in one of the following forms:
8113 *
8114 * fmode
8115 * fmode ":" ext_enc
8116 * fmode ":" ext_enc ":" int_enc
8117 * fmode ":" "BOM|UTF-*"
8118 *
8119 * +fmode+ is an IO open mode string, +ext_enc+ is the external encoding for
8120 * the IO and +int_enc+ is the internal encoding.
8121 *
8122 * ==== IO Open Mode
8123 *
8124 * Ruby allows the following open modes:
8125 *
8126 * "r" Read-only, starts at beginning of file (default mode).
8127 *
8128 * "r+" Read-write, starts at beginning of file.
8129 *
8130 * "w" Write-only, truncates existing file
8131 * to zero length or creates a new file for writing.
8132 *
8133 * "w+" Read-write, truncates existing file to zero length
8134 * or creates a new file for reading and writing.
8135 *
8136 * "a" Write-only, each write call appends data at end of file.
8137 * Creates a new file for writing if file does not exist.
8138 *
8139 * "a+" Read-write, each write call appends data at end of file.
8140 * Creates a new file for reading and writing if file does
8141 * not exist.
8142 *
8143 * The following modes must be used separately, and along with one or more of
8144 * the modes seen above.
8145 *
8146 * "b" Binary file mode
8147 * Suppresses EOL <-> CRLF conversion on Windows. And
8148 * sets external encoding to ASCII-8BIT unless explicitly
8149 * specified.
8150 *
8151 * "t" Text file mode
8152 *
8153 * The exclusive access mode ("x") can be used together with "w" to ensure
8154 * the file is created. Errno::EEXIST is raised when it already exists.
8155 * It may not be supported with all kinds of streams (e.g. pipes).
8156 *
8157 * When the open mode of original IO is read only, the mode cannot be
8158 * changed to be writable. Similarly, the open mode cannot be changed from
8159 * write only to readable.
8160 *
8161 * When such a change is attempted the error is raised in different locations
8162 * according to the platform.
8163 *
8164 * === IO Encoding
8165 *
8166 * When +ext_enc+ is specified, strings read will be tagged by the encoding
8167 * when reading, and strings output will be converted to the specified
8168 * encoding when writing.
8169 *
8170 * When +ext_enc+ and +int_enc+ are specified read strings will be converted
8171 * from +ext_enc+ to +int_enc+ upon input, and written strings will be
8172 * converted from +int_enc+ to +ext_enc+ upon output. See Encoding for
8173 * further details of transcoding on input and output.
8174 *
8175 * If "BOM|UTF-8", "BOM|UTF-16LE" or "BOM|UTF16-BE" are used, Ruby checks for
8176 * a Unicode BOM in the input document to help determine the encoding. For
8177 * UTF-16 encodings the file open mode must be binary. When present, the BOM
8178 * is stripped and the external encoding from the BOM is used. When the BOM
8179 * is missing the given Unicode encoding is used as +ext_enc+. (The BOM-set
8180 * encoding option is case insensitive, so "bom|utf-8" is also valid.)
8181 *
8182 * === Options
8183 *
8184 * +opt+ can be used instead of +mode+ for improved readability. The
8185 * following keys are supported:
8186 *
8187 * :mode ::
8188 * Same as +mode+ parameter
8189 *
8190 * :flags ::
8191 * Specifies file open flags as integer.
8192 * If +mode+ parameter is given, this parameter will be bitwise-ORed.
8193 *
8194 * :\external_encoding ::
8195 * External encoding for the IO.
8196 *
8197 * :\internal_encoding ::
8198 * Internal encoding for the IO. "-" is a synonym for the default internal
8199 * encoding.
8200 *
8201 * If the value is +nil+ no conversion occurs.
8202 *
8203 * :encoding ::
8204 * Specifies external and internal encodings as "extern:intern".
8205 *
8206 * :textmode ::
8207 * If the value is truth value, same as "t" in argument +mode+.
8208 *
8209 * :binmode ::
8210 * If the value is truth value, same as "b" in argument +mode+.
8211 *
8212 * :autoclose ::
8213 * If the value is +false+, the +fd+ will be kept open after this IO
8214 * instance gets finalized.
8215 *
8216 * Also, +opt+ can have same keys in String#encode for controlling conversion
8217 * between the external encoding and the internal encoding.
8218 *
8219 * === Example 1
8220 *
8221 * fd = IO.sysopen("/dev/tty", "w")
8222 * a = IO.new(fd,"w")
8223 * $stderr.puts "Hello"
8224 * a.puts "World"
8225 *
8226 * Produces:
8227 *
8228 * Hello
8229 * World
8230 *
8231 * === Example 2
8232 *
8233 * require 'fcntl'
8234 *
8235 * fd = STDERR.fcntl(Fcntl::F_DUPFD)
8236 * io = IO.new(fd, mode: 'w:UTF-16LE', cr_newline: true)
8237 * io.puts "Hello, World!"
8238 *
8239 * fd = STDERR.fcntl(Fcntl::F_DUPFD)
8240 * io = IO.new(fd, mode: 'w', cr_newline: true,
8241 * external_encoding: Encoding::UTF_16LE)
8242 * io.puts "Hello, World!"
8243 *
8244 * Both of above print "Hello, World!" in UTF-16LE to standard error output
8245 * with converting EOL generated by #puts to CR.
8246 */
8247
8248 static VALUE
8249 rb_io_initialize(int argc, VALUE *argv, VALUE io)
8250 {
8251 VALUE fnum, vmode;
8252 rb_io_t *fp;
8253 int fd, fmode, oflags = O_RDONLY;
8254 convconfig_t convconfig;
8255 VALUE opt;
8256 #if defined(HAVE_FCNTL) && defined(F_GETFL)
8257 int ofmode;
8258 #else
8259 struct stat st;
8260 #endif
8261
8262
8263 argc = rb_scan_args(argc, argv, "11:", &fnum, &vmode, &opt);
8264 rb_io_extract_modeenc(&vmode, 0, opt, &oflags, &fmode, &convconfig);
8265
8266 fd = NUM2INT(fnum);
8267 if (rb_reserved_fd_p(fd)) {
8268 rb_raise(rb_eArgError, "The given fd is not accessible because RubyVM reserves it");
8269 }
8270 #if defined(HAVE_FCNTL) && defined(F_GETFL)
8271 oflags = fcntl(fd, F_GETFL);
8272 if (oflags == -1) rb_sys_fail(0);
8273 #else
8274 if (fstat(fd, &st) < 0) rb_sys_fail(0);
8275 #endif
8276 rb_update_max_fd(fd);
8277 #if defined(HAVE_FCNTL) && defined(F_GETFL)
8278 ofmode = rb_io_oflags_fmode(oflags);
8279 if (NIL_P(vmode)) {
8280 fmode = ofmode;
8281 }
8282 else if ((~ofmode & fmode) & FMODE_READWRITE) {
8283 VALUE error = INT2FIX(EINVAL);
8284 rb_exc_raise(rb_class_new_instance(1, &error, rb_eSystemCallError));
8285 }
8286 #endif
8287 if (!NIL_P(opt) && rb_hash_aref(opt, sym_autoclose) == Qfalse) {
8288 fmode |= FMODE_PREP;
8289 }
8290 MakeOpenFile(io, fp);
8291 fp->fd = fd;
8292 fp->mode = fmode;
8293 fp->encs = convconfig;
8294 clear_codeconv(fp);
8295 io_check_tty(fp);
8296 if (fileno(stdin) == fd)
8297 fp->stdio_file = stdin;
8298 else if (fileno(stdout) == fd)
8299 fp->stdio_file = stdout;
8300 else if (fileno(stderr) == fd)
8301 fp->stdio_file = stderr;
8302
8303 if (fmode & FMODE_SETENC_BY_BOM) io_set_encoding_by_bom(io);
8304 return io;
8305 }
8306
8307 /*
8308 * call-seq:
8309 * ios.set_encoding_by_bom -> encoding or nil
8310 *
8311 * Checks if +ios+ starts with a BOM, and then consumes it and sets
8312 * the external encoding. Returns the result encoding if found, or
8313 * nil. If +ios+ is not binmode or its encoding has been set
8314 * already, an exception will be raised.
8315 *
8316 * File.write("bom.txt", "\u{FEFF}abc")
8317 * ios = File.open("bom.txt", "rb")
8318 * ios.set_encoding_by_bom #=> #<Encoding:UTF-8>
8319 *
8320 * File.write("nobom.txt", "abc")
8321 * ios = File.open("nobom.txt", "rb")
8322 * ios.set_encoding_by_bom #=> nil
8323 */
8324
8325 static VALUE
8326 rb_io_set_encoding_by_bom(VALUE io)
8327 {
8328 rb_io_t *fptr;
8329
8330 GetOpenFile(io, fptr);
8331 if (!(fptr->mode & FMODE_BINMODE)) {
8332 rb_raise(rb_eArgError, "ASCII incompatible encoding needs binmode");
8333 }
8334 if (fptr->encs.enc2) {
8335 rb_raise(rb_eArgError, "encoding conversion is set");
8336 }
8337 else if (fptr->encs.enc && fptr->encs.enc != rb_ascii8bit_encoding()) {
8338 rb_raise(rb_eArgError, "encoding is set to %s already",
8339 rb_enc_name(fptr->encs.enc));
8340 }
8341 if (!io_set_encoding_by_bom(io)) return Qnil;
8342 return rb_enc_from_encoding(fptr->encs.enc);
8343 }
8344
8345 /*
8346 * call-seq:
8347 * File.new(filename, mode="r" [, opt]) -> file
8348 * File.new(filename [, mode [, perm]] [, opt]) -> file
8349 *
8350 * Opens the file named by +filename+ according to the given +mode+ and
8351 * returns a new File object.
8352 *
8353 * See IO.new for a description of +mode+ and +opt+.
8354 *
8355 * If a file is being created, permission bits may be given in +perm+. These
8356 * mode and permission bits are platform dependent; on Unix systems, see
8357 * open(2) and chmod(2) man pages for details.
8358 *
8359 * The new File object is buffered mode (or non-sync mode), unless
8360 * +filename+ is a tty.
8361 * See IO#flush, IO#fsync, IO#fdatasync, and IO#sync= about sync mode.
8362 *
8363 * === Examples
8364 *
8365 * f = File.new("testfile", "r")
8366 * f = File.new("newfile", "w+")
8367 * f = File.new("newfile", File::CREAT|File::TRUNC|File::RDWR, 0644)
8368 */
8369
8370 static VALUE
8371 rb_file_initialize(int argc, VALUE *argv, VALUE io)
8372 {
8373 if (RFILE(io)->fptr) {
8374 rb_raise(rb_eRuntimeError, "reinitializing File");
8375 }
8376 if (0 < argc && argc < 3) {
8377 VALUE fd = rb_check_to_int(argv[0]);
8378
8379 if (!NIL_P(fd)) {
8380 argv[0] = fd;
8381 return rb_io_initialize(argc, argv, io);
8382 }
8383 }
8384 rb_open_file(argc, argv, io);
8385
8386 return io;
8387 }
8388
8389 /* :nodoc: */
8390 static VALUE
8391 rb_io_s_new(int argc, VALUE *argv, VALUE klass)
8392 {
8393 if (rb_block_given_p()) {
8394 VALUE cname = rb_obj_as_string(klass);
8395
8396 rb_warn("%"PRIsVALUE"::new() does not take block; use %"PRIsVALUE"::open() instead",
8397 cname, cname);
8398 }
8399 return rb_class_new_instance_kw(argc, argv, klass, RB_PASS_CALLED_KEYWORDS);
8400 }
8401
8402
8403 /*
8404 * call-seq:
8405 * IO.for_fd(fd, mode [, opt]) -> io
8406 *
8407 * Synonym for IO.new.
8408 *
8409 */
8410
8411 static VALUE
8412 rb_io_s_for_fd(int argc, VALUE *argv, VALUE klass)
8413 {
8414 VALUE io = rb_obj_alloc(klass);
8415 rb_io_initialize(argc, argv, io);
8416 return io;
8417 }
8418
8419 /*
8420 * call-seq:
8421 * ios.autoclose? -> true or false
8422 *
8423 * Returns +true+ if the underlying file descriptor of _ios_ will be
8424 * closed automatically at its finalization, otherwise +false+.
8425 */
8426
8427 static VALUE
8428 rb_io_autoclose_p(VALUE io)
8429 {
8430 rb_io_t *fptr = RFILE(io)->fptr;
8431 rb_io_check_closed(fptr);
8432 return (fptr->mode & FMODE_PREP) ? Qfalse : Qtrue;
8433 }
8434
8435 /*
8436 * call-seq:
8437 * io.autoclose = bool -> true or false
8438 *
8439 * Sets auto-close flag.
8440 *
8441 * f = open("/dev/null")
8442 * IO.for_fd(f.fileno)
8443 * # ...
8444 * f.gets # may cause Errno::EBADF
8445 *
8446 * f = open("/dev/null")
8447 * IO.for_fd(f.fileno).autoclose = false
8448 * # ...
8449 * f.gets # won't cause Errno::EBADF
8450 */
8451
8452 static VALUE
8453 rb_io_set_autoclose(VALUE io, VALUE autoclose)
8454 {
8455 rb_io_t *fptr;
8456 GetOpenFile(io, fptr);
8457 if (!RTEST(autoclose))
8458 fptr->mode |= FMODE_PREP;
8459 else
8460 fptr->mode &= ~FMODE_PREP;
8461 return autoclose;
8462 }
8463
8464 static void
8465 argf_mark(void *ptr)
8466 {
8467 struct argf *p = ptr;
8468 rb_gc_mark(p->filename);
8469 rb_gc_mark(p->current_file);
8470 rb_gc_mark(p->argv);
8471 rb_gc_mark(p->inplace);
8472 rb_gc_mark(p->encs.ecopts);
8473 }
8474
8475 static size_t
8476 argf_memsize(const void *ptr)
8477 {
8478 const struct argf *p = ptr;
8479 size_t size = sizeof(*p);
8480 return size;
8481 }
8482
8483 static const rb_data_type_t argf_type = {
8484 "ARGF",
8485 {argf_mark, RUBY_TYPED_DEFAULT_FREE, argf_memsize},
8486 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
8487 };
8488
8489 static inline void
8490 argf_init(struct argf *p, VALUE v)
8491 {
8492 p->filename = Qnil;
8493 p->current_file = Qnil;
8494 p->lineno = 0;
8495 p->argv = v;
8496 }
8497
8498 static VALUE
8499 argf_alloc(VALUE klass)
8500 {
8501 struct argf *p;
8502 VALUE argf = TypedData_Make_Struct(klass, struct argf, &argf_type, p);
8503
8504 argf_init(p, Qnil);
8505 return argf;
8506 }
8507
8508 #undef rb_argv
8509
8510 /* :nodoc: */
8511 static VALUE
8512 argf_initialize(VALUE argf, VALUE argv)
8513 {
8514 memset(&ARGF, 0, sizeof(ARGF));
8515 argf_init(&ARGF, argv);
8516
8517 return argf;
8518 }
8519
8520 /* :nodoc: */
8521 static VALUE
8522 argf_initialize_copy(VALUE argf, VALUE orig)
8523 {
8524 if (!OBJ_INIT_COPY(argf, orig)) return argf;
8525 ARGF = argf_of(orig);
8526 ARGF.argv = rb_obj_dup(ARGF.argv);
8527 return argf;
8528 }
8529
8530 /*
8531 * call-seq:
8532 * ARGF.lineno = integer -> integer
8533 *
8534 * Sets the line number of +ARGF+ as a whole to the given +Integer+.
8535 *
8536 * +ARGF+ sets the line number automatically as you read data, so normally
8537 * you will not need to set it explicitly. To access the current line number
8538 * use +ARGF.lineno+.
8539 *
8540 * For example:
8541 *
8542 * ARGF.lineno #=> 0
8543 * ARGF.readline #=> "This is line 1\n"
8544 * ARGF.lineno #=> 1
8545 * ARGF.lineno = 0 #=> 0
8546 * ARGF.lineno #=> 0
8547 */
8548 static VALUE
8549 argf_set_lineno(VALUE argf, VALUE val)
8550 {
8551 ARGF.lineno = NUM2INT(val);
8552 ARGF.last_lineno = ARGF.lineno;
8553 return Qnil;
8554 }
8555
8556 /*
8557 * call-seq:
8558 * ARGF.lineno -> integer
8559 *
8560 * Returns the current line number of ARGF as a whole. This value
8561 * can be set manually with +ARGF.lineno=+.
8562 *
8563 * For example:
8564 *
8565 * ARGF.lineno #=> 0
8566 * ARGF.readline #=> "This is line 1\n"
8567 * ARGF.lineno #=> 1
8568 */
8569 static VALUE
8570 argf_lineno(VALUE argf)
8571 {
8572 return INT2FIX(ARGF.lineno);
8573 }
8574
8575 static VALUE
8576 argf_forward(int argc, VALUE *argv, VALUE argf)
8577 {
8578 return rb_funcall3(ARGF.current_file, rb_frame_this_func(), argc, argv);
8579 }
8580
8581 #define next_argv() argf_next_argv(argf)
8582 #define ARGF_GENERIC_INPUT_P() \
8583 (ARGF.current_file == rb_stdin && !RB_TYPE_P(ARGF.current_file, T_FILE))
8584 #define ARGF_FORWARD(argc, argv) do {\
8585 if (ARGF_GENERIC_INPUT_P())\
8586 return argf_forward((argc), (argv), argf);\
8587 } while (0)
8588 #define NEXT_ARGF_FORWARD(argc, argv) do {\
8589 if (!next_argv()) return Qnil;\
8590 ARGF_FORWARD((argc), (argv));\
8591 } while (0)
8592
8593 static void
8594 argf_close(VALUE argf)
8595 {
8596 VALUE file = ARGF.current_file;
8597 if (file == rb_stdin) return;
8598 if (RB_TYPE_P(file, T_FILE)) {
8599 rb_io_set_write_io(file, Qnil);
8600 }
8601 io_close(file);
8602 ARGF.init_p = -1;
8603 }
8604
8605 static int
8606 argf_next_argv(VALUE argf)
8607 {
8608 char *fn;
8609 rb_io_t *fptr;
8610 int stdout_binmode = 0;
8611 int fmode;
8612
8613 if (RB_TYPE_P(rb_stdout, T_FILE)) {
8614 GetOpenFile(rb_stdout, fptr);
8615 if (fptr->mode & FMODE_BINMODE)
8616 stdout_binmode = 1;
8617 }
8618
8619 if (ARGF.init_p == 0) {
8620 if (!NIL_P(ARGF.argv) && RARRAY_LEN(ARGF.argv) > 0) {
8621 ARGF.next_p = 1;
8622 }
8623 else {
8624 ARGF.next_p = -1;
8625 }
8626 ARGF.init_p = 1;
8627 }
8628 else {
8629 if (NIL_P(ARGF.argv)) {
8630 ARGF.next_p = -1;
8631 }
8632 else if (ARGF.next_p == -1 && RARRAY_LEN(ARGF.argv) > 0) {
8633 ARGF.next_p = 1;
8634 }
8635 }
8636
8637 if (ARGF.next_p == 1) {
8638 if (ARGF.init_p == 1) argf_close(argf);
8639 retry:
8640 if (RARRAY_LEN(ARGF.argv) > 0) {
8641 VALUE filename = rb_ary_shift(ARGF.argv);
8642 FilePathValue(filename);
8643 ARGF.filename = filename;
8644 filename = rb_str_encode_ospath(filename);
8645 fn = StringValueCStr(filename);
8646 if (RSTRING_LEN(filename) == 1 && fn[0] == '-') {
8647 ARGF.current_file = rb_stdin;
8648 if (ARGF.inplace) {
8649 rb_warn("Can't do inplace edit for stdio; skipping");
8650 goto retry;
8651 }
8652 }
8653 else {
8654 VALUE write_io = Qnil;
8655 int fr = rb_sysopen(filename, O_RDONLY, 0);
8656
8657 if (ARGF.inplace) {
8658 struct stat st;
8659 #ifndef NO_SAFE_RENAME
8660 struct stat st2;
8661 #endif
8662 VALUE str;
8663 int fw;
8664
8665 if (RB_TYPE_P(rb_stdout, T_FILE) && rb_stdout != orig_stdout) {
8666 rb_io_close(rb_stdout);
8667 }
8668 fstat(fr, &st);
8669 str = filename;
8670 if (!NIL_P(ARGF.inplace)) {
8671 VALUE suffix = ARGF.inplace;
8672 str = rb_str_dup(str);
8673 if (NIL_P(rb_str_cat_conv_enc_opts(str, RSTRING_LEN(str),
8674 RSTRING_PTR(suffix), RSTRING_LEN(suffix),
8675 rb_enc_get(suffix), 0, Qnil))) {
8676 rb_str_append(str, suffix);
8677 }
8678 #ifdef NO_SAFE_RENAME
8679 (void)close(fr);
8680 (void)unlink(RSTRING_PTR(str));
8681 if (rename(fn, RSTRING_PTR(str)) < 0) {
8682 rb_warn("Can't rename %"PRIsVALUE" to %"PRIsVALUE": %s, skipping file",
8683 filename, str, strerror(errno));
8684 goto retry;
8685 }
8686 fr = rb_sysopen(str, O_RDONLY, 0);
8687 #else
8688 if (rename(fn, RSTRING_PTR(str)) < 0) {
8689 rb_warn("Can't rename %"PRIsVALUE" to %"PRIsVALUE": %s, skipping file",
8690 filename, str, strerror(errno));
8691 close(fr);
8692 goto retry;
8693 }
8694 #endif
8695 }
8696 else {
8697 #ifdef NO_SAFE_RENAME
8698 rb_fatal("Can't do inplace edit without backup");
8699 #else
8700 if (unlink(fn) < 0) {
8701 rb_warn("Can't remove %"PRIsVALUE": %s, skipping file",
8702 filename, strerror(errno));
8703 close(fr);
8704 goto retry;
8705 }
8706 #endif
8707 }
8708 fw = rb_sysopen(filename, O_WRONLY|O_CREAT|O_TRUNC, 0666);
8709 #ifndef NO_SAFE_RENAME
8710 fstat(fw, &st2);
8711 #ifdef HAVE_FCHMOD
8712 fchmod(fw, st.st_mode);
8713 #else
8714 chmod(fn, st.st_mode);
8715 #endif
8716 if (st.st_uid!=st2.st_uid || st.st_gid!=st2.st_gid) {
8717 int err;
8718 #ifdef HAVE_FCHOWN
8719 err = fchown(fw, st.st_uid, st.st_gid);
8720 #else
8721 err = chown(fn, st.st_uid, st.st_gid);
8722 #endif
8723 if (err && getuid() == 0 && st2.st_uid == 0) {
8724 const char *wkfn = RSTRING_PTR(filename);
8725 rb_warn("Can't set owner/group of %"PRIsVALUE" to same as %"PRIsVALUE": %s, skipping file",
8726 filename, str, strerror(errno));
8727 (void)close(fr);
8728 (void)close(fw);
8729 (void)unlink(wkfn);
8730 goto retry;
8731 }
8732 }
8733 #endif
8734 write_io = prep_io(fw, FMODE_WRITABLE, rb_cFile, fn);
8735 rb_stdout = write_io;
8736 if (stdout_binmode) rb_io_binmode(rb_stdout);
8737 }
8738 fmode = FMODE_READABLE;
8739 if (!ARGF.binmode) {
8740 fmode |= DEFAULT_TEXTMODE;
8741 }
8742 ARGF.current_file = prep_io(fr, fmode, rb_cFile, fn);
8743 if (!NIL_P(write_io)) {
8744 rb_io_set_write_io(ARGF.current_file, write_io);
8745 }
8746 RB_GC_GUARD(filename);
8747 }
8748 if (ARGF.binmode) rb_io_ascii8bit_binmode(ARGF.current_file);
8749 GetOpenFile(ARGF.current_file, fptr);
8750 if (ARGF.encs.enc) {
8751 fptr->encs = ARGF.encs;
8752 clear_codeconv(fptr);
8753 }
8754 else {
8755 fptr->encs.ecflags &= ~ECONV_NEWLINE_DECORATOR_MASK;
8756 if (!ARGF.binmode) {
8757 fptr->encs.ecflags |= ECONV_DEFAULT_NEWLINE_DECORATOR;
8758 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
8759 fptr->encs.ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
8760 #endif
8761 }
8762 }
8763 ARGF.next_p = 0;
8764 }
8765 else {
8766 ARGF.next_p = 1;
8767 return FALSE;
8768 }
8769 }
8770 else if (ARGF.next_p == -1) {
8771 ARGF.current_file = rb_stdin;
8772 ARGF.filename = rb_str_new2("-");
8773 if (ARGF.inplace) {
8774 rb_warn("Can't do inplace edit for stdio");
8775 rb_stdout = orig_stdout;
8776 }
8777 }
8778 if (ARGF.init_p == -1) ARGF.init_p = 1;
8779 return TRUE;
8780 }
8781
8782 static VALUE
8783 argf_getline(int argc, VALUE *argv, VALUE argf)
8784 {
8785 VALUE line;
8786 long lineno = ARGF.lineno;
8787
8788 retry:
8789 if (!next_argv()) return Qnil;
8790 if (ARGF_GENERIC_INPUT_P()) {
8791 line = rb_funcall3(ARGF.current_file, idGets, argc, argv);
8792 }
8793 else {
8794 if (argc == 0 && rb_rs == rb_default_rs) {
8795 line = rb_io_gets(ARGF.current_file);
8796 }
8797 else {
8798 line = rb_io_getline(argc, argv, ARGF.current_file);
8799 }
8800 if (NIL_P(line) && ARGF.next_p != -1) {
8801 argf_close(argf);
8802 ARGF.next_p = 1;
8803 goto retry;
8804 }
8805 }
8806 if (!NIL_P(line)) {
8807 ARGF.lineno = ++lineno;
8808 ARGF.last_lineno = ARGF.lineno;
8809 }
8810 return line;
8811 }
8812
8813 static VALUE
8814 argf_lineno_getter(ID id, VALUE *var)
8815 {
8816 VALUE argf = *var;
8817 return INT2FIX(ARGF.last_lineno);
8818 }
8819
8820 static void
8821 argf_lineno_setter(VALUE val, ID id, VALUE *var)
8822 {
8823 VALUE argf = *var;
8824 int n = NUM2INT(val);
8825 ARGF.last_lineno = ARGF.lineno = n;
8826 }
8827
8828 static VALUE argf_gets(int, VALUE *, VALUE);
8829
8830 /*
8831 * call-seq:
8832 * gets(sep=$/ [, getline_args]) -> string or nil
8833 * gets(limit [, getline_args]) -> string or nil
8834 * gets(sep, limit [, getline_args]) -> string or nil
8835 *
8836 * Returns (and assigns to <code>$_</code>) the next line from the list
8837 * of files in +ARGV+ (or <code>$*</code>), or from standard input if
8838 * no files are present on the command line. Returns +nil+ at end of
8839 * file. The optional argument specifies the record separator. The
8840 * separator is included with the contents of each record. A separator
8841 * of +nil+ reads the entire contents, and a zero-length separator
8842 * reads the input one paragraph at a time, where paragraphs are
8843 * divided by two consecutive newlines. If the first argument is an
8844 * integer, or optional second argument is given, the returning string
8845 * would not be longer than the given value in bytes. If multiple
8846 * filenames are present in +ARGV+, <code>gets(nil)</code> will read
8847 * the contents one file at a time.
8848 *
8849 * ARGV << "testfile"
8850 * print while gets
8851 *
8852 * <em>produces:</em>
8853 *
8854 * This is line one
8855 * This is line two
8856 * This is line three
8857 * And so on...
8858 *
8859 * The style of programming using <code>$_</code> as an implicit
8860 * parameter is gradually losing favor in the Ruby community.
8861 */
8862
8863 static VALUE
8864 rb_f_gets(int argc, VALUE *argv, VALUE recv)
8865 {
8866 if (recv == argf) {
8867 return argf_gets(argc, argv, argf);
8868 }
8869 return rb_funcallv(argf, idGets, argc, argv);
8870 }
8871
8872 /*
8873 * call-seq:
8874 * ARGF.gets(sep=$/ [, getline_args]) -> string or nil
8875 * ARGF.gets(limit [, getline_args]) -> string or nil
8876 * ARGF.gets(sep, limit [, getline_args]) -> string or nil
8877 *
8878 * Returns the next line from the current file in +ARGF+.
8879 *
8880 * By default lines are assumed to be separated by <code>$/</code>;
8881 * to use a different character as a separator, supply it as a +String+
8882 * for the _sep_ argument.
8883 *
8884 * The optional _limit_ argument specifies how many characters of each line
8885 * to return. By default all characters are returned.
8886 *
8887 * See IO.readlines for details about getline_args.
8888 *
8889 */
8890 static VALUE
8891 argf_gets(int argc, VALUE *argv, VALUE argf)
8892 {
8893 VALUE line;
8894
8895 line = argf_getline(argc, argv, argf);
8896 rb_lastline_set(line);
8897
8898 return line;
8899 }
8900
8901 VALUE
8902 rb_gets(void)
8903 {
8904 VALUE line;
8905
8906 if (rb_rs != rb_default_rs) {
8907 return rb_f_gets(0, 0, argf);
8908 }
8909
8910 retry:
8911 if (!next_argv()) return Qnil;
8912 line = rb_io_gets(ARGF.current_file);
8913 if (NIL_P(line) && ARGF.next_p != -1) {
8914 rb_io_close(ARGF.current_file);
8915 ARGF.next_p = 1;
8916 goto retry;
8917 }
8918 rb_lastline_set(line);
8919 if (!NIL_P(line)) {
8920 ARGF.lineno++;
8921 ARGF.last_lineno = ARGF.lineno;
8922 }
8923
8924 return line;
8925 }
8926
8927 static VALUE argf_readline(int, VALUE *, VALUE);
8928
8929 /*
8930 * call-seq:
8931 * readline(sep=$/) -> string
8932 * readline(limit) -> string
8933 * readline(sep, limit) -> string
8934 *
8935 * Equivalent to Kernel::gets, except
8936 * +readline+ raises +EOFError+ at end of file.
8937 */
8938
8939 static VALUE
8940 rb_f_readline(int argc, VALUE *argv, VALUE recv)
8941 {
8942 if (recv == argf) {
8943 return argf_readline(argc, argv, argf);
8944 }
8945 return rb_funcallv(argf, rb_intern("readline"), argc, argv);
8946 }
8947
8948
8949 /*
8950 * call-seq:
8951 * ARGF.readline(sep=$/) -> string
8952 * ARGF.readline(limit) -> string
8953 * ARGF.readline(sep, limit) -> string
8954 *
8955 * Returns the next line from the current file in +ARGF+.
8956 *
8957 * By default lines are assumed to be separated by <code>$/</code>;
8958 * to use a different character as a separator, supply it as a +String+
8959 * for the _sep_ argument.
8960 *
8961 * The optional _limit_ argument specifies how many characters of each line
8962 * to return. By default all characters are returned.
8963 *
8964 * An +EOFError+ is raised at the end of the file.
8965 */
8966 static VALUE
8967 argf_readline(int argc, VALUE *argv, VALUE argf)
8968 {
8969 VALUE line;
8970
8971 if (!next_argv()) rb_eof_error();
8972 ARGF_FORWARD(argc, argv);
8973 line = argf_gets(argc, argv, argf);
8974 if (NIL_P(line)) {
8975 rb_eof_error();
8976 }
8977
8978 return line;
8979 }
8980
8981 static VALUE argf_readlines(int, VALUE *, VALUE);
8982
8983 /*
8984 * call-seq:
8985 * readlines(sep=$/) -> array
8986 * readlines(limit) -> array
8987 * readlines(sep, limit) -> array
8988 *
8989 * Returns an array containing the lines returned by calling
8990 * <code>Kernel.gets(<i>sep</i>)</code> until the end of file.
8991 */
8992
8993 static VALUE
8994 rb_f_readlines(int argc, VALUE *argv, VALUE recv)
8995 {
8996 if (recv == argf) {
8997 return argf_readlines(argc, argv, argf);
8998 }
8999 return rb_funcallv(argf, rb_intern("readlines"), argc, argv);
9000 }
9001
9002 /*
9003 * call-seq:
9004 * ARGF.readlines(sep=$/) -> array
9005 * ARGF.readlines(limit) -> array
9006 * ARGF.readlines(sep, limit) -> array
9007 *
9008 * ARGF.to_a(sep=$/) -> array
9009 * ARGF.to_a(limit) -> array
9010 * ARGF.to_a(sep, limit) -> array
9011 *
9012 * Reads +ARGF+'s current file in its entirety, returning an +Array+ of its
9013 * lines, one line per element. Lines are assumed to be separated by _sep_.
9014 *
9015 * lines = ARGF.readlines
9016 * lines[0] #=> "This is line one\n"
9017 */
9018 static VALUE
9019 argf_readlines(int argc, VALUE *argv, VALUE argf)
9020 {
9021 long lineno = ARGF.lineno;
9022 VALUE lines, ary;
9023
9024 ary = rb_ary_new();
9025 while (next_argv()) {
9026 if (ARGF_GENERIC_INPUT_P()) {
9027 lines = rb_funcall3(ARGF.current_file, rb_intern("readlines"), argc, argv);
9028 }
9029 else {
9030 lines = rb_io_readlines(argc, argv, ARGF.current_file);
9031 argf_close(argf);
9032 }
9033 ARGF.next_p = 1;
9034 rb_ary_concat(ary, lines);
9035 ARGF.lineno = lineno + RARRAY_LEN(ary);
9036 ARGF.last_lineno = ARGF.lineno;
9037 }
9038 ARGF.init_p = 0;
9039 return ary;
9040 }
9041
9042 /*
9043 * call-seq:
9044 * `cmd` -> string
9045 *
9046 * Returns the standard output of running _cmd_ in a subshell.
9047 * The built-in syntax <code>%x{...}</code> uses
9048 * this method. Sets <code>$?</code> to the process status.
9049 *
9050 * `date` #=> "Wed Apr 9 08:56:30 CDT 2003\n"
9051 * `ls testdir`.split[1] #=> "main.rb"
9052 * `echo oops && exit 99` #=> "oops\n"
9053 * $?.exitstatus #=> 99
9054 */
9055
9056 static VALUE
9057 rb_f_backquote(VALUE obj, VALUE str)
9058 {
9059 VALUE port;
9060 VALUE result;
9061 rb_io_t *fptr;
9062
9063 SafeStringValue(str);
9064 rb_last_status_clear();
9065 port = pipe_open_s(str, "r", FMODE_READABLE|DEFAULT_TEXTMODE, NULL);
9066 if (NIL_P(port)) return rb_str_new(0,0);
9067
9068 GetOpenFile(port, fptr);
9069 result = read_all(fptr, remain_size(fptr), Qnil);
9070 rb_io_close(port);
9071 RFILE(port)->fptr = NULL;
9072 rb_io_fptr_finalize(fptr);
9073 rb_gc_force_recycle(port); /* also guards from premature GC */
9074
9075 return result;
9076 }
9077
9078 #ifdef HAVE_SYS_SELECT_H
9079 #include <sys/select.h>
9080 #endif
9081
9082 static VALUE
9083 select_internal(VALUE read, VALUE write, VALUE except, struct timeval *tp, rb_fdset_t *fds)
9084 {
9085 VALUE res, list;
9086 rb_fdset_t *rp, *wp, *ep;
9087 rb_io_t *fptr;
9088 long i;
9089 int max = 0, n;
9090 int pending = 0;
9091 struct timeval timerec;
9092
9093 if (!NIL_P(read)) {
9094 Check_Type(read, T_ARRAY);
9095 for (i=0; i<RARRAY_LEN(read); i++) {
9096 GetOpenFile(rb_io_get_io(RARRAY_AREF(read, i)), fptr);
9097 rb_fd_set(fptr->fd, &fds[0]);
9098 if (READ_DATA_PENDING(fptr) || READ_CHAR_PENDING(fptr)) { /* check for buffered data */
9099 pending++;
9100 rb_fd_set(fptr->fd, &fds[3]);
9101 }
9102 if (max < fptr->fd) max = fptr->fd;
9103 }
9104 if (pending) { /* no blocking if there's buffered data */
9105 timerec.tv_sec = timerec.tv_usec = 0;
9106 tp = &timerec;
9107 }
9108 rp = &fds[0];
9109 }
9110 else
9111 rp = 0;
9112
9113 if (!NIL_P(write)) {
9114 Check_Type(write, T_ARRAY);
9115 for (i=0; i<RARRAY_LEN(write); i++) {
9116 VALUE write_io = GetWriteIO(rb_io_get_io(RARRAY_AREF(write, i)));
9117 GetOpenFile(write_io, fptr);
9118 rb_fd_set(fptr->fd, &fds[1]);
9119 if (max < fptr->fd) max = fptr->fd;
9120 }
9121 wp = &fds[1];
9122 }
9123 else
9124 wp = 0;
9125
9126 if (!NIL_P(except)) {
9127 Check_Type(except, T_ARRAY);
9128 for (i=0; i<RARRAY_LEN(except); i++) {
9129 VALUE io = rb_io_get_io(RARRAY_AREF(except, i));
9130 VALUE write_io = GetWriteIO(io);
9131 GetOpenFile(io, fptr);
9132 rb_fd_set(fptr->fd, &fds[2]);
9133 if (max < fptr->fd) max = fptr->fd;
9134 if (io != write_io) {
9135 GetOpenFile(write_io, fptr);
9136 rb_fd_set(fptr->fd, &fds[2]);
9137 if (max < fptr->fd) max = fptr->fd;
9138 }
9139 }
9140 ep = &fds[2];
9141 }
9142 else {
9143 ep = 0;
9144 }
9145
9146 max++;
9147
9148 n = rb_thread_fd_select(max, rp, wp, ep, tp);
9149 if (n < 0) {
9150 rb_sys_fail(0);
9151 }
9152 if (!pending && n == 0) return Qnil; /* returns nil on timeout */
9153
9154 res = rb_ary_new2(3);
9155 rb_ary_push(res, rp?rb_ary_new():rb_ary_new2(0));
9156 rb_ary_push(res, wp?rb_ary_new():rb_ary_new2(0));
9157 rb_ary_push(res, ep?rb_ary_new():rb_ary_new2(0));
9158
9159 if (rp) {
9160 list = RARRAY_AREF(res, 0);
9161 for (i=0; i< RARRAY_LEN(read); i++) {
9162 VALUE obj = rb_ary_entry(read, i);
9163 VALUE io = rb_io_get_io(obj);
9164 GetOpenFile(io, fptr);
9165 if (rb_fd_isset(fptr->fd, &fds[0]) ||
9166 rb_fd_isset(fptr->fd, &fds[3])) {
9167 rb_ary_push(list, obj);
9168 }
9169 }
9170 }
9171
9172 if (wp) {
9173 list = RARRAY_AREF(res, 1);
9174 for (i=0; i< RARRAY_LEN(write); i++) {
9175 VALUE obj = rb_ary_entry(write, i);
9176 VALUE io = rb_io_get_io(obj);
9177 VALUE write_io = GetWriteIO(io);
9178 GetOpenFile(write_io, fptr);
9179 if (rb_fd_isset(fptr->fd, &fds[1])) {
9180 rb_ary_push(list, obj);
9181 }
9182 }
9183 }
9184
9185 if (ep) {
9186 list = RARRAY_AREF(res, 2);
9187 for (i=0; i< RARRAY_LEN(except); i++) {
9188 VALUE obj = rb_ary_entry(except, i);
9189 VALUE io = rb_io_get_io(obj);
9190 VALUE write_io = GetWriteIO(io);
9191 GetOpenFile(io, fptr);
9192 if (rb_fd_isset(fptr->fd, &fds[2])) {
9193 rb_ary_push(list, obj);
9194 }
9195 else if (io != write_io) {
9196 GetOpenFile(write_io, fptr);
9197 if (rb_fd_isset(fptr->fd, &fds[2])) {
9198 rb_ary_push(list, obj);
9199 }
9200 }
9201 }
9202 }
9203
9204 return res; /* returns an empty array on interrupt */
9205 }
9206
9207 struct select_args {
9208 VALUE read, write, except;
9209 struct timeval *timeout;
9210 rb_fdset_t fdsets[4];
9211 };
9212
9213 static VALUE
9214 select_call(VALUE arg)
9215 {
9216 struct select_args *p = (struct select_args *)arg;
9217
9218 return select_internal(p->read, p->write, p->except, p->timeout, p->fdsets);
9219 }
9220
9221 static VALUE
9222 select_end(VALUE arg)
9223 {
9224 struct select_args *p = (struct select_args *)arg;
9225 int i;
9226
9227 for (i = 0; i < numberof(p->fdsets); ++i)
9228 rb_fd_term(&p->fdsets[i]);
9229 return Qnil;
9230 }
9231
9232 static VALUE sym_normal, sym_sequential, sym_random,
9233 sym_willneed, sym_dontneed, sym_noreuse;
9234
9235 #ifdef HAVE_POSIX_FADVISE
9236 struct io_advise_struct {
9237 int fd;
9238 int advice;
9239 off_t offset;
9240 off_t len;
9241 };
9242
9243 static VALUE
9244 io_advise_internal(void *arg)
9245 {
9246 struct io_advise_struct *ptr = arg;
9247 return posix_fadvise(ptr->fd, ptr->offset, ptr->len, ptr->advice);
9248 }
9249
9250 static VALUE
9251 io_advise_sym_to_const(VALUE sym)
9252 {
9253 #ifdef POSIX_FADV_NORMAL
9254 if (sym == sym_normal)
9255 return INT2NUM(POSIX_FADV_NORMAL);
9256 #endif
9257
9258 #ifdef POSIX_FADV_RANDOM
9259 if (sym == sym_random)
9260 return INT2NUM(POSIX_FADV_RANDOM);
9261 #endif
9262
9263 #ifdef POSIX_FADV_SEQUENTIAL
9264 if (sym == sym_sequential)
9265 return INT2NUM(POSIX_FADV_SEQUENTIAL);
9266 #endif
9267
9268 #ifdef POSIX_FADV_WILLNEED
9269 if (sym == sym_willneed)
9270 return INT2NUM(POSIX_FADV_WILLNEED);
9271 #endif
9272
9273 #ifdef POSIX_FADV_DONTNEED
9274 if (sym == sym_dontneed)
9275 return INT2NUM(POSIX_FADV_DONTNEED);
9276 #endif
9277
9278 #ifdef POSIX_FADV_NOREUSE
9279 if (sym == sym_noreuse)
9280 return INT2NUM(POSIX_FADV_NOREUSE);
9281 #endif
9282
9283 return Qnil;
9284 }
9285
9286 static VALUE
9287 do_io_advise(rb_io_t *fptr, VALUE advice, off_t offset, off_t len)
9288 {
9289 int rv;
9290 struct io_advise_struct ias;
9291 VALUE num_adv;
9292
9293 num_adv = io_advise_sym_to_const(advice);
9294
9295 /*
9296 * The platform doesn't support this hint. We don't raise exception, instead
9297 * silently ignore it. Because IO::advise is only hint.
9298 */
9299 if (NIL_P(num_adv))
9300 return Qnil;
9301
9302 ias.fd = fptr->fd;
9303 ias.advice = NUM2INT(num_adv);
9304 ias.offset = offset;
9305 ias.len = len;
9306
9307 rv = (int)rb_thread_io_blocking_region(io_advise_internal, &ias, fptr->fd);
9308 if (rv && rv != ENOSYS) {
9309 /* posix_fadvise(2) doesn't set errno. On success it returns 0; otherwise
9310 it returns the error code. */
9311 VALUE message = rb_sprintf("%"PRIsVALUE" "
9312 "(%"PRI_OFFT_PREFIX"d, "
9313 "%"PRI_OFFT_PREFIX"d, "
9314 "%"PRIsVALUE")",
9315 fptr->pathv, offset, len, advice);
9316 rb_syserr_fail_str(rv, message);
9317 }
9318
9319 return Qnil;
9320 }
9321
9322 #endif /* HAVE_POSIX_FADVISE */
9323
9324 static void
9325 advice_arg_check(VALUE advice)
9326 {
9327 if (!SYMBOL_P(advice))
9328 rb_raise(rb_eTypeError, "advice must be a Symbol");
9329
9330 if (advice != sym_normal &&
9331 advice != sym_sequential &&
9332 advice != sym_random &&
9333 advice != sym_willneed &&
9334 advice != sym_dontneed &&
9335 advice != sym_noreuse) {
9336 rb_raise(rb_eNotImpError, "Unsupported advice: %+"PRIsVALUE, advice);
9337 }
9338 }
9339
9340 /*
9341 * call-seq:
9342 * ios.advise(advice, offset=0, len=0) -> nil
9343 *
9344 * Announce an intention to access data from the current file in a
9345 * specific pattern. On platforms that do not support the
9346 * <em>posix_fadvise(2)</em> system call, this method is a no-op.
9347 *
9348 * _advice_ is one of the following symbols:
9349 *
9350 * :normal:: No advice to give; the default assumption for an open file.
9351 * :sequential:: The data will be accessed sequentially
9352 * with lower offsets read before higher ones.
9353 * :random:: The data will be accessed in random order.
9354 * :willneed:: The data will be accessed in the near future.
9355 * :dontneed:: The data will not be accessed in the near future.
9356 * :noreuse:: The data will only be accessed once.
9357 *
9358 * The semantics of a piece of advice are platform-dependent. See
9359 * <em>man 2 posix_fadvise</em> for details.
9360 *
9361 * "data" means the region of the current file that begins at
9362 * _offset_ and extends for _len_ bytes. If _len_ is 0, the region
9363 * ends at the last byte of the file. By default, both _offset_ and
9364 * _len_ are 0, meaning that the advice applies to the entire file.
9365 *
9366 * If an error occurs, one of the following exceptions will be raised:
9367 *
9368 * IOError:: The IO stream is closed.
9369 * Errno::EBADF::
9370 * The file descriptor of the current file is invalid.
9371 * Errno::EINVAL:: An invalid value for _advice_ was given.
9372 * Errno::ESPIPE::
9373 * The file descriptor of the current file refers to a FIFO or
9374 * pipe. (Linux raises Errno::EINVAL in this case).
9375 * TypeError::
9376 * Either _advice_ was not a Symbol, or one of the
9377 * other arguments was not an Integer.
9378 * RangeError:: One of the arguments given was too big/small.
9379 *
9380 * This list is not exhaustive; other Errno:: exceptions are also possible.
9381 */
9382 static VALUE
9383 rb_io_advise(int argc, VALUE *argv, VALUE io)
9384 {
9385 VALUE advice, offset, len;
9386 off_t off, l;
9387 rb_io_t *fptr;
9388
9389 rb_scan_args(argc, argv, "12", &advice, &offset, &len);
9390 advice_arg_check(advice);
9391
9392 io = GetWriteIO(io);
9393 GetOpenFile(io, fptr);
9394
9395 off = NIL_P(offset) ? 0 : NUM2OFFT(offset);
9396 l = NIL_P(len) ? 0 : NUM2OFFT(len);
9397
9398 #ifdef HAVE_POSIX_FADVISE
9399 return do_io_advise(fptr, advice, off, l);
9400 #else
9401 ((void)off, (void)l); /* Ignore all hint */
9402 return Qnil;
9403 #endif
9404 }
9405
9406 /*
9407 * call-seq:
9408 * IO.select(read_array [, write_array [, error_array [, timeout]]]) -> array or nil
9409 *
9410 * Calls select(2) system call.
9411 * It monitors given arrays of IO objects, waits until one or more of
9412 * IO objects are ready for reading, are ready for writing, and have
9413 * pending exceptions respectively, and returns an array that contains
9414 * arrays of those IO objects. It will return +nil+ if optional
9415 * <i>timeout</i> value is given and no IO object is ready in
9416 * <i>timeout</i> seconds.
9417 *
9418 * IO.select peeks the buffer of IO objects for testing readability.
9419 * If the IO buffer is not empty, IO.select immediately notifies
9420 * readability. This "peek" only happens for IO objects. It does not
9421 * happen for IO-like objects such as OpenSSL::SSL::SSLSocket.
9422 *
9423 * The best way to use IO.select is invoking it after nonblocking
9424 * methods such as #read_nonblock, #write_nonblock, etc. The methods
9425 * raise an exception which is extended by IO::WaitReadable or
9426 * IO::WaitWritable. The modules notify how the caller should wait
9427 * with IO.select. If IO::WaitReadable is raised, the caller should
9428 * wait for reading. If IO::WaitWritable is raised, the caller should
9429 * wait for writing.
9430 *
9431 * So, blocking read (#readpartial) can be emulated using
9432 * #read_nonblock and IO.select as follows:
9433 *
9434 * begin
9435 * result = io_like.read_nonblock(maxlen)
9436 * rescue IO::WaitReadable
9437 * IO.select([io_like])
9438 * retry
9439 * rescue IO::WaitWritable
9440 * IO.select(nil, [io_like])
9441 * retry
9442 * end
9443 *
9444 * Especially, the combination of nonblocking methods and IO.select is
9445 * preferred for IO like objects such as OpenSSL::SSL::SSLSocket. It
9446 * has #to_io method to return underlying IO object. IO.select calls
9447 * #to_io to obtain the file descriptor to wait.
9448 *
9449 * This means that readability notified by IO.select doesn't mean
9450 * readability from OpenSSL::SSL::SSLSocket object.
9451 *
9452 * The most likely situation is that OpenSSL::SSL::SSLSocket buffers
9453 * some data. IO.select doesn't see the buffer. So IO.select can
9454 * block when OpenSSL::SSL::SSLSocket#readpartial doesn't block.
9455 *
9456 * However, several more complicated situations exist.
9457 *
9458 * SSL is a protocol which is sequence of records.
9459 * The record consists of multiple bytes.
9460 * So, the remote side of SSL sends a partial record, IO.select
9461 * notifies readability but OpenSSL::SSL::SSLSocket cannot decrypt a
9462 * byte and OpenSSL::SSL::SSLSocket#readpartial will block.
9463 *
9464 * Also, the remote side can request SSL renegotiation which forces
9465 * the local SSL engine to write some data.
9466 * This means OpenSSL::SSL::SSLSocket#readpartial may invoke #write
9467 * system call and it can block.
9468 * In such a situation, OpenSSL::SSL::SSLSocket#read_nonblock raises
9469 * IO::WaitWritable instead of blocking.
9470 * So, the caller should wait for ready for writability as above
9471 * example.
9472 *
9473 * The combination of nonblocking methods and IO.select is also useful
9474 * for streams such as tty, pipe socket socket when multiple processes
9475 * read from a stream.
9476 *
9477 * Finally, Linux kernel developers don't guarantee that
9478 * readability of select(2) means readability of following read(2) even
9479 * for a single process.
9480 * See select(2) manual on GNU/Linux system.
9481 *
9482 * Invoking IO.select before IO#readpartial works well as usual.
9483 * However it is not the best way to use IO.select.
9484 *
9485 * The writability notified by select(2) doesn't show
9486 * how many bytes are writable.
9487 * IO#write method blocks until given whole string is written.
9488 * So, <code>IO#write(two or more bytes)</code> can block after
9489 * writability is notified by IO.select. IO#write_nonblock is required
9490 * to avoid the blocking.
9491 *
9492 * Blocking write (#write) can be emulated using #write_nonblock and
9493 * IO.select as follows: IO::WaitReadable should also be rescued for
9494 * SSL renegotiation in OpenSSL::SSL::SSLSocket.
9495 *
9496 * while 0 < string.bytesize
9497 * begin
9498 * written = io_like.write_nonblock(string)
9499 * rescue IO::WaitReadable
9500 * IO.select([io_like])
9501 * retry
9502 * rescue IO::WaitWritable
9503 * IO.select(nil, [io_like])
9504 * retry
9505 * end
9506 * string = string.byteslice(written..-1)
9507 * end
9508 *
9509 * === Parameters
9510 * read_array:: an array of IO objects that wait until ready for read
9511 * write_array:: an array of IO objects that wait until ready for write
9512 * error_array:: an array of IO objects that wait for exceptions
9513 * timeout:: a numeric value in second
9514 *
9515 * === Example
9516 *
9517 * rp, wp = IO.pipe
9518 * mesg = "ping "
9519 * 100.times {
9520 * # IO.select follows IO#read. Not the best way to use IO.select.
9521 * rs, ws, = IO.select([rp], [wp])
9522 * if r = rs[0]
9523 * ret = r.read(5)
9524 * print ret
9525 * case ret
9526 * when /ping/
9527 * mesg = "pong\n"
9528 * when /pong/
9529 * mesg = "ping "
9530 * end
9531 * end
9532 * if w = ws[0]
9533 * w.write(mesg)
9534 * end
9535 * }
9536 *
9537 * <em>produces:</em>
9538 *
9539 * ping pong
9540 * ping pong
9541 * ping pong
9542 * (snipped)
9543 * ping
9544 */
9545
9546 static VALUE
9547 rb_f_select(int argc, VALUE *argv, VALUE obj)
9548 {
9549 VALUE timeout;
9550 struct select_args args;
9551 struct timeval timerec;
9552 int i;
9553
9554 rb_scan_args(argc, argv, "13", &args.read, &args.write, &args.except, &timeout);
9555 if (NIL_P(timeout)) {
9556 args.timeout = 0;
9557 }
9558 else {
9559 timerec = rb_time_interval(timeout);
9560 args.timeout = &timerec;
9561 }
9562
9563 for (i = 0; i < numberof(args.fdsets); ++i)
9564 rb_fd_init(&args.fdsets[i]);
9565
9566 return rb_ensure(select_call, (VALUE)&args, select_end, (VALUE)&args);
9567 }
9568
9569 #if (defined(__linux__) && !defined(__ANDROID__)) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
9570 typedef unsigned long ioctl_req_t;
9571 # define NUM2IOCTLREQ(num) NUM2ULONG(num)
9572 #else
9573 typedef int ioctl_req_t;
9574 # define NUM2IOCTLREQ(num) ((int)NUM2LONG(num))
9575 #endif
9576
9577 #ifdef HAVE_IOCTL
9578 struct ioctl_arg {
9579 int fd;
9580 ioctl_req_t cmd;
9581 long narg;
9582 };
9583
9584 static VALUE
9585 nogvl_ioctl(void *ptr)
9586 {
9587 struct ioctl_arg *arg = ptr;
9588
9589 return (VALUE)ioctl(arg->fd, arg->cmd, arg->narg);
9590 }
9591
9592 static int
9593 do_ioctl(int fd, ioctl_req_t cmd, long narg)
9594 {
9595 int retval;
9596 struct ioctl_arg arg;
9597
9598 arg.fd = fd;
9599 arg.cmd = cmd;
9600 arg.narg = narg;
9601
9602 retval = (int)rb_thread_io_blocking_region(nogvl_ioctl, &arg, fd);
9603
9604 return retval;
9605 }
9606 #endif
9607
9608 #define DEFULT_IOCTL_NARG_LEN (256)
9609
9610 #if defined(__linux__) && defined(_IOC_SIZE)
9611 static long
9612 linux_iocparm_len(ioctl_req_t cmd)
9613 {
9614 long len;
9615
9616 if ((cmd & 0xFFFF0000) == 0) {
9617 /* legacy and unstructured ioctl number. */
9618 return DEFULT_IOCTL_NARG_LEN;
9619 }
9620
9621 len = _IOC_SIZE(cmd);
9622
9623 /* paranoia check for silly drivers which don't keep ioctl convention */
9624 if (len < DEFULT_IOCTL_NARG_LEN)
9625 len = DEFULT_IOCTL_NARG_LEN;
9626
9627 return len;
9628 }
9629 #endif
9630
9631 static long
9632 ioctl_narg_len(ioctl_req_t cmd)
9633 {
9634 long len;
9635
9636 #ifdef IOCPARM_MASK
9637 #ifndef IOCPARM_LEN
9638 #define IOCPARM_LEN(x) (((x) >> 16) & IOCPARM_MASK)
9639 #endif
9640 #endif
9641 #ifdef IOCPARM_LEN
9642 len = IOCPARM_LEN(cmd); /* on BSDish systems we're safe */
9643 #elif defined(__linux__) && defined(_IOC_SIZE)
9644 len = linux_iocparm_len(cmd);
9645 #else
9646 /* otherwise guess at what's safe */
9647 len = DEFULT_IOCTL_NARG_LEN;
9648 #endif
9649
9650 return len;
9651 }
9652
9653 #ifdef HAVE_FCNTL
9654 #ifdef __linux__
9655 typedef long fcntl_arg_t;
9656 #else
9657 /* posix */
9658 typedef int fcntl_arg_t;
9659 #endif
9660
9661 static long
9662 fcntl_narg_len(int cmd)
9663 {
9664 long len;
9665
9666 switch (cmd) {
9667 #ifdef F_DUPFD
9668 case F_DUPFD:
9669 len = sizeof(fcntl_arg_t);
9670 break;
9671 #endif
9672 #ifdef F_DUP2FD /* bsd specific */
9673 case F_DUP2FD:
9674 len = sizeof(int);
9675 break;
9676 #endif
9677 #ifdef F_DUPFD_CLOEXEC /* linux specific */
9678 case F_DUPFD_CLOEXEC:
9679 len = sizeof(fcntl_arg_t);
9680 break;
9681 #endif
9682 #ifdef F_GETFD
9683 case F_GETFD:
9684 len = 1;
9685 break;
9686 #endif
9687 #ifdef F_SETFD
9688 case F_SETFD:
9689 len = sizeof(fcntl_arg_t);
9690 break;
9691 #endif
9692 #ifdef F_GETFL
9693 case F_GETFL:
9694 len = 1;
9695 break;
9696 #endif
9697 #ifdef F_SETFL
9698 case F_SETFL:
9699 len = sizeof(fcntl_arg_t);
9700 break;
9701 #endif
9702 #ifdef F_GETOWN
9703 case F_GETOWN:
9704 len = 1;
9705 break;
9706 #endif
9707 #ifdef F_SETOWN
9708 case F_SETOWN:
9709 len = sizeof(fcntl_arg_t);
9710 break;
9711 #endif
9712 #ifdef F_GETOWN_EX /* linux specific */
9713 case F_GETOWN_EX:
9714 len = sizeof(struct f_owner_ex);
9715 break;
9716 #endif
9717 #ifdef F_SETOWN_EX /* linux specific */
9718 case F_SETOWN_EX:
9719 len = sizeof(struct f_owner_ex);
9720 break;
9721 #endif
9722 #ifdef F_GETLK
9723 case F_GETLK:
9724 len = sizeof(struct flock);
9725 break;
9726 #endif
9727 #ifdef F_SETLK
9728 case F_SETLK:
9729 len = sizeof(struct flock);
9730 break;
9731 #endif
9732 #ifdef F_SETLKW
9733 case F_SETLKW:
9734 len = sizeof(struct flock);
9735 break;
9736 #endif
9737 #ifdef F_READAHEAD /* bsd specific */
9738 case F_READAHEAD:
9739 len = sizeof(int);
9740 break;
9741 #endif
9742 #ifdef F_RDAHEAD /* Darwin specific */
9743 case F_RDAHEAD:
9744 len = sizeof(int);
9745 break;
9746 #endif
9747 #ifdef F_GETSIG /* linux specific */
9748 case F_GETSIG:
9749 len = 1;
9750 break;
9751 #endif
9752 #ifdef F_SETSIG /* linux specific */
9753 case F_SETSIG:
9754 len = sizeof(fcntl_arg_t);
9755 break;
9756 #endif
9757 #ifdef F_GETLEASE /* linux specific */
9758 case F_GETLEASE:
9759 len = 1;
9760 break;
9761 #endif
9762 #ifdef F_SETLEASE /* linux specific */
9763 case F_SETLEASE:
9764 len = sizeof(fcntl_arg_t);
9765 break;
9766 #endif
9767 #ifdef F_NOTIFY /* linux specific */
9768 case F_NOTIFY:
9769 len = sizeof(fcntl_arg_t);
9770 break;
9771 #endif
9772
9773 default:
9774 len = 256;
9775 break;
9776 }
9777
9778 return len;
9779 }
9780 #else /* HAVE_FCNTL */
9781 static long
9782 fcntl_narg_len(int cmd)
9783 {
9784 return 0;
9785 }
9786 #endif /* HAVE_FCNTL */
9787
9788 static long
9789 setup_narg(ioctl_req_t cmd, VALUE *argp, int io_p)
9790 {
9791 long narg = 0;
9792 VALUE arg = *argp;
9793
9794 if (NIL_P(arg) || arg == Qfalse) {
9795 narg = 0;
9796 }
9797 else if (FIXNUM_P(arg)) {
9798 narg = FIX2LONG(arg);
9799 }
9800 else if (arg == Qtrue) {
9801 narg = 1;
9802 }
9803 else {
9804 VALUE tmp = rb_check_string_type(arg);
9805
9806 if (NIL_P(tmp)) {
9807 narg = NUM2LONG(arg);
9808 }
9809 else {
9810 char *ptr;
9811 long len, slen;
9812
9813 *argp = arg = tmp;
9814 if (io_p)
9815 len = ioctl_narg_len(cmd);
9816 else
9817 len = fcntl_narg_len((int)cmd);
9818 rb_str_modify(arg);
9819
9820 slen = RSTRING_LEN(arg);
9821 /* expand for data + sentinel. */
9822 if (slen < len+1) {
9823 rb_str_resize(arg, len+1);
9824 MEMZERO(RSTRING_PTR(arg)+slen, char, len-slen);
9825 slen = len+1;
9826 }
9827 /* a little sanity check here */
9828 ptr = RSTRING_PTR(arg);
9829 ptr[slen - 1] = 17;
9830 narg = (long)(SIGNED_VALUE)ptr;
9831 }
9832 }
9833
9834 return narg;
9835 }
9836
9837 #ifdef HAVE_IOCTL
9838 static VALUE
9839 rb_ioctl(VALUE io, VALUE req, VALUE arg)
9840 {
9841 ioctl_req_t cmd = NUM2IOCTLREQ(req);
9842 rb_io_t *fptr;
9843 long narg;
9844 int retval;
9845
9846 narg = setup_narg(cmd, &arg, 1);
9847 GetOpenFile(io, fptr);
9848 retval = do_ioctl(fptr->fd, cmd, narg);
9849 if (retval < 0) rb_sys_fail_path(fptr->pathv);
9850 if (RB_TYPE_P(arg, T_STRING)) {
9851 char *ptr;
9852 long slen;
9853 RSTRING_GETMEM(arg, ptr, slen);
9854 if (ptr[slen-1] != 17)
9855 rb_raise(rb_eArgError, "return value overflowed string");
9856 ptr[slen-1] = '\0';
9857 }
9858
9859 return INT2NUM(retval);
9860 }
9861
9862 /*
9863 * call-seq:
9864 * ios.ioctl(integer_cmd, arg) -> integer
9865 *
9866 * Provides a mechanism for issuing low-level commands to control or
9867 * query I/O devices. Arguments and results are platform dependent. If
9868 * <i>arg</i> is a number, its value is passed directly. If it is a
9869 * string, it is interpreted as a binary sequence of bytes. On Unix
9870 * platforms, see <code>ioctl(2)</code> for details. Not implemented on
9871 * all platforms.
9872 */
9873
9874 static VALUE
9875 rb_io_ioctl(int argc, VALUE *argv, VALUE io)
9876 {
9877 VALUE req, arg;
9878
9879 rb_scan_args(argc, argv, "11", &req, &arg);
9880 return rb_ioctl(io, req, arg);
9881 }
9882 #else
9883 #define rb_io_ioctl rb_f_notimplement
9884 #endif
9885
9886 #ifdef HAVE_FCNTL
9887 struct fcntl_arg {
9888 int fd;
9889 int cmd;
9890 long narg;
9891 };
9892
9893 static VALUE
9894 nogvl_fcntl(void *ptr)
9895 {
9896 struct fcntl_arg *arg = ptr;
9897
9898 #if defined(F_DUPFD)
9899 if (arg->cmd == F_DUPFD)
9900 return (VALUE)rb_cloexec_fcntl_dupfd(arg->fd, (int)arg->narg);
9901 #endif
9902 return (VALUE)fcntl(arg->fd, arg->cmd, arg->narg);
9903 }
9904
9905 static int
9906 do_fcntl(int fd, int cmd, long narg)
9907 {
9908 int retval;
9909 struct fcntl_arg arg;
9910
9911 arg.fd = fd;
9912 arg.cmd = cmd;
9913 arg.narg = narg;
9914
9915 retval = (int)rb_thread_io_blocking_region(nogvl_fcntl, &arg, fd);
9916 if (retval != -1) {
9917 switch (cmd) {
9918 #if defined(F_DUPFD)
9919 case F_DUPFD:
9920 #endif
9921 #if defined(F_DUPFD_CLOEXEC)
9922 case F_DUPFD_CLOEXEC:
9923 #endif
9924 rb_update_max_fd(retval);
9925 }
9926 }
9927
9928 return retval;
9929 }
9930
9931 static VALUE
9932 rb_fcntl(VALUE io, VALUE req, VALUE arg)
9933 {
9934 int cmd = NUM2INT(req);
9935 rb_io_t *fptr;
9936 long narg;
9937 int retval;
9938
9939 narg = setup_narg(cmd, &arg, 0);
9940 GetOpenFile(io, fptr);
9941 retval = do_fcntl(fptr->fd, cmd, narg);
9942 if (retval < 0) rb_sys_fail_path(fptr->pathv);
9943 if (RB_TYPE_P(arg, T_STRING)) {
9944 char *ptr;
9945 long slen;
9946 RSTRING_GETMEM(arg, ptr, slen);
9947 if (ptr[slen-1] != 17)
9948 rb_raise(rb_eArgError, "return value overflowed string");
9949 ptr[slen-1] = '\0';
9950 }
9951
9952 return INT2NUM(retval);
9953 }
9954
9955 /*
9956 * call-seq:
9957 * ios.fcntl(integer_cmd, arg) -> integer
9958 *
9959 * Provides a mechanism for issuing low-level commands to control or
9960 * query file-oriented I/O streams. Arguments and results are platform
9961 * dependent. If <i>arg</i> is a number, its value is passed
9962 * directly. If it is a string, it is interpreted as a binary sequence
9963 * of bytes (Array#pack might be a useful way to build this string). On
9964 * Unix platforms, see <code>fcntl(2)</code> for details. Not
9965 * implemented on all platforms.
9966 */
9967
9968 static VALUE
9969 rb_io_fcntl(int argc, VALUE *argv, VALUE io)
9970 {
9971 VALUE req, arg;
9972
9973 rb_scan_args(argc, argv, "11", &req, &arg);
9974 return rb_fcntl(io, req, arg);
9975 }
9976 #else
9977 #define rb_io_fcntl rb_f_notimplement
9978 #endif
9979
9980 #if defined(HAVE_SYSCALL) || defined(HAVE___SYSCALL)
9981 /*
9982 * call-seq:
9983 * syscall(num [, args...]) -> integer
9984 *
9985 * Calls the operating system function identified by _num_ and
9986 * returns the result of the function or raises SystemCallError if
9987 * it failed.
9988 *
9989 * Arguments for the function can follow _num_. They must be either
9990 * +String+ objects or +Integer+ objects. A +String+ object is passed
9991 * as a pointer to the byte sequence. An +Integer+ object is passed
9992 * as an integer whose bit size is same as a pointer.
9993 * Up to nine parameters may be passed.
9994 *
9995 * The function identified by _num_ is system
9996 * dependent. On some Unix systems, the numbers may be obtained from a
9997 * header file called <code>syscall.h</code>.
9998 *
9999 * syscall 4, 1, "hello\n", 6 # '4' is write(2) on our box
10000 *
10001 * <em>produces:</em>
10002 *
10003 * hello
10004 *
10005 * Calling +syscall+ on a platform which does not have any way to
10006 * an arbitrary system function just fails with NotImplementedError.
10007 *
10008 * *Note:*
10009 * +syscall+ is essentially unsafe and unportable.
10010 * Feel free to shoot your foot.
10011 * The DL (Fiddle) library is preferred for safer and a bit
10012 * more portable programming.
10013 */
10014
10015 static VALUE
10016 rb_f_syscall(int argc, VALUE *argv, VALUE _)
10017 {
10018 VALUE arg[8];
10019 #if SIZEOF_VOIDP == 8 && defined(HAVE___SYSCALL) && SIZEOF_INT != 8 /* mainly *BSD */
10020 # define SYSCALL __syscall
10021 # define NUM2SYSCALLID(x) NUM2LONG(x)
10022 # define RETVAL2NUM(x) LONG2NUM(x)
10023 # if SIZEOF_LONG == 8
10024 long num, retval = -1;
10025 # elif SIZEOF_LONG_LONG == 8
10026 long long num, retval = -1;
10027 # else
10028 # error ---->> it is asserted that __syscall takes the first argument and returns retval in 64bit signed integer. <<----
10029 # endif
10030 #elif defined(__linux__)
10031 # define SYSCALL syscall
10032 # define NUM2SYSCALLID(x) NUM2LONG(x)
10033 # define RETVAL2NUM(x) LONG2NUM(x)
10034 /*
10035 * Linux man page says, syscall(2) function prototype is below.
10036 *
10037 * int syscall(int number, ...);
10038 *
10039 * But, it's incorrect. Actual one takes and returned long. (see unistd.h)
10040 */
10041 long num, retval = -1;
10042 #else
10043 # define SYSCALL syscall
10044 # define NUM2SYSCALLID(x) NUM2INT(x)
10045 # define RETVAL2NUM(x) INT2NUM(x)
10046 int num, retval = -1;
10047 #endif
10048 int i;
10049
10050 if (RTEST(ruby_verbose)) {
10051 rb_warning("We plan to remove a syscall function at future release. DL(Fiddle) provides safer alternative.");
10052 }
10053
10054 if (argc == 0)
10055 rb_raise(rb_eArgError, "too few arguments for syscall");
10056 if (argc > numberof(arg))
10057 rb_raise(rb_eArgError, "too many arguments for syscall");
10058 num = NUM2SYSCALLID(argv[0]); ++argv;
10059 for (i = argc - 1; i--; ) {
10060 VALUE v = rb_check_string_type(argv[i]);
10061
10062 if (!NIL_P(v)) {
10063 SafeStringValue(v);
10064 rb_str_modify(v);
10065 arg[i] = (VALUE)StringValueCStr(v);
10066 }
10067 else {
10068 arg[i] = (VALUE)NUM2LONG(argv[i]);
10069 }
10070 }
10071
10072 switch (argc) {
10073 case 1:
10074 retval = SYSCALL(num);
10075 break;
10076 case 2:
10077 retval = SYSCALL(num, arg[0]);
10078 break;
10079 case 3:
10080 retval = SYSCALL(num, arg[0],arg[1]);
10081 break;
10082 case 4:
10083 retval = SYSCALL(num, arg[0],arg[1],arg[2]);
10084 break;
10085 case 5:
10086 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3]);
10087 break;
10088 case 6:
10089 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4]);
10090 break;
10091 case 7:
10092 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5]);
10093 break;
10094 case 8:
10095 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6]);
10096 break;
10097 }
10098
10099 if (retval == -1)
10100 rb_sys_fail(0);
10101 return RETVAL2NUM(retval);
10102 #undef SYSCALL
10103 #undef NUM2SYSCALLID
10104 #undef RETVAL2NUM
10105 }
10106 #else
10107 #define rb_f_syscall rb_f_notimplement
10108 #endif
10109
10110 static VALUE
10111 io_new_instance(VALUE args)
10112 {
10113 return rb_class_new_instance(2, (VALUE*)args+1, *(VALUE*)args);
10114 }
10115
10116 static rb_encoding *
10117 find_encoding(VALUE v)
10118 {
10119 rb_encoding *enc = rb_find_encoding(v);
10120 if (!enc) rb_warn("Unsupported encoding %"PRIsVALUE" ignored", v);
10121 return enc;
10122 }
10123
10124 static void
10125 io_encoding_set(rb_io_t *fptr, VALUE v1, VALUE v2, VALUE opt)
10126 {
10127 rb_encoding *enc, *enc2;
10128 int ecflags = fptr->encs.ecflags;
10129 VALUE ecopts, tmp;
10130
10131 if (!NIL_P(v2)) {
10132 enc2 = find_encoding(v1);
10133 tmp = rb_check_string_type(v2);
10134 if (!NIL_P(tmp)) {
10135 if (RSTRING_LEN(tmp) == 1 && RSTRING_PTR(tmp)[0] == '-') {
10136 /* Special case - "-" => no transcoding */
10137 enc = enc2;
10138 enc2 = NULL;
10139 }
10140 else
10141 enc = find_encoding(v2);
10142 if (enc == enc2) {
10143 /* Special case - "-" => no transcoding */
10144 enc2 = NULL;
10145 }
10146 }
10147 else {
10148 enc = find_encoding(v2);
10149 if (enc == enc2) {
10150 /* Special case - "-" => no transcoding */
10151 enc2 = NULL;
10152 }
10153 }
10154 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
10155 ecflags = rb_econv_prepare_options(opt, &ecopts, ecflags);
10156 }
10157 else {
10158 if (NIL_P(v1)) {
10159 /* Set to default encodings */
10160 rb_io_ext_int_to_encs(NULL, NULL, &enc, &enc2, 0);
10161 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
10162 ecopts = Qnil;
10163 }
10164 else {
10165 tmp = rb_check_string_type(v1);
10166 if (!NIL_P(tmp) && rb_enc_asciicompat(enc = rb_enc_get(tmp))) {
10167 parse_mode_enc(RSTRING_PTR(tmp), enc, &enc, &enc2, NULL);
10168 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
10169 ecflags = rb_econv_prepare_options(opt, &ecopts, ecflags);
10170 }
10171 else {
10172 rb_io_ext_int_to_encs(find_encoding(v1), NULL, &enc, &enc2, 0);
10173 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
10174 ecopts = Qnil;
10175 }
10176 }
10177 }
10178 validate_enc_binmode(&fptr->mode, ecflags, enc, enc2);
10179 fptr->encs.enc = enc;
10180 fptr->encs.enc2 = enc2;
10181 fptr->encs.ecflags = ecflags;
10182 fptr->encs.ecopts = ecopts;
10183 clear_codeconv(fptr);
10184
10185 }
10186
10187 struct io_encoding_set_args {
10188 rb_io_t *fptr;
10189 VALUE v1;
10190 VALUE v2;
10191 VALUE opt;
10192 };
10193
10194 static VALUE
10195 io_encoding_set_v(VALUE v)
10196 {
10197 struct io_encoding_set_args *arg = (struct io_encoding_set_args *)v;
10198 io_encoding_set(arg->fptr, arg->v1, arg->v2, arg->opt);
10199 return Qnil;
10200 }
10201
10202 static VALUE
10203 pipe_pair_close(VALUE rw)
10204 {
10205 VALUE *rwp = (VALUE *)rw;
10206 return rb_ensure(io_close, rwp[0], io_close, rwp[1]);
10207 }
10208
10209 /*
10210 * call-seq:
10211 * IO.pipe -> [read_io, write_io]
10212 * IO.pipe(ext_enc) -> [read_io, write_io]
10213 * IO.pipe("ext_enc:int_enc" [, opt]) -> [read_io, write_io]
10214 * IO.pipe(ext_enc, int_enc [, opt]) -> [read_io, write_io]
10215 *
10216 * IO.pipe(...) {|read_io, write_io| ... }
10217 *
10218 * Creates a pair of pipe endpoints (connected to each other) and
10219 * returns them as a two-element array of IO objects:
10220 * <code>[</code> <i>read_io</i>, <i>write_io</i> <code>]</code>.
10221 *
10222 * If a block is given, the block is called and
10223 * returns the value of the block.
10224 * <i>read_io</i> and <i>write_io</i> are sent to the block as arguments.
10225 * If read_io and write_io are not closed when the block exits, they are closed.
10226 * i.e. closing read_io and/or write_io doesn't cause an error.
10227 *
10228 * Not available on all platforms.
10229 *
10230 * If an encoding (encoding name or encoding object) is specified as an optional argument,
10231 * read string from pipe is tagged with the encoding specified.
10232 * If the argument is a colon separated two encoding names "A:B",
10233 * the read string is converted from encoding A (external encoding)
10234 * to encoding B (internal encoding), then tagged with B.
10235 * If two optional arguments are specified, those must be
10236 * encoding objects or encoding names,
10237 * and the first one is the external encoding,
10238 * and the second one is the internal encoding.
10239 * If the external encoding and the internal encoding is specified,
10240 * optional hash argument specify the conversion option.
10241 *
10242 * In the example below, the two processes close the ends of the pipe
10243 * that they are not using. This is not just a cosmetic nicety. The
10244 * read end of a pipe will not generate an end of file condition if
10245 * there are any writers with the pipe still open. In the case of the
10246 * parent process, the <code>rd.read</code> will never return if it
10247 * does not first issue a <code>wr.close</code>.
10248 *
10249 * rd, wr = IO.pipe
10250 *
10251 * if fork
10252 * wr.close
10253 * puts "Parent got: <#{rd.read}>"
10254 * rd.close
10255 * Process.wait
10256 * else
10257 * rd.close
10258 * puts "Sending message to parent"
10259 * wr.write "Hi Dad"
10260 * wr.close
10261 * end
10262 *
10263 * <em>produces:</em>
10264 *
10265 * Sending message to parent
10266 * Parent got: <Hi Dad>
10267 */
10268
10269 static VALUE
10270 rb_io_s_pipe(int argc, VALUE *argv, VALUE klass)
10271 {
10272 int pipes[2], state;
10273 VALUE r, w, args[3], v1, v2;
10274 VALUE opt;
10275 rb_io_t *fptr, *fptr2;
10276 struct io_encoding_set_args ies_args;
10277 int fmode = 0;
10278 VALUE ret;
10279
10280 argc = rb_scan_args(argc, argv, "02:", &v1, &v2, &opt);
10281 if (rb_pipe(pipes) < 0)
10282 rb_sys_fail(0);
10283
10284 args[0] = klass;
10285 args[1] = INT2NUM(pipes[0]);
10286 args[2] = INT2FIX(O_RDONLY);
10287 r = rb_protect(io_new_instance, (VALUE)args, &state);
10288 if (state) {
10289 close(pipes[0]);
10290 close(pipes[1]);
10291 rb_jump_tag(state);
10292 }
10293 GetOpenFile(r, fptr);
10294
10295 ies_args.fptr = fptr;
10296 ies_args.v1 = v1;
10297 ies_args.v2 = v2;
10298 ies_args.opt = opt;
10299 rb_protect(io_encoding_set_v, (VALUE)&ies_args, &state);
10300 if (state) {
10301 close(pipes[1]);
10302 io_close(r);
10303 rb_jump_tag(state);
10304 }
10305
10306 args[1] = INT2NUM(pipes[1]);
10307 args[2] = INT2FIX(O_WRONLY);
10308 w = rb_protect(io_new_instance, (VALUE)args, &state);
10309 if (state) {
10310 close(pipes[1]);
10311 if (!NIL_P(r)) rb_io_close(r);
10312 rb_jump_tag(state);
10313 }
10314 GetOpenFile(w, fptr2);
10315 rb_io_synchronized(fptr2);
10316
10317 extract_binmode(opt, &fmode);
10318
10319 if ((fmode & FMODE_BINMODE) && v1 == Qnil) {
10320 rb_io_ascii8bit_binmode(r);
10321 rb_io_ascii8bit_binmode(w);
10322 }
10323
10324 #if DEFAULT_TEXTMODE
10325 if ((fptr->mode & FMODE_TEXTMODE) && (fmode & FMODE_BINMODE)) {
10326 fptr->mode &= ~FMODE_TEXTMODE;
10327 setmode(fptr->fd, O_BINARY);
10328 }
10329 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
10330 if (fptr->encs.ecflags & ECONV_DEFAULT_NEWLINE_DECORATOR) {
10331 fptr->encs.ecflags |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;
10332 }
10333 #endif
10334 #endif
10335 fptr->mode |= fmode;
10336 #if DEFAULT_TEXTMODE
10337 if ((fptr2->mode & FMODE_TEXTMODE) && (fmode & FMODE_BINMODE)) {
10338 fptr2->mode &= ~FMODE_TEXTMODE;
10339 setmode(fptr2->fd, O_BINARY);
10340 }
10341 #endif
10342 fptr2->mode |= fmode;
10343
10344 ret = rb_assoc_new(r, w);
10345 if (rb_block_given_p()) {
10346 VALUE rw[2];
10347 rw[0] = r;
10348 rw[1] = w;
10349 return rb_ensure(rb_yield, ret, pipe_pair_close, (VALUE)rw);
10350 }
10351 return ret;
10352 }
10353
10354 struct foreach_arg {
10355 int argc;
10356 VALUE *argv;
10357 VALUE io;
10358 };
10359
10360 static void
10361 open_key_args(VALUE klass, int argc, VALUE *argv, VALUE opt, struct foreach_arg *arg)
10362 {
10363 VALUE path, v;
10364 VALUE vmode = Qnil, vperm = Qnil;
10365
10366 path = *argv++;
10367 argc--;
10368 FilePathValue(path);
10369 arg->io = 0;
10370 arg->argc = argc;
10371 arg->argv = argv;
10372 if (NIL_P(opt)) {
10373 vmode = INT2NUM(O_RDONLY);
10374 vperm = INT2FIX(0666);
10375 }
10376 else if (!NIL_P(v = rb_hash_aref(opt, sym_open_args))) {
10377 int n;
10378
10379 v = rb_to_array_type(v);
10380 n = RARRAY_LENINT(v);
10381 rb_check_arity(n, 0, 3); /* rb_io_open */
10382 rb_scan_args_kw(RB_SCAN_ARGS_LAST_HASH_KEYWORDS, n, RARRAY_CONST_PTR(v), "02:", &vmode, &vperm, &opt);
10383 }
10384 arg->io = rb_io_open(klass, path, vmode, vperm, opt);
10385 }
10386
10387 static VALUE
10388 io_s_foreach(VALUE v)
10389 {
10390 struct getline_arg *arg = (void *)v;
10391 VALUE str;
10392
10393 while (!NIL_P(str = rb_io_getline_1(arg->rs, arg->limit, arg->chomp, arg->io))) {
10394 rb_lastline_set(str);
10395 rb_yield(str);
10396 }
10397 rb_lastline_set(Qnil);
10398 return Qnil;
10399 }
10400
10401 /*
10402 * call-seq:
10403 * IO.foreach(name, sep=$/ [, getline_args, open_args]) {|line| block } -> nil
10404 * IO.foreach(name, limit [, getline_args, open_args]) {|line| block } -> nil
10405 * IO.foreach(name, sep, limit [, getline_args, open_args]) {|line| block } -> nil
10406 * IO.foreach(...) -> an_enumerator
10407 *
10408 * Executes the block for every line in the named I/O port, where lines
10409 * are separated by <em>sep</em>.
10410 *
10411 * If no block is given, an enumerator is returned instead.
10412 *
10413 * IO.foreach("testfile") {|x| print "GOT ", x }
10414 *
10415 * <em>produces:</em>
10416 *
10417 * GOT This is line one
10418 * GOT This is line two
10419 * GOT This is line three
10420 * GOT And so on...
10421 *
10422 * If the last argument is a hash, it's the keyword argument to open.
10423 * See IO.readlines for details about getline_args.
10424 * And see also IO.read for details about open_args.
10425 *
10426 */
10427
10428 static VALUE
10429 rb_io_s_foreach(int argc, VALUE *argv, VALUE self)
10430 {
10431 VALUE opt;
10432 int orig_argc = argc;
10433 struct foreach_arg arg;
10434 struct getline_arg garg;
10435
10436 argc = rb_scan_args(argc, argv, "13:", NULL, NULL, NULL, NULL, &opt);
10437 RETURN_ENUMERATOR(self, orig_argc, argv);
10438 extract_getline_args(argc-1, argv+1, &garg);
10439 open_key_args(self, argc, argv, opt, &arg);
10440 if (NIL_P(arg.io)) return Qnil;
10441 extract_getline_opts(opt, &garg);
10442 check_getline_args(&garg.rs, &garg.limit, garg.io = arg.io);
10443 return rb_ensure(io_s_foreach, (VALUE)&garg, rb_io_close, arg.io);
10444 }
10445
10446 static VALUE
10447 io_s_readlines(VALUE v)
10448 {
10449 struct getline_arg *arg = (void *)v;
10450 return io_readlines(arg, arg->io);
10451 }
10452
10453 /*
10454 * call-seq:
10455 * IO.readlines(name, sep=$/ [, getline_args, open_args]) -> array
10456 * IO.readlines(name, limit [, getline_args, open_args]) -> array
10457 * IO.readlines(name, sep, limit [, getline_args, open_args]) -> array
10458 *
10459 * Reads the entire file specified by <i>name</i> as individual
10460 * lines, and returns those lines in an array. Lines are separated by
10461 * <i>sep</i>.
10462 *
10463 * a = IO.readlines("testfile")
10464 * a[0] #=> "This is line one\n"
10465 *
10466 * b = IO.readlines("testfile", chomp: true)
10467 * b[0] #=> "This is line one"
10468 *
10469 * If the last argument is a hash, it's the keyword argument to open.
10470 *
10471 * === Options for getline
10472 *
10473 * The options hash accepts the following keys:
10474 *
10475 * :chomp::
10476 * When the optional +chomp+ keyword argument has a true value,
10477 * <code>\n</code>, <code>\r</code>, and <code>\r\n</code>
10478 * will be removed from the end of each line.
10479 *
10480 * See also IO.read for details about open_args.
10481 */
10482
10483 static VALUE
10484 rb_io_s_readlines(int argc, VALUE *argv, VALUE io)
10485 {
10486 VALUE opt;
10487 struct foreach_arg arg;
10488 struct getline_arg garg;
10489
10490 argc = rb_scan_args(argc, argv, "13:", NULL, NULL, NULL, NULL, &opt);
10491 extract_getline_args(argc-1, argv+1, &garg);
10492 open_key_args(io, argc, argv, opt, &arg);
10493 if (NIL_P(arg.io)) return Qnil;
10494 extract_getline_opts(opt, &garg);
10495 check_getline_args(&garg.rs, &garg.limit, garg.io = arg.io);
10496 return rb_ensure(io_s_readlines, (VALUE)&garg, rb_io_close, arg.io);
10497 }
10498
10499 static VALUE
10500 io_s_read(VALUE v)
10501 {
10502 struct foreach_arg *arg = (void *)v;
10503 return io_read(arg->argc, arg->argv, arg->io);
10504 }
10505
10506 struct seek_arg {
10507 VALUE io;
10508 VALUE offset;
10509 int mode;
10510 };
10511
10512 static VALUE
10513 seek_before_access(VALUE argp)
10514 {
10515 struct seek_arg *arg = (struct seek_arg *)argp;
10516 rb_io_binmode(arg->io);
10517 return rb_io_seek(arg->io, arg->offset, arg->mode);
10518 }
10519
10520 /*
10521 * call-seq:
10522 * IO.read(name, [length [, offset]] [, opt] ) -> string
10523 *
10524 * Opens the file, optionally seeks to the given +offset+, then returns
10525 * +length+ bytes (defaulting to the rest of the file). #read ensures
10526 * the file is closed before returning.
10527 *
10528 * If +name+ starts with a pipe character (<code>"|"</code>), a subprocess is
10529 * created in the same way as Kernel#open, and its output is returned.
10530 *
10531 * === Options
10532 *
10533 * The options hash accepts the following keys:
10534 *
10535 * :encoding::
10536 * string or encoding
10537 *
10538 * Specifies the encoding of the read string. +:encoding+ will be ignored
10539 * if +length+ is specified. See Encoding.aliases for possible encodings.
10540 *
10541 * :mode::
10542 * string or integer
10543 *
10544 * Specifies the <i>mode</i> argument for open(). It must start
10545 * with an "r", otherwise it will cause an error.
10546 * See IO.new for the list of possible modes.
10547 *
10548 * :open_args::
10549 * array
10550 *
10551 * Specifies arguments for open() as an array. This key can not be used
10552 * in combination with either +:encoding+ or +:mode+.
10553 *
10554 * Examples:
10555 *
10556 * IO.read("testfile") #=> "This is line one\nThis is line two\nThis is line three\nAnd so on...\n"
10557 * IO.read("testfile", 20) #=> "This is line one\nThi"
10558 * IO.read("testfile", 20, 10) #=> "ne one\nThis is line "
10559 * IO.read("binfile", mode: "rb") #=> "\xF7\x00\x00\x0E\x12"
10560 */
10561
10562 static VALUE
10563 rb_io_s_read(int argc, VALUE *argv, VALUE io)
10564 {
10565 VALUE opt, offset;
10566 struct foreach_arg arg;
10567
10568 argc = rb_scan_args(argc, argv, "13:", NULL, NULL, &offset, NULL, &opt);
10569 open_key_args(io, argc, argv, opt, &arg);
10570 if (NIL_P(arg.io)) return Qnil;
10571 if (!NIL_P(offset)) {
10572 struct seek_arg sarg;
10573 int state = 0;
10574 sarg.io = arg.io;
10575 sarg.offset = offset;
10576 sarg.mode = SEEK_SET;
10577 rb_protect(seek_before_access, (VALUE)&sarg, &state);
10578 if (state) {
10579 rb_io_close(arg.io);
10580 rb_jump_tag(state);
10581 }
10582 if (arg.argc == 2) arg.argc = 1;
10583 }
10584 return rb_ensure(io_s_read, (VALUE)&arg, rb_io_close, arg.io);
10585 }
10586
10587 /*
10588 * call-seq:
10589 * IO.binread(name, [length [, offset]] ) -> string
10590 *
10591 * Opens the file, optionally seeks to the given <i>offset</i>, then
10592 * returns <i>length</i> bytes (defaulting to the rest of the file).
10593 * #binread ensures the file is closed before returning. The open mode
10594 * would be <code>"rb:ASCII-8BIT"</code>.
10595 *
10596 * IO.binread("testfile") #=> "This is line one\nThis is line two\nThis is line three\nAnd so on...\n"
10597 * IO.binread("testfile", 20) #=> "This is line one\nThi"
10598 * IO.binread("testfile", 20, 10) #=> "ne one\nThis is line "
10599 */
10600
10601 static VALUE
10602 rb_io_s_binread(int argc, VALUE *argv, VALUE io)
10603 {
10604 VALUE offset;
10605 struct foreach_arg arg;
10606 enum {
10607 fmode = FMODE_READABLE|FMODE_BINMODE,
10608 oflags = O_RDONLY
10609 #ifdef O_BINARY
10610 |O_BINARY
10611 #endif
10612 };
10613 convconfig_t convconfig = {NULL, NULL, 0, Qnil};
10614
10615 rb_scan_args(argc, argv, "12", NULL, NULL, &offset);
10616 FilePathValue(argv[0]);
10617 convconfig.enc = rb_ascii8bit_encoding();
10618 arg.io = rb_io_open_generic(io, argv[0], oflags, fmode, &convconfig, 0);
10619 if (NIL_P(arg.io)) return Qnil;
10620 arg.argv = argv+1;
10621 arg.argc = (argc > 1) ? 1 : 0;
10622 if (!NIL_P(offset)) {
10623 struct seek_arg sarg;
10624 int state = 0;
10625 sarg.io = arg.io;
10626 sarg.offset = offset;
10627 sarg.mode = SEEK_SET;
10628 rb_protect(seek_before_access, (VALUE)&sarg, &state);
10629 if (state) {
10630 rb_io_close(arg.io);
10631 rb_jump_tag(state);
10632 }
10633 }
10634 return rb_ensure(io_s_read, (VALUE)&arg, rb_io_close, arg.io);
10635 }
10636
10637 static VALUE
10638 io_s_write0(VALUE v)
10639 {
10640 struct write_arg *arg = (void * )v;
10641 return io_write(arg->io,arg->str,arg->nosync);
10642 }
10643
10644 static VALUE
10645 io_s_write(int argc, VALUE *argv, VALUE klass, int binary)
10646 {
10647 VALUE string, offset, opt;
10648 struct foreach_arg arg;
10649 struct write_arg warg;
10650
10651 rb_scan_args(argc, argv, "21:", NULL, &string, &offset, &opt);
10652
10653 if (NIL_P(opt)) opt = rb_hash_new();
10654 else opt = rb_hash_dup(opt);
10655
10656
10657 if (NIL_P(rb_hash_aref(opt,sym_mode))) {
10658 int mode = O_WRONLY|O_CREAT;
10659 #ifdef O_BINARY
10660 if (binary) mode |= O_BINARY;
10661 #endif
10662 if (NIL_P(offset)) mode |= O_TRUNC;
10663 rb_hash_aset(opt,sym_mode,INT2NUM(mode));
10664 }
10665 open_key_args(klass, argc, argv, opt, &arg);
10666
10667 #ifndef O_BINARY
10668 if (binary) rb_io_binmode_m(arg.io);
10669 #endif
10670
10671 if (NIL_P(arg.io)) return Qnil;
10672 if (!NIL_P(offset)) {
10673 struct seek_arg sarg;
10674 int state = 0;
10675 sarg.io = arg.io;
10676 sarg.offset = offset;
10677 sarg.mode = SEEK_SET;
10678 rb_protect(seek_before_access, (VALUE)&sarg, &state);
10679 if (state) {
10680 rb_io_close(arg.io);
10681 rb_jump_tag(state);
10682 }
10683 }
10684
10685 warg.io = arg.io;
10686 warg.str = string;
10687 warg.nosync = 0;
10688
10689 return rb_ensure(io_s_write0, (VALUE)&warg, rb_io_close, arg.io);
10690 }
10691
10692 /*
10693 * call-seq:
10694 * IO.write(name, string [, offset]) -> integer
10695 * IO.write(name, string [, offset] [, opt]) -> integer
10696 *
10697 * Opens the file, optionally seeks to the given <i>offset</i>, writes
10698 * <i>string</i>, then returns the length written. #write ensures the
10699 * file is closed before returning. If <i>offset</i> is not given in
10700 * write mode, the file is truncated. Otherwise, it is not truncated.
10701 *
10702 * IO.write("testfile", "0123456789", 20) #=> 10
10703 * # File could contain: "This is line one\nThi0123456789two\nThis is line three\nAnd so on...\n"
10704 * IO.write("testfile", "0123456789") #=> 10
10705 * # File would now read: "0123456789"
10706 *
10707 * If the last argument is a hash, it specifies options for the internal
10708 * open(). It accepts the following keys:
10709 *
10710 * :encoding::
10711 * string or encoding
10712 *
10713 * Specifies the encoding of the read string.
10714 * See Encoding.aliases for possible encodings.
10715 *
10716 * :mode::
10717 * string or integer
10718 *
10719 * Specifies the <i>mode</i> argument for open(). It must start
10720 * with "w", "a", or "r+", otherwise it will cause an error.
10721 * See IO.new for the list of possible modes.
10722 *
10723 * :perm::
10724 * integer
10725 *
10726 * Specifies the <i>perm</i> argument for open().
10727 *
10728 * :open_args::
10729 * array
10730 *
10731 * Specifies arguments for open() as an array.
10732 * This key can not be used in combination with other keys.
10733 */
10734
10735 static VALUE
10736 rb_io_s_write(int argc, VALUE *argv, VALUE io)
10737 {
10738 return io_s_write(argc, argv, io, 0);
10739 }
10740
10741 /*
10742 * call-seq:
10743 * IO.binwrite(name, string, [offset] ) -> integer
10744 * IO.binwrite(name, string, [offset], open_args ) -> integer
10745 *
10746 * Same as IO.write except opening the file in binary mode and
10747 * ASCII-8BIT encoding (<code>"wb:ASCII-8BIT"</code>).
10748 */
10749
10750 static VALUE
10751 rb_io_s_binwrite(int argc, VALUE *argv, VALUE io)
10752 {
10753 return io_s_write(argc, argv, io, 1);
10754 }
10755
10756 struct copy_stream_struct {
10757 VALUE src;
10758 VALUE dst;
10759 off_t copy_length; /* (off_t)-1 if not specified */
10760 off_t src_offset; /* (off_t)-1 if not specified */
10761
10762 int src_fd;
10763 int dst_fd;
10764 unsigned close_src : 1;
10765 unsigned close_dst : 1;
10766 int error_no;
10767 off_t total;
10768 const char *syserr;
10769 const char *notimp;
10770 VALUE th;
10771 struct stat src_stat;
10772 struct stat dst_stat;
10773 #ifdef HAVE_FCOPYFILE
10774 copyfile_state_t copyfile_state;
10775 #endif
10776 };
10777
10778 static void *
10779 exec_interrupts(void *arg)
10780 {
10781 VALUE th = (VALUE)arg;
10782 rb_thread_execute_interrupts(th);
10783 return NULL;
10784 }
10785
10786 /*
10787 * returns TRUE if the preceding system call was interrupted
10788 * so we can continue. If the thread was interrupted, we
10789 * reacquire the GVL to execute interrupts before continuing.
10790 */
10791 static int
10792 maygvl_copy_stream_continue_p(int has_gvl, struct copy_stream_struct *stp)
10793 {
10794 switch (errno) {
10795 case EINTR:
10796 #if defined(ERESTART)
10797 case ERESTART:
10798 #endif
10799 if (rb_thread_interrupted(stp->th)) {
10800 if (has_gvl)
10801 rb_thread_execute_interrupts(stp->th);
10802 else
10803 rb_thread_call_with_gvl(exec_interrupts, (void *)stp->th);
10804 }
10805 return TRUE;
10806 }
10807 return FALSE;
10808 }
10809
10810 #if USE_POLL
10811 # define IOWAIT_SYSCALL "poll"
10812 STATIC_ASSERT(pollin_expected, POLLIN == RB_WAITFD_IN);
10813 STATIC_ASSERT(pollout_expected, POLLOUT == RB_WAITFD_OUT);
10814 static int
10815 nogvl_wait_for_single_fd(int fd, short events)
10816 {
10817 struct pollfd fds;
10818
10819 fds.fd = fd;
10820 fds.events = events;
10821
10822 return poll(&fds, 1, -1);
10823 }
10824 #else /* !USE_POLL */
10825 # define IOWAIT_SYSCALL "select"
10826 static int
10827 nogvl_wait_for_single_fd(int fd, short events)
10828 {
10829 rb_fdset_t fds;
10830 int ret;
10831
10832 rb_fd_init(&fds);
10833 rb_fd_set(fd, &fds);
10834
10835 switch (events) {
10836 case RB_WAITFD_IN:
10837 ret = rb_fd_select(fd + 1, &fds, 0, 0, 0);
10838 break;
10839 case RB_WAITFD_OUT:
10840 ret = rb_fd_select(fd + 1, 0, &fds, 0, 0);
10841 break;
10842 default:
10843 VM_UNREACHABLE(nogvl_wait_for_single_fd);
10844 }
10845
10846 rb_fd_term(&fds);
10847 return ret;
10848 }
10849 #endif /* !USE_POLL */
10850
10851 static int
10852 maygvl_copy_stream_wait_read(int has_gvl, struct copy_stream_struct *stp)
10853 {
10854 int ret;
10855
10856 do {
10857 if (has_gvl) {
10858 ret = rb_wait_for_single_fd(stp->src_fd, RB_WAITFD_IN, NULL);
10859 }
10860 else {
10861 ret = nogvl_wait_for_single_fd(stp->src_fd, RB_WAITFD_IN);
10862 }
10863 } while (ret < 0 && maygvl_copy_stream_continue_p(has_gvl, stp));
10864
10865 if (ret < 0) {
10866 stp->syserr = IOWAIT_SYSCALL;
10867 stp->error_no = errno;
10868 return ret;
10869 }
10870 return 0;
10871 }
10872
10873 static int
10874 nogvl_copy_stream_wait_write(struct copy_stream_struct *stp)
10875 {
10876 int ret;
10877
10878 do {
10879 ret = nogvl_wait_for_single_fd(stp->dst_fd, RB_WAITFD_OUT);
10880 } while (ret < 0 && maygvl_copy_stream_continue_p(0, stp));
10881
10882 if (ret < 0) {
10883 stp->syserr = IOWAIT_SYSCALL;
10884 stp->error_no = errno;
10885 return ret;
10886 }
10887 return 0;
10888 }
10889
10890 #if defined HAVE_COPY_FILE_RANGE || (defined __linux__ && defined __NR_copy_file_range)
10891 # define USE_COPY_FILE_RANGE
10892 #endif
10893
10894 #ifdef USE_COPY_FILE_RANGE
10895
10896 static ssize_t
10897 simple_copy_file_range(int in_fd, off_t *in_offset, int out_fd, off_t *out_offset, size_t count, unsigned int flags)
10898 {
10899 #ifdef HAVE_COPY_FILE_RANGE
10900 return copy_file_range(in_fd, in_offset, out_fd, out_offset, count, flags);
10901 #else
10902 return syscall(__NR_copy_file_range, in_fd, in_offset, out_fd, out_offset, count, flags);
10903 #endif
10904 }
10905
10906 static int
10907 nogvl_copy_file_range(struct copy_stream_struct *stp)
10908 {
10909 ssize_t ss;
10910 off_t src_size;
10911 off_t copy_length, src_offset, *src_offset_ptr;
10912
10913 if (!S_ISREG(stp->src_stat.st_mode))
10914 return 0;
10915
10916 src_size = stp->src_stat.st_size;
10917 src_offset = stp->src_offset;
10918 if (src_offset >= (off_t)0) {
10919 src_offset_ptr = &src_offset;
10920 }
10921 else {
10922 src_offset_ptr = NULL; /* if src_offset_ptr is NULL, then bytes are read from in_fd starting from the file offset */
10923 }
10924
10925 copy_length = stp->copy_length;
10926 if (copy_length < (off_t)0) {
10927 if (src_offset < (off_t)0) {
10928 off_t current_offset;
10929 errno = 0;
10930 current_offset = lseek(stp->src_fd, 0, SEEK_CUR);
10931 if (current_offset < (off_t)0 && errno) {
10932 stp->syserr = "lseek";
10933 stp->error_no = errno;
10934 return (int)current_offset;
10935 }
10936 copy_length = src_size - current_offset;
10937 }
10938 else {
10939 copy_length = src_size - src_offset;
10940 }
10941 }
10942
10943 retry_copy_file_range:
10944 # if SIZEOF_OFF_T > SIZEOF_SIZE_T
10945 /* we are limited by the 32-bit ssize_t return value on 32-bit */
10946 ss = (copy_length > (off_t)SSIZE_MAX) ? SSIZE_MAX : (ssize_t)copy_length;
10947 # else
10948 ss = (ssize_t)copy_length;
10949 # endif
10950 ss = simple_copy_file_range(stp->src_fd, src_offset_ptr, stp->dst_fd, NULL, ss, 0);
10951 if (0 < ss) {
10952 stp->total += ss;
10953 copy_length -= ss;
10954 if (0 < copy_length) {
10955 goto retry_copy_file_range;
10956 }
10957 }
10958 if (ss < 0) {
10959 if (maygvl_copy_stream_continue_p(0, stp)) {
10960 goto retry_copy_file_range;
10961 }
10962 switch (errno) {
10963 case EINVAL:
10964 case EPERM: /* copy_file_range(2) doesn't exist (may happen in
10965 docker container) */
10966 #ifdef ENOSYS
10967 case ENOSYS:
10968 #endif
10969 #ifdef EXDEV
10970 case EXDEV: /* in_fd and out_fd are not on the same filesystem */
10971 #endif
10972 return 0;
10973 case EAGAIN:
10974 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
10975 case EWOULDBLOCK:
10976 #endif
10977 {
10978 int ret = nogvl_copy_stream_wait_write(stp);
10979 if (ret < 0) return ret;
10980 }
10981 goto retry_copy_file_range;
10982 case EBADF:
10983 {
10984 int e = errno;
10985 int flags = fcntl(stp->dst_fd, F_GETFL);
10986
10987 if (flags != -1 && flags & O_APPEND) {
10988 return 0;
10989 }
10990 errno = e;
10991 }
10992 }
10993 stp->syserr = "copy_file_range";
10994 stp->error_no = errno;
10995 return (int)ss;
10996 }
10997 return 1;
10998 }
10999 #endif
11000
11001 #ifdef HAVE_FCOPYFILE
11002 static int
11003 nogvl_fcopyfile(struct copy_stream_struct *stp)
11004 {
11005 off_t cur, ss = 0;
11006 const off_t src_offset = stp->src_offset;
11007 int ret;
11008
11009 if (stp->copy_length >= (off_t)0) {
11010 /* copy_length can't be specified in fcopyfile(3) */
11011 return 0;
11012 }
11013
11014 if (!S_ISREG(stp->src_stat.st_mode))
11015 return 0;
11016
11017 if (!S_ISREG(stp->dst_stat.st_mode))
11018 return 0;
11019 if (lseek(stp->dst_fd, 0, SEEK_CUR) > (off_t)0) /* if dst IO was already written */
11020 return 0;
11021
11022 if (src_offset > (off_t)0) {
11023 off_t r;
11024
11025 /* get current offset */
11026 errno = 0;
11027 cur = lseek(stp->src_fd, 0, SEEK_CUR);
11028 if (cur < (off_t)0 && errno) {
11029 stp->error_no = errno;
11030 return 1;
11031 }
11032
11033 errno = 0;
11034 r = lseek(stp->src_fd, src_offset, SEEK_SET);
11035 if (r < (off_t)0 && errno) {
11036 stp->error_no = errno;
11037 return 1;
11038 }
11039 }
11040
11041 stp->copyfile_state = copyfile_state_alloc(); /* this will be freed by copy_stream_finalize() */
11042 ret = fcopyfile(stp->src_fd, stp->dst_fd, stp->copyfile_state, COPYFILE_DATA);
11043 copyfile_state_get(stp->copyfile_state, COPYFILE_STATE_COPIED, &ss); /* get copied bytes */
11044
11045 if (ret == 0) { /* success */
11046 stp->total = ss;
11047 if (src_offset > (off_t)0) {
11048 off_t r;
11049 errno = 0;
11050 /* reset offset */
11051 r = lseek(stp->src_fd, cur, SEEK_SET);
11052 if (r < (off_t)0 && errno) {
11053 stp->error_no = errno;
11054 return 1;
11055 }
11056 }
11057 }
11058 else {
11059 switch (errno) {
11060 case ENOTSUP:
11061 case EPERM:
11062 case EINVAL:
11063 return 0;
11064 }
11065 stp->syserr = "fcopyfile";
11066 stp->error_no = errno;
11067 return (int)ret;
11068 }
11069 return 1;
11070 }
11071 #endif
11072
11073 #ifdef HAVE_SENDFILE
11074
11075 # ifdef __linux__
11076 # define USE_SENDFILE
11077
11078 # ifdef HAVE_SYS_SENDFILE_H
11079 # include <sys/sendfile.h>
11080 # endif
11081
11082 static ssize_t
11083 simple_sendfile(int out_fd, int in_fd, off_t *offset, off_t count)
11084 {
11085 return sendfile(out_fd, in_fd, offset, (size_t)count);
11086 }
11087
11088 # elif 0 /* defined(__FreeBSD__) || defined(__DragonFly__) */ || defined(__APPLE__)
11089 /* This runs on FreeBSD8.1 r30210, but sendfiles blocks its execution
11090 * without cpuset -l 0.
11091 */
11092 # define USE_SENDFILE
11093
11094 static ssize_t
11095 simple_sendfile(int out_fd, int in_fd, off_t *offset, off_t count)
11096 {
11097 int r;
11098 off_t pos = offset ? *offset : lseek(in_fd, 0, SEEK_CUR);
11099 off_t sbytes;
11100 # ifdef __APPLE__
11101 r = sendfile(in_fd, out_fd, pos, &count, NULL, 0);
11102 sbytes = count;
11103 # else
11104 r = sendfile(in_fd, out_fd, pos, (size_t)count, NULL, &sbytes, 0);
11105 # endif
11106 if (r != 0 && sbytes == 0) return r;
11107 if (offset) {
11108 *offset += sbytes;
11109 }
11110 else {
11111 lseek(in_fd, sbytes, SEEK_CUR);
11112 }
11113 return (ssize_t)sbytes;
11114 }
11115
11116 # endif
11117
11118 #endif
11119
11120 #ifdef USE_SENDFILE
11121 static int
11122 nogvl_copy_stream_sendfile(struct copy_stream_struct *stp)
11123 {
11124 ssize_t ss;
11125 off_t src_size;
11126 off_t copy_length;
11127 off_t src_offset;
11128 int use_pread;
11129
11130 if (!S_ISREG(stp->src_stat.st_mode))
11131 return 0;
11132
11133 src_size = stp->src_stat.st_size;
11134 #ifndef __linux__
11135 if ((stp->dst_stat.st_mode & S_IFMT) != S_IFSOCK)
11136 return 0;
11137 #endif
11138
11139 src_offset = stp->src_offset;
11140 use_pread = src_offset >= (off_t)0;
11141
11142 copy_length = stp->copy_length;
11143 if (copy_length < (off_t)0) {
11144 if (use_pread)
11145 copy_length = src_size - src_offset;
11146 else {
11147 off_t cur;
11148 errno = 0;
11149 cur = lseek(stp->src_fd, 0, SEEK_CUR);
11150 if (cur < (off_t)0 && errno) {
11151 stp->syserr = "lseek";
11152 stp->error_no = errno;
11153 return (int)cur;
11154 }
11155 copy_length = src_size - cur;
11156 }
11157 }
11158
11159 retry_sendfile:
11160 # if SIZEOF_OFF_T > SIZEOF_SIZE_T
11161 /* we are limited by the 32-bit ssize_t return value on 32-bit */
11162 ss = (copy_length > (off_t)SSIZE_MAX) ? SSIZE_MAX : (ssize_t)copy_length;
11163 # else
11164 ss = (ssize_t)copy_length;
11165 # endif
11166 if (use_pread) {
11167 ss = simple_sendfile(stp->dst_fd, stp->src_fd, &src_offset, ss);
11168 }
11169 else {
11170 ss = simple_sendfile(stp->dst_fd, stp->src_fd, NULL, ss);
11171 }
11172 if (0 < ss) {
11173 stp->total += ss;
11174 copy_length -= ss;
11175 if (0 < copy_length) {
11176 goto retry_sendfile;
11177 }
11178 }
11179 if (ss < 0) {
11180 if (maygvl_copy_stream_continue_p(0, stp))
11181 goto retry_sendfile;
11182 switch (errno) {
11183 case EINVAL:
11184 #ifdef ENOSYS
11185 case ENOSYS:
11186 #endif
11187 return 0;
11188 case EAGAIN:
11189 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
11190 case EWOULDBLOCK:
11191 #endif
11192 {
11193 int ret;
11194 #ifndef __linux__
11195 /*
11196 * Linux requires stp->src_fd to be a mmap-able (regular) file,
11197 * select() reports regular files to always be "ready", so
11198 * there is no need to select() on it.
11199 * Other OSes may have the same limitation for sendfile() which
11200 * allow us to bypass maygvl_copy_stream_wait_read()...
11201 */
11202 ret = maygvl_copy_stream_wait_read(0, stp);
11203 if (ret < 0) return ret;
11204 #endif
11205 ret = nogvl_copy_stream_wait_write(stp);
11206 if (ret < 0) return ret;
11207 }
11208 goto retry_sendfile;
11209 }
11210 stp->syserr = "sendfile";
11211 stp->error_no = errno;
11212 return (int)ss;
11213 }
11214 return 1;
11215 }
11216 #endif
11217
11218 static ssize_t
11219 maygvl_read(int has_gvl, int fd, void *buf, size_t count)
11220 {
11221 if (has_gvl)
11222 return rb_read_internal(fd, buf, count);
11223 else
11224 return read(fd, buf, count);
11225 }
11226
11227 static ssize_t
11228 maygvl_copy_stream_read(int has_gvl, struct copy_stream_struct *stp, char *buf, size_t len, off_t offset)
11229 {
11230 ssize_t ss;
11231 retry_read:
11232 if (offset < (off_t)0) {
11233 ss = maygvl_read(has_gvl, stp->src_fd, buf, len);
11234 }
11235 else {
11236 #ifdef HAVE_PREAD
11237 ss = pread(stp->src_fd, buf, len, offset);
11238 #else
11239 stp->notimp = "pread";
11240 return -1;
11241 #endif
11242 }
11243 if (ss == 0) {
11244 return 0;
11245 }
11246 if (ss < 0) {
11247 if (maygvl_copy_stream_continue_p(has_gvl, stp))
11248 goto retry_read;
11249 switch (errno) {
11250 case EAGAIN:
11251 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
11252 case EWOULDBLOCK:
11253 #endif
11254 {
11255 int ret = maygvl_copy_stream_wait_read(has_gvl, stp);
11256 if (ret < 0) return ret;
11257 }
11258 goto retry_read;
11259 #ifdef ENOSYS
11260 case ENOSYS:
11261 stp->notimp = "pread";
11262 return ss;
11263 #endif
11264 }
11265 stp->syserr = offset < (off_t)0 ? "read" : "pread";
11266 stp->error_no = errno;
11267 }
11268 return ss;
11269 }
11270
11271 static int
11272 nogvl_copy_stream_write(struct copy_stream_struct *stp, char *buf, size_t len)
11273 {
11274 ssize_t ss;
11275 int off = 0;
11276 while (len) {
11277 ss = write(stp->dst_fd, buf+off, len);
11278 if (ss < 0) {
11279 if (maygvl_copy_stream_continue_p(0, stp))
11280 continue;
11281 if (errno == EAGAIN || errno == EWOULDBLOCK) {
11282 int ret = nogvl_copy_stream_wait_write(stp);
11283 if (ret < 0) return ret;
11284 continue;
11285 }
11286 stp->syserr = "write";
11287 stp->error_no = errno;
11288 return (int)ss;
11289 }
11290 off += (int)ss;
11291 len -= (int)ss;
11292 stp->total += ss;
11293 }
11294 return 0;
11295 }
11296
11297 static void
11298 nogvl_copy_stream_read_write(struct copy_stream_struct *stp)
11299 {
11300 char buf[1024*16];
11301 size_t len;
11302 ssize_t ss;
11303 int ret;
11304 off_t copy_length;
11305 int use_eof;
11306 off_t src_offset;
11307 int use_pread;
11308
11309 copy_length = stp->copy_length;
11310 use_eof = copy_length < (off_t)0;
11311 src_offset = stp->src_offset;
11312 use_pread = src_offset >= (off_t)0;
11313
11314 if (use_pread && stp->close_src) {
11315 off_t r;
11316 errno = 0;
11317 r = lseek(stp->src_fd, src_offset, SEEK_SET);
11318 if (r < (off_t)0 && errno) {
11319 stp->syserr = "lseek";
11320 stp->error_no = errno;
11321 return;
11322 }
11323 src_offset = (off_t)-1;
11324 use_pread = 0;
11325 }
11326
11327 while (use_eof || 0 < copy_length) {
11328 if (!use_eof && copy_length < (off_t)sizeof(buf)) {
11329 len = (size_t)copy_length;
11330 }
11331 else {
11332 len = sizeof(buf);
11333 }
11334 if (use_pread) {
11335 ss = maygvl_copy_stream_read(0, stp, buf, len, src_offset);
11336 if (0 < ss)
11337 src_offset += ss;
11338 }
11339 else {
11340 ss = maygvl_copy_stream_read(0, stp, buf, len, (off_t)-1);
11341 }
11342 if (ss <= 0) /* EOF or error */
11343 return;
11344
11345 ret = nogvl_copy_stream_write(stp, buf, ss);
11346 if (ret < 0)
11347 return;
11348
11349 if (!use_eof)
11350 copy_length -= ss;
11351 }
11352 }
11353
11354 static void *
11355 nogvl_copy_stream_func(void *arg)
11356 {
11357 struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
11358 #if defined(USE_SENDFILE) || defined(USE_COPY_FILE_RANGE) || defined(HAVE_FCOPYFILE)
11359 int ret;
11360 #endif
11361
11362 #ifdef USE_COPY_FILE_RANGE
11363 ret = nogvl_copy_file_range(stp);
11364 if (ret != 0)
11365 goto finish; /* error or success */
11366 #endif
11367
11368 #ifdef HAVE_FCOPYFILE
11369 ret = nogvl_fcopyfile(stp);
11370 if (ret != 0)
11371 goto finish; /* error or success */
11372 #endif
11373
11374 #ifdef USE_SENDFILE
11375 ret = nogvl_copy_stream_sendfile(stp);
11376 if (ret != 0)
11377 goto finish; /* error or success */
11378 #endif
11379
11380 nogvl_copy_stream_read_write(stp);
11381
11382 #if defined(USE_SENDFILE) || defined(USE_COPY_FILE_RANGE) || defined(HAVE_FCOPYFILE)
11383 finish:
11384 #endif
11385 return 0;
11386 }
11387
11388 static VALUE
11389 copy_stream_fallback_body(VALUE arg)
11390 {
11391 struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
11392 const int buflen = 16*1024;
11393 VALUE n;
11394 VALUE buf = rb_str_buf_new(buflen);
11395 off_t rest = stp->copy_length;
11396 off_t off = stp->src_offset;
11397 ID read_method = id_readpartial;
11398
11399 if (stp->src_fd < 0) {
11400 if (!rb_respond_to(stp->src, read_method)) {
11401 read_method = id_read;
11402 }
11403 }
11404
11405 while (1) {
11406 long numwrote;
11407 long l;
11408 if (stp->copy_length < (off_t)0) {
11409 l = buflen;
11410 }
11411 else {
11412 if (rest == 0) {
11413 rb_str_resize(buf, 0);
11414 break;
11415 }
11416 l = buflen < rest ? buflen : (long)rest;
11417 }
11418 if (stp->src_fd < 0) {
11419 VALUE rc = rb_funcall(stp->src, read_method, 2, INT2FIX(l), buf);
11420
11421 if (read_method == id_read && NIL_P(rc))
11422 break;
11423 }
11424 else {
11425 ssize_t ss;
11426 rb_str_resize(buf, buflen);
11427 ss = maygvl_copy_stream_read(1, stp, RSTRING_PTR(buf), l, off);
11428 rb_str_resize(buf, ss > 0 ? ss : 0);
11429 if (ss < 0)
11430 return Qnil;
11431 if (ss == 0)
11432 rb_eof_error();
11433 if (off >= (off_t)0)
11434 off += ss;
11435 }
11436 n = rb_io_write(stp->dst, buf);
11437 numwrote = NUM2LONG(n);
11438 stp->total += numwrote;
11439 rest -= numwrote;
11440 if (read_method == id_read && RSTRING_LEN(buf) == 0) {
11441 break;
11442 }
11443 }
11444
11445 return Qnil;
11446 }
11447
11448 static VALUE
11449 copy_stream_fallback(struct copy_stream_struct *stp)
11450 {
11451 if (stp->src_fd < 0 && stp->src_offset >= (off_t)0) {
11452 rb_raise(rb_eArgError, "cannot specify src_offset for non-IO");
11453 }
11454 rb_rescue2(copy_stream_fallback_body, (VALUE)stp,
11455 (VALUE (*) (VALUE, VALUE))0, (VALUE)0,
11456 rb_eEOFError, (VALUE)0);
11457 return Qnil;
11458 }
11459
11460 static VALUE
11461 copy_stream_body(VALUE arg)
11462 {
11463 struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
11464 VALUE src_io = stp->src, dst_io = stp->dst;
11465 rb_io_t *src_fptr = 0, *dst_fptr = 0;
11466 int src_fd, dst_fd;
11467 const int common_oflags = 0
11468 #ifdef O_NOCTTY
11469 | O_NOCTTY
11470 #endif
11471 ;
11472
11473 stp->th = rb_thread_current();
11474
11475 stp->total = 0;
11476
11477 if (src_io == argf ||
11478 !(RB_TYPE_P(src_io, T_FILE) ||
11479 RB_TYPE_P(src_io, T_STRING) ||
11480 rb_respond_to(src_io, rb_intern("to_path")))) {
11481 src_fd = -1;
11482 }
11483 else {
11484 int stat_ret;
11485 VALUE tmp_io = rb_io_check_io(src_io);
11486 if (!NIL_P(tmp_io)) {
11487 src_io = tmp_io;
11488 }
11489 else if (!RB_TYPE_P(src_io, T_FILE)) {
11490 VALUE args[2];
11491 FilePathValue(src_io);
11492 args[0] = src_io;
11493 args[1] = INT2NUM(O_RDONLY|common_oflags);
11494 src_io = rb_class_new_instance(2, args, rb_cFile);
11495 stp->src = src_io;
11496 stp->close_src = 1;
11497 }
11498 GetOpenFile(src_io, src_fptr);
11499 rb_io_check_byte_readable(src_fptr);
11500 src_fd = src_fptr->fd;
11501
11502 stat_ret = fstat(src_fd, &stp->src_stat);
11503 if (stat_ret < 0) {
11504 stp->syserr = "fstat";
11505 stp->error_no = errno;
11506 return Qnil;
11507 }
11508 }
11509 stp->src_fd = src_fd;
11510
11511 if (dst_io == argf ||
11512 !(RB_TYPE_P(dst_io, T_FILE) ||
11513 RB_TYPE_P(dst_io, T_STRING) ||
11514 rb_respond_to(dst_io, rb_intern("to_path")))) {
11515 dst_fd = -1;
11516 }
11517 else {
11518 int stat_ret;
11519 VALUE tmp_io = rb_io_check_io(dst_io);
11520 if (!NIL_P(tmp_io)) {
11521 dst_io = GetWriteIO(tmp_io);
11522 }
11523 else if (!RB_TYPE_P(dst_io, T_FILE)) {
11524 VALUE args[3];
11525 FilePathValue(dst_io);
11526 args[0] = dst_io;
11527 args[1] = INT2NUM(O_WRONLY|O_CREAT|O_TRUNC|common_oflags);
11528 args[2] = INT2FIX(0666);
11529 dst_io = rb_class_new_instance(3, args, rb_cFile);
11530 stp->dst = dst_io;
11531 stp->close_dst = 1;
11532 }
11533 else {
11534 dst_io = GetWriteIO(dst_io);
11535 stp->dst = dst_io;
11536 }
11537 GetOpenFile(dst_io, dst_fptr);
11538 rb_io_check_writable(dst_fptr);
11539 dst_fd = dst_fptr->fd;
11540
11541 stat_ret = fstat(dst_fd, &stp->dst_stat);
11542 if (stat_ret < 0) {
11543 stp->syserr = "fstat";
11544 stp->error_no = errno;
11545 return Qnil;
11546 }
11547 }
11548 stp->dst_fd = dst_fd;
11549
11550 #ifdef O_BINARY
11551 if (src_fptr)
11552 SET_BINARY_MODE_WITH_SEEK_CUR(src_fptr);
11553 #endif
11554 if (dst_fptr)
11555 io_ascii8bit_binmode(dst_fptr);
11556
11557 if (stp->src_offset < (off_t)0 && src_fptr && src_fptr->rbuf.len) {
11558 size_t len = src_fptr->rbuf.len;
11559 VALUE str;
11560 if (stp->copy_length >= (off_t)0 && stp->copy_length < (off_t)len) {
11561 len = (size_t)stp->copy_length;
11562 }
11563 str = rb_str_buf_new(len);
11564 rb_str_resize(str,len);
11565 read_buffered_data(RSTRING_PTR(str), len, src_fptr);
11566 if (dst_fptr) { /* IO or filename */
11567 if (io_binwrite(str, RSTRING_PTR(str), RSTRING_LEN(str), dst_fptr, 0) < 0)
11568 rb_sys_fail(0);
11569 }
11570 else /* others such as StringIO */
11571 rb_io_write(dst_io, str);
11572 rb_str_resize(str, 0);
11573 stp->total += len;
11574 if (stp->copy_length >= (off_t)0)
11575 stp->copy_length -= len;
11576 }
11577
11578 if (dst_fptr && io_fflush(dst_fptr) < 0) {
11579 rb_raise(rb_eIOError, "flush failed");
11580 }
11581
11582 if (stp->copy_length == 0)
11583 return Qnil;
11584
11585 if (src_fd < 0 || dst_fd < 0) {
11586 return copy_stream_fallback(stp);
11587 }
11588
11589 rb_thread_call_without_gvl(nogvl_copy_stream_func, (void*)stp, RUBY_UBF_IO, 0);
11590 return Qnil;
11591 }
11592
11593 static VALUE
11594 copy_stream_finalize(VALUE arg)
11595 {
11596 struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
11597
11598 #ifdef HAVE_FCOPYFILE
11599 if (stp->copyfile_state) {
11600 copyfile_state_free(stp->copyfile_state);
11601 }
11602 #endif
11603
11604 if (stp->close_src) {
11605 rb_io_close_m(stp->src);
11606 }
11607 if (stp->close_dst) {
11608 rb_io_close_m(stp->dst);
11609 }
11610 if (stp->syserr) {
11611 rb_syserr_fail(stp->error_no, stp->syserr);
11612 }
11613 if (stp->notimp) {
11614 rb_raise(rb_eNotImpError, "%s() not implemented", stp->notimp);
11615 }
11616 return Qnil;
11617 }
11618
11619 /*
11620 * call-seq:
11621 * IO.copy_stream(src, dst)
11622 * IO.copy_stream(src, dst, copy_length)
11623 * IO.copy_stream(src, dst, copy_length, src_offset)
11624 *
11625 * IO.copy_stream copies <i>src</i> to <i>dst</i>.
11626 * <i>src</i> and <i>dst</i> is either a filename or an IO-like object.
11627 * IO-like object for <i>src</i> should have #readpartial or #read
11628 * method. IO-like object for <i>dst</i> should have #write method.
11629 * (Specialized mechanisms, such as sendfile system call, may be used
11630 * on appropriate situation.)
11631 *
11632 * This method returns the number of bytes copied.
11633 *
11634 * If optional arguments are not given,
11635 * the start position of the copy is
11636 * the beginning of the filename or
11637 * the current file offset of the IO.
11638 * The end position of the copy is the end of file.
11639 *
11640 * If <i>copy_length</i> is given,
11641 * No more than <i>copy_length</i> bytes are copied.
11642 *
11643 * If <i>src_offset</i> is given,
11644 * it specifies the start position of the copy.
11645 *
11646 * When <i>src_offset</i> is specified and
11647 * <i>src</i> is an IO,
11648 * IO.copy_stream doesn't move the current file offset.
11649 *
11650 */
11651 static VALUE
11652 rb_io_s_copy_stream(int argc, VALUE *argv, VALUE io)
11653 {
11654 VALUE src, dst, length, src_offset;
11655 struct copy_stream_struct st;
11656
11657 MEMZERO(&st, struct copy_stream_struct, 1);
11658
11659 rb_scan_args(argc, argv, "22", &src, &dst, &length, &src_offset);
11660
11661 st.src = src;
11662 st.dst = dst;
11663
11664 if (NIL_P(length))
11665 st.copy_length = (off_t)-1;
11666 else
11667 st.copy_length = NUM2OFFT(length);
11668
11669 if (NIL_P(src_offset))
11670 st.src_offset = (off_t)-1;
11671 else
11672 st.src_offset = NUM2OFFT(src_offset);
11673
11674 rb_ensure(copy_stream_body, (VALUE)&st, copy_stream_finalize, (VALUE)&st);
11675
11676 return OFFT2NUM(st.total);
11677 }
11678
11679 /*
11680 * call-seq:
11681 * io.external_encoding -> encoding
11682 *
11683 * Returns the Encoding object that represents the encoding of the file.
11684 * If _io_ is in write mode and no encoding is specified, returns +nil+.
11685 */
11686
11687 static VALUE
11688 rb_io_external_encoding(VALUE io)
11689 {
11690 rb_io_t *fptr;
11691
11692 GetOpenFile(io, fptr);
11693 if (fptr->encs.enc2) {
11694 return rb_enc_from_encoding(fptr->encs.enc2);
11695 }
11696 if (fptr->mode & FMODE_WRITABLE) {
11697 if (fptr->encs.enc)
11698 return rb_enc_from_encoding(fptr->encs.enc);
11699 return Qnil;
11700 }
11701 return rb_enc_from_encoding(io_read_encoding(fptr));
11702 }
11703
11704 /*
11705 * call-seq:
11706 * io.internal_encoding -> encoding
11707 *
11708 * Returns the Encoding of the internal string if conversion is
11709 * specified. Otherwise returns +nil+.
11710 */
11711
11712 static VALUE
11713 rb_io_internal_encoding(VALUE io)
11714 {
11715 rb_io_t *fptr;
11716
11717 GetOpenFile(io, fptr);
11718 if (!fptr->encs.enc2) return Qnil;
11719 return rb_enc_from_encoding(io_read_encoding(fptr));
11720 }
11721
11722 /*
11723 * call-seq:
11724 * io.set_encoding(ext_enc) -> io
11725 * io.set_encoding("ext_enc:int_enc") -> io
11726 * io.set_encoding(ext_enc, int_enc) -> io
11727 * io.set_encoding("ext_enc:int_enc", opt) -> io
11728 * io.set_encoding(ext_enc, int_enc, opt) -> io
11729 *
11730 * If single argument is specified, read string from io is tagged
11731 * with the encoding specified. If encoding is a colon separated two
11732 * encoding names "A:B", the read string is converted from encoding A
11733 * (external encoding) to encoding B (internal encoding), then tagged
11734 * with B. If two arguments are specified, those must be encoding
11735 * objects or encoding names, and the first one is the external encoding, and the
11736 * second one is the internal encoding.
11737 * If the external encoding and the internal encoding is specified,
11738 * optional hash argument specify the conversion option.
11739 */
11740
11741 static VALUE
11742 rb_io_set_encoding(int argc, VALUE *argv, VALUE io)
11743 {
11744 rb_io_t *fptr;
11745 VALUE v1, v2, opt;
11746
11747 if (!RB_TYPE_P(io, T_FILE)) {
11748 return rb_funcallv(io, id_set_encoding, argc, argv);
11749 }
11750
11751 argc = rb_scan_args(argc, argv, "11:", &v1, &v2, &opt);
11752 GetOpenFile(io, fptr);
11753 io_encoding_set(fptr, v1, v2, opt);
11754 return io;
11755 }
11756
11757 void
11758 rb_stdio_set_default_encoding(void)
11759 {
11760 VALUE val = Qnil;
11761
11762 rb_io_set_encoding(1, &val, rb_stdin);
11763 rb_io_set_encoding(1, &val, rb_stdout);
11764 rb_io_set_encoding(1, &val, rb_stderr);
11765 }
11766
11767 static inline int
11768 global_argf_p(VALUE arg)
11769 {
11770 return arg == argf;
11771 }
11772
11773 /*
11774 * call-seq:
11775 * ARGF.external_encoding -> encoding
11776 *
11777 * Returns the external encoding for files read from +ARGF+ as an +Encoding+
11778 * object. The external encoding is the encoding of the text as stored in a
11779 * file. Contrast with +ARGF.internal_encoding+, which is the encoding used
11780 * to represent this text within Ruby.
11781 *
11782 * To set the external encoding use +ARGF.set_encoding+.
11783 *
11784 * For example:
11785 *
11786 * ARGF.external_encoding #=> #<Encoding:UTF-8>
11787 *
11788 */
11789 static VALUE
11790 argf_external_encoding(VALUE argf)
11791 {
11792 if (!RTEST(ARGF.current_file)) {
11793 return rb_enc_from_encoding(rb_default_external_encoding());
11794 }
11795 return rb_io_external_encoding(rb_io_check_io(ARGF.current_file));
11796 }
11797
11798 /*
11799 * call-seq:
11800 * ARGF.internal_encoding -> encoding
11801 *
11802 * Returns the internal encoding for strings read from +ARGF+ as an
11803 * +Encoding+ object.
11804 *
11805 * If +ARGF.set_encoding+ has been called with two encoding names, the second
11806 * is returned. Otherwise, if +Encoding.default_external+ has been set, that
11807 * value is returned. Failing that, if a default external encoding was
11808 * specified on the command-line, that value is used. If the encoding is
11809 * unknown, +nil+ is returned.
11810 */
11811 static VALUE
11812 argf_internal_encoding(VALUE argf)
11813 {
11814 if (!RTEST(ARGF.current_file)) {
11815 return rb_enc_from_encoding(rb_default_external_encoding());
11816 }
11817 return rb_io_internal_encoding(rb_io_check_io(ARGF.current_file));
11818 }
11819
11820 /*
11821 * call-seq:
11822 * ARGF.set_encoding(ext_enc) -> ARGF
11823 * ARGF.set_encoding("ext_enc:int_enc") -> ARGF
11824 * ARGF.set_encoding(ext_enc, int_enc) -> ARGF
11825 * ARGF.set_encoding("ext_enc:int_enc", opt) -> ARGF
11826 * ARGF.set_encoding(ext_enc, int_enc, opt) -> ARGF
11827 *
11828 * If single argument is specified, strings read from ARGF are tagged with
11829 * the encoding specified.
11830 *
11831 * If two encoding names separated by a colon are given, e.g. "ascii:utf-8",
11832 * the read string is converted from the first encoding (external encoding)
11833 * to the second encoding (internal encoding), then tagged with the second
11834 * encoding.
11835 *
11836 * If two arguments are specified, they must be encoding objects or encoding
11837 * names. Again, the first specifies the external encoding; the second
11838 * specifies the internal encoding.
11839 *
11840 * If the external encoding and the internal encoding are specified, the
11841 * optional +Hash+ argument can be used to adjust the conversion process. The
11842 * structure of this hash is explained in the String#encode documentation.
11843 *
11844 * For example:
11845 *
11846 * ARGF.set_encoding('ascii') # Tag the input as US-ASCII text
11847 * ARGF.set_encoding(Encoding::UTF_8) # Tag the input as UTF-8 text
11848 * ARGF.set_encoding('utf-8','ascii') # Transcode the input from US-ASCII
11849 * # to UTF-8.
11850 */
11851 static VALUE
11852 argf_set_encoding(int argc, VALUE *argv, VALUE argf)
11853 {
11854 rb_io_t *fptr;
11855
11856 if (!next_argv()) {
11857 rb_raise(rb_eArgError, "no stream to set encoding");
11858 }
11859 rb_io_set_encoding(argc, argv, ARGF.current_file);
11860 GetOpenFile(ARGF.current_file, fptr);
11861 ARGF.encs = fptr->encs;
11862 return argf;
11863 }
11864
11865 /*
11866 * call-seq:
11867 * ARGF.tell -> Integer
11868 * ARGF.pos -> Integer
11869 *
11870 * Returns the current offset (in bytes) of the current file in +ARGF+.
11871 *
11872 * ARGF.pos #=> 0
11873 * ARGF.gets #=> "This is line one\n"
11874 * ARGF.pos #=> 17
11875 *
11876 */
11877 static VALUE
11878 argf_tell(VALUE argf)
11879 {
11880 if (!next_argv()) {
11881 rb_raise(rb_eArgError, "no stream to tell");
11882 }
11883 ARGF_FORWARD(0, 0);
11884 return rb_io_tell(ARGF.current_file);
11885 }
11886
11887 /*
11888 * call-seq:
11889 * ARGF.seek(amount, whence=IO::SEEK_SET) -> 0
11890 *
11891 * Seeks to offset _amount_ (an +Integer+) in the +ARGF+ stream according to
11892 * the value of _whence_. See IO#seek for further details.
11893 */
11894 static VALUE
11895 argf_seek_m(int argc, VALUE *argv, VALUE argf)
11896 {
11897 if (!next_argv()) {
11898 rb_raise(rb_eArgError, "no stream to seek");
11899 }
11900 ARGF_FORWARD(argc, argv);
11901 return rb_io_seek_m(argc, argv, ARGF.current_file);
11902 }
11903
11904 /*
11905 * call-seq:
11906 * ARGF.pos = position -> Integer
11907 *
11908 * Seeks to the position given by _position_ (in bytes) in +ARGF+.
11909 *
11910 * For example:
11911 *
11912 * ARGF.pos = 17
11913 * ARGF.gets #=> "This is line two\n"
11914 */
11915 static VALUE
11916 argf_set_pos(VALUE argf, VALUE offset)
11917 {
11918 if (!next_argv()) {
11919 rb_raise(rb_eArgError, "no stream to set position");
11920 }
11921 ARGF_FORWARD(1, &offset);
11922 return rb_io_set_pos(ARGF.current_file, offset);
11923 }
11924
11925 /*
11926 * call-seq:
11927 * ARGF.rewind -> 0
11928 *
11929 * Positions the current file to the beginning of input, resetting
11930 * +ARGF.lineno+ to zero.
11931 *
11932 * ARGF.readline #=> "This is line one\n"
11933 * ARGF.rewind #=> 0
11934 * ARGF.lineno #=> 0
11935 * ARGF.readline #=> "This is line one\n"
11936 */
11937 static VALUE
11938 argf_rewind(VALUE argf)
11939 {
11940 VALUE ret;
11941 int old_lineno;
11942
11943 if (!next_argv()) {
11944 rb_raise(rb_eArgError, "no stream to rewind");
11945 }
11946 ARGF_FORWARD(0, 0);
11947 old_lineno = RFILE(ARGF.current_file)->fptr->lineno;
11948 ret = rb_io_rewind(ARGF.current_file);
11949 if (!global_argf_p(argf)) {
11950 ARGF.last_lineno = ARGF.lineno -= old_lineno;
11951 }
11952 return ret;
11953 }
11954
11955 /*
11956 * call-seq:
11957 * ARGF.fileno -> integer
11958 * ARGF.to_i -> integer
11959 *
11960 * Returns an integer representing the numeric file descriptor for
11961 * the current file. Raises an +ArgumentError+ if there isn't a current file.
11962 *
11963 * ARGF.fileno #=> 3
11964 */
11965 static VALUE
11966 argf_fileno(VALUE argf)
11967 {
11968 if (!next_argv()) {
11969 rb_raise(rb_eArgError, "no stream");
11970 }
11971 ARGF_FORWARD(0, 0);
11972 return rb_io_fileno(ARGF.current_file);
11973 }
11974
11975 /*
11976 * call-seq:
11977 * ARGF.to_io -> IO
11978 *
11979 * Returns an +IO+ object representing the current file. This will be a
11980 * +File+ object unless the current file is a stream such as STDIN.
11981 *
11982 * For example:
11983 *
11984 * ARGF.to_io #=> #<File:glark.txt>
11985 * ARGF.to_io #=> #<IO:<STDIN>>
11986 */
11987 static VALUE
11988 argf_to_io(VALUE argf)
11989 {
11990 next_argv();
11991 ARGF_FORWARD(0, 0);
11992 return ARGF.current_file;
11993 }
11994
11995 /*
11996 * call-seq:
11997 * ARGF.eof? -> true or false
11998 * ARGF.eof -> true or false
11999 *
12000 * Returns true if the current file in +ARGF+ is at end of file, i.e. it has
12001 * no data to read. The stream must be opened for reading or an +IOError+
12002 * will be raised.
12003 *
12004 * $ echo "eof" | ruby argf.rb
12005 *
12006 * ARGF.eof? #=> false
12007 * 3.times { ARGF.readchar }
12008 * ARGF.eof? #=> false
12009 * ARGF.readchar #=> "\n"
12010 * ARGF.eof? #=> true
12011 */
12012
12013 static VALUE
12014 argf_eof(VALUE argf)
12015 {
12016 next_argv();
12017 if (RTEST(ARGF.current_file)) {
12018 if (ARGF.init_p == 0) return Qtrue;
12019 next_argv();
12020 ARGF_FORWARD(0, 0);
12021 if (rb_io_eof(ARGF.current_file)) {
12022 return Qtrue;
12023 }
12024 }
12025 return Qfalse;
12026 }
12027
12028 /*
12029 * call-seq:
12030 * ARGF.read([length [, outbuf]]) -> string, outbuf, or nil
12031 *
12032 * Reads _length_ bytes from ARGF. The files named on the command line
12033 * are concatenated and treated as a single file by this method, so when
12034 * called without arguments the contents of this pseudo file are returned in
12035 * their entirety.
12036 *
12037 * _length_ must be a non-negative integer or +nil+.
12038 *
12039 * If _length_ is a positive integer, +read+ tries to read
12040 * _length_ bytes without any conversion (binary mode).
12041 * It returns +nil+ if an EOF is encountered before anything can be read.
12042 * Fewer than _length_ bytes are returned if an EOF is encountered during
12043 * the read.
12044 * In the case of an integer _length_, the resulting string is always
12045 * in ASCII-8BIT encoding.
12046 *
12047 * If _length_ is omitted or is +nil+, it reads until EOF
12048 * and the encoding conversion is applied, if applicable.
12049 * A string is returned even if EOF is encountered before any data is read.
12050 *
12051 * If _length_ is zero, it returns an empty string (<code>""</code>).
12052 *
12053 * If the optional _outbuf_ argument is present,
12054 * it must reference a String, which will receive the data.
12055 * The _outbuf_ will contain only the received data after the method call
12056 * even if it is not empty at the beginning.
12057 *
12058 * For example:
12059 *
12060 * $ echo "small" > small.txt
12061 * $ echo "large" > large.txt
12062 * $ ./glark.rb small.txt large.txt
12063 *
12064 * ARGF.read #=> "small\nlarge"
12065 * ARGF.read(200) #=> "small\nlarge"
12066 * ARGF.read(2) #=> "sm"
12067 * ARGF.read(0) #=> ""
12068 *
12069 * Note that this method behaves like the fread() function in C.
12070 * This means it retries to invoke read(2) system calls to read data
12071 * with the specified length.
12072 * If you need the behavior like a single read(2) system call,
12073 * consider ARGF#readpartial or ARGF#read_nonblock.
12074 */
12075
12076 static VALUE
12077 argf_read(int argc, VALUE *argv, VALUE argf)
12078 {
12079 VALUE tmp, str, length;
12080 long len = 0;
12081
12082 rb_scan_args(argc, argv, "02", &length, &str);
12083 if (!NIL_P(length)) {
12084 len = NUM2LONG(argv[0]);
12085 }
12086 if (!NIL_P(str)) {
12087 StringValue(str);
12088 rb_str_resize(str,0);
12089 argv[1] = Qnil;
12090 }
12091
12092 retry:
12093 if (!next_argv()) {
12094 return str;
12095 }
12096 if (ARGF_GENERIC_INPUT_P()) {
12097 tmp = argf_forward(argc, argv, argf);
12098 }
12099 else {
12100 tmp = io_read(argc, argv, ARGF.current_file);
12101 }
12102 if (NIL_P(str)) str = tmp;
12103 else if (!NIL_P(tmp)) rb_str_append(str, tmp);
12104 if (NIL_P(tmp) || NIL_P(length)) {
12105 if (ARGF.next_p != -1) {
12106 argf_close(argf);
12107 ARGF.next_p = 1;
12108 goto retry;
12109 }
12110 }
12111 else if (argc >= 1) {
12112 long slen = RSTRING_LEN(str);
12113 if (slen < len) {
12114 len -= slen;
12115 argv[0] = INT2NUM(len);
12116 goto retry;
12117 }
12118 }
12119 return str;
12120 }
12121
12122 struct argf_call_arg {
12123 int argc;
12124 VALUE *argv;
12125 VALUE argf;
12126 };
12127
12128 static VALUE
12129 argf_forward_call(VALUE arg)
12130 {
12131 struct argf_call_arg *p = (struct argf_call_arg *)arg;
12132 argf_forward(p->argc, p->argv, p->argf);
12133 return Qnil;
12134 }
12135
12136 static VALUE argf_getpartial(int argc, VALUE *argv, VALUE argf, VALUE opts,
12137 int nonblock);
12138
12139 /*
12140 * call-seq:
12141 * ARGF.readpartial(maxlen) -> string
12142 * ARGF.readpartial(maxlen, outbuf) -> outbuf
12143 *
12144 * Reads at most _maxlen_ bytes from the ARGF stream.
12145 *
12146 * If the optional _outbuf_ argument is present,
12147 * it must reference a String, which will receive the data.
12148 * The _outbuf_ will contain only the received data after the method call
12149 * even if it is not empty at the beginning.
12150 *
12151 * It raises EOFError on end of ARGF stream.
12152 * Since ARGF stream is a concatenation of multiple files,
12153 * internally EOF is occur for each file.
12154 * ARGF.readpartial returns empty strings for EOFs except the last one and
12155 * raises EOFError for the last one.
12156 *
12157 */
12158
12159 static VALUE
12160 argf_readpartial(int argc, VALUE *argv, VALUE argf)
12161 {
12162 return argf_getpartial(argc, argv, argf, Qnil, 0);
12163 }
12164
12165 /*
12166 * call-seq:
12167 * ARGF.read_nonblock(maxlen[, options]) -> string
12168 * ARGF.read_nonblock(maxlen, outbuf[, options]) -> outbuf
12169 *
12170 * Reads at most _maxlen_ bytes from the ARGF stream in non-blocking mode.
12171 */
12172
12173 static VALUE
12174 argf_read_nonblock(int argc, VALUE *argv, VALUE argf)
12175 {
12176 VALUE opts;
12177
12178 rb_scan_args(argc, argv, "11:", NULL, NULL, &opts);
12179
12180 if (!NIL_P(opts))
12181 argc--;
12182
12183 return argf_getpartial(argc, argv, argf, opts, 1);
12184 }
12185
12186 static VALUE
12187 argf_getpartial(int argc, VALUE *argv, VALUE argf, VALUE opts, int nonblock)
12188 {
12189 VALUE tmp, str, length;
12190 int no_exception;
12191
12192 rb_scan_args(argc, argv, "11", &length, &str);
12193 if (!NIL_P(str)) {
12194 StringValue(str);
12195 argv[1] = str;
12196 }
12197 no_exception = no_exception_p(opts);
12198
12199 if (!next_argv()) {
12200 if (!NIL_P(str)) {
12201 rb_str_resize(str, 0);
12202 }
12203 rb_eof_error();
12204 }
12205 if (ARGF_GENERIC_INPUT_P()) {
12206 VALUE (*const rescue_does_nothing)(VALUE, VALUE) = 0;
12207 struct argf_call_arg arg;
12208 arg.argc = argc;
12209 arg.argv = argv;
12210 arg.argf = argf;
12211 tmp = rb_rescue2(argf_forward_call, (VALUE)&arg,
12212 rescue_does_nothing, Qnil, rb_eEOFError, (VALUE)0);
12213 }
12214 else {
12215 tmp = io_getpartial(argc, argv, ARGF.current_file, no_exception, nonblock);
12216 }
12217 if (NIL_P(tmp)) {
12218 if (ARGF.next_p == -1) {
12219 return io_nonblock_eof(no_exception);
12220 }
12221 argf_close(argf);
12222 ARGF.next_p = 1;
12223 if (RARRAY_LEN(ARGF.argv) == 0) {
12224 return io_nonblock_eof(no_exception);
12225 }
12226 if (NIL_P(str))
12227 str = rb_str_new(NULL, 0);
12228 return str;
12229 }
12230 return tmp;
12231 }
12232
12233 /*
12234 * call-seq:
12235 * ARGF.getc -> String or nil
12236 *
12237 * Reads the next character from +ARGF+ and returns it as a +String+. Returns
12238 * +nil+ at the end of the stream.
12239 *
12240 * +ARGF+ treats the files named on the command line as a single file created
12241 * by concatenating their contents. After returning the last character of the
12242 * first file, it returns the first character of the second file, and so on.
12243 *
12244 * For example:
12245 *
12246 * $ echo "foo" > file
12247 * $ ruby argf.rb file
12248 *
12249 * ARGF.getc #=> "f"
12250 * ARGF.getc #=> "o"
12251 * ARGF.getc #=> "o"
12252 * ARGF.getc #=> "\n"
12253 * ARGF.getc #=> nil
12254 * ARGF.getc #=> nil
12255 */
12256 static VALUE
12257 argf_getc(VALUE argf)
12258 {
12259 VALUE ch;
12260
12261 retry:
12262 if (!next_argv()) return Qnil;
12263 if (ARGF_GENERIC_INPUT_P()) {
12264 ch = rb_funcall3(ARGF.current_file, rb_intern("getc"), 0, 0);
12265 }
12266 else {
12267 ch = rb_io_getc(ARGF.current_file);
12268 }
12269 if (NIL_P(ch) && ARGF.next_p != -1) {
12270 argf_close(argf);
12271 ARGF.next_p = 1;
12272 goto retry;
12273 }
12274
12275 return ch;
12276 }
12277
12278 /*
12279 * call-seq:
12280 * ARGF.getbyte -> Integer or nil
12281 *
12282 * Gets the next 8-bit byte (0..255) from +ARGF+. Returns +nil+ if called at
12283 * the end of the stream.
12284 *
12285 * For example:
12286 *
12287 * $ echo "foo" > file
12288 * $ ruby argf.rb file
12289 *
12290 * ARGF.getbyte #=> 102
12291 * ARGF.getbyte #=> 111
12292 * ARGF.getbyte #=> 111
12293 * ARGF.getbyte #=> 10
12294 * ARGF.getbyte #=> nil
12295 */
12296 static VALUE
12297 argf_getbyte(VALUE argf)
12298 {
12299 VALUE ch;
12300
12301 retry:
12302 if (!next_argv()) return Qnil;
12303 if (!RB_TYPE_P(ARGF.current_file, T_FILE)) {
12304 ch = rb_funcall3(ARGF.current_file, rb_intern("getbyte"), 0, 0);
12305 }
12306 else {
12307 ch = rb_io_getbyte(ARGF.current_file);
12308 }
12309 if (NIL_P(ch) && ARGF.next_p != -1) {
12310 argf_close(argf);
12311 ARGF.next_p = 1;
12312 goto retry;
12313 }
12314
12315 return ch;
12316 }
12317
12318 /*
12319 * call-seq:
12320 * ARGF.readchar -> String or nil
12321 *
12322 * Reads the next character from +ARGF+ and returns it as a +String+. Raises
12323 * an +EOFError+ after the last character of the last file has been read.
12324 *
12325 * For example:
12326 *
12327 * $ echo "foo" > file
12328 * $ ruby argf.rb file
12329 *
12330 * ARGF.readchar #=> "f"
12331 * ARGF.readchar #=> "o"
12332 * ARGF.readchar #=> "o"
12333 * ARGF.readchar #=> "\n"
12334 * ARGF.readchar #=> end of file reached (EOFError)
12335 */
12336 static VALUE
12337 argf_readchar(VALUE argf)
12338 {
12339 VALUE ch;
12340
12341 retry:
12342 if (!next_argv()) rb_eof_error();
12343 if (!RB_TYPE_P(ARGF.current_file, T_FILE)) {
12344 ch = rb_funcall3(ARGF.current_file, rb_intern("getc"), 0, 0);
12345 }
12346 else {
12347 ch = rb_io_getc(ARGF.current_file);
12348 }
12349 if (NIL_P(ch) && ARGF.next_p != -1) {
12350 argf_close(argf);
12351 ARGF.next_p = 1;
12352 goto retry;
12353 }
12354
12355 return ch;
12356 }
12357
12358 /*
12359 * call-seq:
12360 * ARGF.readbyte -> Integer
12361 *
12362 * Reads the next 8-bit byte from ARGF and returns it as an +Integer+. Raises
12363 * an +EOFError+ after the last byte of the last file has been read.
12364 *
12365 * For example:
12366 *
12367 * $ echo "foo" > file
12368 * $ ruby argf.rb file
12369 *
12370 * ARGF.readbyte #=> 102
12371 * ARGF.readbyte #=> 111
12372 * ARGF.readbyte #=> 111
12373 * ARGF.readbyte #=> 10
12374 * ARGF.readbyte #=> end of file reached (EOFError)
12375 */
12376 static VALUE
12377 argf_readbyte(VALUE argf)
12378 {
12379 VALUE c;
12380
12381 NEXT_ARGF_FORWARD(0, 0);
12382 c = argf_getbyte(argf);
12383 if (NIL_P(c)) {
12384 rb_eof_error();
12385 }
12386 return c;
12387 }
12388
12389 #define FOREACH_ARGF() while (next_argv())
12390
12391 static VALUE
12392 argf_block_call_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, argf))
12393 {
12394 const VALUE current = ARGF.current_file;
12395 rb_yield_values2(argc, argv);
12396 if (ARGF.init_p == -1 || current != ARGF.current_file) {
12397 rb_iter_break_value(Qundef);
12398 }
12399 return Qnil;
12400 }
12401
12402 static void
12403 argf_block_call(ID mid, int argc, VALUE *argv, VALUE argf)
12404 {
12405 VALUE ret = rb_block_call(ARGF.current_file, mid, argc, argv, argf_block_call_i, argf);
12406 if (ret != Qundef) ARGF.next_p = 1;
12407 }
12408
12409 static VALUE
12410 argf_block_call_line_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, argf))
12411 {
12412 if (!global_argf_p(argf)) {
12413 ARGF.last_lineno = ++ARGF.lineno;
12414 }
12415 return argf_block_call_i(i, argf, argc, argv, blockarg);
12416 }
12417
12418 static void
12419 argf_block_call_line(ID mid, int argc, VALUE *argv, VALUE argf)
12420 {
12421 VALUE ret = rb_block_call(ARGF.current_file, mid, argc, argv, argf_block_call_line_i, argf);
12422 if (ret != Qundef) ARGF.next_p = 1;
12423 }
12424
12425 /*
12426 * call-seq:
12427 * ARGF.each(sep=$/) {|line| block } -> ARGF
12428 * ARGF.each(sep=$/, limit) {|line| block } -> ARGF
12429 * ARGF.each(...) -> an_enumerator
12430 *
12431 * ARGF.each_line(sep=$/) {|line| block } -> ARGF
12432 * ARGF.each_line(sep=$/, limit) {|line| block } -> ARGF
12433 * ARGF.each_line(...) -> an_enumerator
12434 *
12435 * Returns an enumerator which iterates over each line (separated by _sep_,
12436 * which defaults to your platform's newline character) of each file in
12437 * +ARGV+. If a block is supplied, each line in turn will be yielded to the
12438 * block, otherwise an enumerator is returned.
12439 * The optional _limit_ argument is an +Integer+ specifying the maximum
12440 * length of each line; longer lines will be split according to this limit.
12441 *
12442 * This method allows you to treat the files supplied on the command line as
12443 * a single file consisting of the concatenation of each named file. After
12444 * the last line of the first file has been returned, the first line of the
12445 * second file is returned. The +ARGF.filename+ and +ARGF.lineno+ methods can
12446 * be used to determine the filename of the current line and line number of
12447 * the whole input, respectively.
12448 *
12449 * For example, the following code prints out each line of each named file
12450 * prefixed with its line number, displaying the filename once per file:
12451 *
12452 * ARGF.each_line do |line|
12453 * puts ARGF.filename if ARGF.file.lineno == 1
12454 * puts "#{ARGF.file.lineno}: #{line}"
12455 * end
12456 *
12457 * While the following code prints only the first file's name at first, and
12458 * the contents with line number counted through all named files.
12459 *
12460 * ARGF.each_line do |line|
12461 * puts ARGF.filename if ARGF.lineno == 1
12462 * puts "#{ARGF.lineno}: #{line}"
12463 * end
12464 */
12465 static VALUE
12466 argf_each_line(int argc, VALUE *argv, VALUE argf)
12467 {
12468 RETURN_ENUMERATOR(argf, argc, argv);
12469 FOREACH_ARGF() {
12470 argf_block_call_line(rb_intern("each_line"), argc, argv, argf);
12471 }
12472 return argf;
12473 }
12474
12475 /*
12476 * This is a deprecated alias for #each_line.
12477 */
12478
12479 static VALUE
12480 argf_lines(int argc, VALUE *argv, VALUE argf)
12481 {
12482 rb_warn_deprecated("ARGF#lines", "#each_line");
12483 if (!rb_block_given_p())
12484 return rb_enumeratorize(argf, ID2SYM(rb_intern("each_line")), argc, argv);
12485 return argf_each_line(argc, argv, argf);
12486 }
12487
12488 /*
12489 * call-seq:
12490 * ARGF.bytes {|byte| block } -> ARGF
12491 * ARGF.bytes -> an_enumerator
12492 *
12493 * ARGF.each_byte {|byte| block } -> ARGF
12494 * ARGF.each_byte -> an_enumerator
12495 *
12496 * Iterates over each byte of each file in +ARGV+.
12497 * A byte is returned as an +Integer+ in the range 0..255.
12498 *
12499 * This method allows you to treat the files supplied on the command line as
12500 * a single file consisting of the concatenation of each named file. After
12501 * the last byte of the first file has been returned, the first byte of the
12502 * second file is returned. The +ARGF.filename+ method can be used to
12503 * determine the filename of the current byte.
12504 *
12505 * If no block is given, an enumerator is returned instead.
12506 *
12507 * For example:
12508 *
12509 * ARGF.bytes.to_a #=> [35, 32, ... 95, 10]
12510 *
12511 */
12512 static VALUE
12513 argf_each_byte(VALUE argf)
12514 {
12515 RETURN_ENUMERATOR(argf, 0, 0);
12516 FOREACH_ARGF() {
12517 argf_block_call(rb_intern("each_byte"), 0, 0, argf);
12518 }
12519 return argf;
12520 }
12521
12522 /*
12523 * This is a deprecated alias for #each_byte.
12524 */
12525
12526 static VALUE
12527 argf_bytes(VALUE argf)
12528 {
12529 rb_warn_deprecated("ARGF#bytes", "#each_byte");
12530 if (!rb_block_given_p())
12531 return rb_enumeratorize(argf, ID2SYM(rb_intern("each_byte")), 0, 0);
12532 return argf_each_byte(argf);
12533 }
12534
12535 /*
12536 * call-seq:
12537 * ARGF.each_char {|char| block } -> ARGF
12538 * ARGF.each_char -> an_enumerator
12539 *
12540 * Iterates over each character of each file in +ARGF+.
12541 *
12542 * This method allows you to treat the files supplied on the command line as
12543 * a single file consisting of the concatenation of each named file. After
12544 * the last character of the first file has been returned, the first
12545 * character of the second file is returned. The +ARGF.filename+ method can
12546 * be used to determine the name of the file in which the current character
12547 * appears.
12548 *
12549 * If no block is given, an enumerator is returned instead.
12550 */
12551 static VALUE
12552 argf_each_char(VALUE argf)
12553 {
12554 RETURN_ENUMERATOR(argf, 0, 0);
12555 FOREACH_ARGF() {
12556 argf_block_call(rb_intern("each_char"), 0, 0, argf);
12557 }
12558 return argf;
12559 }
12560
12561 /*
12562 * This is a deprecated alias for #each_char.
12563 */
12564
12565 static VALUE
12566 argf_chars(VALUE argf)
12567 {
12568 rb_warn_deprecated("ARGF#chars", "#each_char");
12569 if (!rb_block_given_p())
12570 return rb_enumeratorize(argf, ID2SYM(rb_intern("each_char")), 0, 0);
12571 return argf_each_char(argf);
12572 }
12573
12574 /*
12575 * call-seq:
12576 * ARGF.each_codepoint {|codepoint| block } -> ARGF
12577 * ARGF.each_codepoint -> an_enumerator
12578 *
12579 * Iterates over each codepoint of each file in +ARGF+.
12580 *
12581 * This method allows you to treat the files supplied on the command line as
12582 * a single file consisting of the concatenation of each named file. After
12583 * the last codepoint of the first file has been returned, the first
12584 * codepoint of the second file is returned. The +ARGF.filename+ method can
12585 * be used to determine the name of the file in which the current codepoint
12586 * appears.
12587 *
12588 * If no block is given, an enumerator is returned instead.
12589 */
12590 static VALUE
12591 argf_each_codepoint(VALUE argf)
12592 {
12593 RETURN_ENUMERATOR(argf, 0, 0);
12594 FOREACH_ARGF() {
12595 argf_block_call(rb_intern("each_codepoint"), 0, 0, argf);
12596 }
12597 return argf;
12598 }
12599
12600 /*
12601 * This is a deprecated alias for #each_codepoint.
12602 */
12603
12604 static VALUE
12605 argf_codepoints(VALUE argf)
12606 {
12607 rb_warn_deprecated("ARGF#codepoints", "#each_codepoint");
12608 if (!rb_block_given_p())
12609 return rb_enumeratorize(argf, ID2SYM(rb_intern("each_codepoint")), 0, 0);
12610 return argf_each_codepoint(argf);
12611 }
12612
12613 /*
12614 * call-seq:
12615 * ARGF.filename -> String
12616 * ARGF.path -> String
12617 *
12618 * Returns the current filename. "-" is returned when the current file is
12619 * STDIN.
12620 *
12621 * For example:
12622 *
12623 * $ echo "foo" > foo
12624 * $ echo "bar" > bar
12625 * $ echo "glark" > glark
12626 *
12627 * $ ruby argf.rb foo bar glark
12628 *
12629 * ARGF.filename #=> "foo"
12630 * ARGF.read(5) #=> "foo\nb"
12631 * ARGF.filename #=> "bar"
12632 * ARGF.skip
12633 * ARGF.filename #=> "glark"
12634 */
12635 static VALUE
12636 argf_filename(VALUE argf)
12637 {
12638 next_argv();
12639 return ARGF.filename;
12640 }
12641
12642 static VALUE
12643 argf_filename_getter(ID id, VALUE *var)
12644 {
12645 return argf_filename(*var);
12646 }
12647
12648 /*
12649 * call-seq:
12650 * ARGF.file -> IO or File object
12651 *
12652 * Returns the current file as an +IO+ or +File+ object.
12653 * <code>$stdin</code> is returned when the current file is STDIN.
12654 *
12655 * For example:
12656 *
12657 * $ echo "foo" > foo
12658 * $ echo "bar" > bar
12659 *
12660 * $ ruby argf.rb foo bar
12661 *
12662 * ARGF.file #=> #<File:foo>
12663 * ARGF.read(5) #=> "foo\nb"
12664 * ARGF.file #=> #<File:bar>
12665 */
12666 static VALUE
12667 argf_file(VALUE argf)
12668 {
12669 next_argv();
12670 return ARGF.current_file;
12671 }
12672
12673 /*
12674 * call-seq:
12675 * ARGF.binmode -> ARGF
12676 *
12677 * Puts +ARGF+ into binary mode. Once a stream is in binary mode, it cannot
12678 * be reset to non-binary mode. This option has the following effects:
12679 *
12680 * * Newline conversion is disabled.
12681 * * Encoding conversion is disabled.
12682 * * Content is treated as ASCII-8BIT.
12683 */
12684 static VALUE
12685 argf_binmode_m(VALUE argf)
12686 {
12687 ARGF.binmode = 1;
12688 next_argv();
12689 ARGF_FORWARD(0, 0);
12690 rb_io_ascii8bit_binmode(ARGF.current_file);
12691 return argf;
12692 }
12693
12694 /*
12695 * call-seq:
12696 * ARGF.binmode? -> true or false
12697 *
12698 * Returns true if +ARGF+ is being read in binary mode; false otherwise.
12699 * To enable binary mode use +ARGF.binmode+.
12700 *
12701 * For example:
12702 *
12703 * ARGF.binmode? #=> false
12704 * ARGF.binmode
12705 * ARGF.binmode? #=> true
12706 */
12707 static VALUE
12708 argf_binmode_p(VALUE argf)
12709 {
12710 return ARGF.binmode ? Qtrue : Qfalse;
12711 }
12712
12713 /*
12714 * call-seq:
12715 * ARGF.skip -> ARGF
12716 *
12717 * Sets the current file to the next file in ARGV. If there aren't any more
12718 * files it has no effect.
12719 *
12720 * For example:
12721 *
12722 * $ ruby argf.rb foo bar
12723 * ARGF.filename #=> "foo"
12724 * ARGF.skip
12725 * ARGF.filename #=> "bar"
12726 */
12727 static VALUE
12728 argf_skip(VALUE argf)
12729 {
12730 if (ARGF.init_p && ARGF.next_p == 0) {
12731 argf_close(argf);
12732 ARGF.next_p = 1;
12733 }
12734 return argf;
12735 }
12736
12737 /*
12738 * call-seq:
12739 * ARGF.close -> ARGF
12740 *
12741 * Closes the current file and skips to the next file in ARGV. If there are
12742 * no more files to open, just closes the current file. +STDIN+ will not be
12743 * closed.
12744 *
12745 * For example:
12746 *
12747 * $ ruby argf.rb foo bar
12748 *
12749 * ARGF.filename #=> "foo"
12750 * ARGF.close
12751 * ARGF.filename #=> "bar"
12752 * ARGF.close
12753 */
12754 static VALUE
12755 argf_close_m(VALUE argf)
12756 {
12757 next_argv();
12758 argf_close(argf);
12759 if (ARGF.next_p != -1) {
12760 ARGF.next_p = 1;
12761 }
12762 ARGF.lineno = 0;
12763 return argf;
12764 }
12765
12766 /*
12767 * call-seq:
12768 * ARGF.closed? -> true or false
12769 *
12770 * Returns _true_ if the current file has been closed; _false_ otherwise. Use
12771 * +ARGF.close+ to actually close the current file.
12772 */
12773 static VALUE
12774 argf_closed(VALUE argf)
12775 {
12776 next_argv();
12777 ARGF_FORWARD(0, 0);
12778 return rb_io_closed(ARGF.current_file);
12779 }
12780
12781 /*
12782 * call-seq:
12783 * ARGF.to_s -> String
12784 *
12785 * Returns "ARGF".
12786 */
12787 static VALUE
12788 argf_to_s(VALUE argf)
12789 {
12790 return rb_str_new2("ARGF");
12791 }
12792
12793 /*
12794 * call-seq:
12795 * ARGF.inplace_mode -> String
12796 *
12797 * Returns the file extension appended to the names of modified files under
12798 * in-place edit mode. This value can be set using +ARGF.inplace_mode=+ or
12799 * passing the +-i+ switch to the Ruby binary.
12800 */
12801 static VALUE
12802 argf_inplace_mode_get(VALUE argf)
12803 {
12804 if (!ARGF.inplace) return Qnil;
12805 if (NIL_P(ARGF.inplace)) return rb_str_new(0, 0);
12806 return rb_str_dup(ARGF.inplace);
12807 }
12808
12809 static VALUE
12810 opt_i_get(ID id, VALUE *var)
12811 {
12812 return argf_inplace_mode_get(*var);
12813 }
12814
12815 /*
12816 * call-seq:
12817 * ARGF.inplace_mode = ext -> ARGF
12818 *
12819 * Sets the filename extension for in-place editing mode to the given String.
12820 * Each file being edited has this value appended to its filename. The
12821 * modified file is saved under this new name.
12822 *
12823 * For example:
12824 *
12825 * $ ruby argf.rb file.txt
12826 *
12827 * ARGF.inplace_mode = '.bak'
12828 * ARGF.each_line do |line|
12829 * print line.sub("foo","bar")
12830 * end
12831 *
12832 * Each line of _file.txt_ has the first occurrence of "foo" replaced with
12833 * "bar", then the new line is written out to _file.txt.bak_.
12834 */
12835 static VALUE
12836 argf_inplace_mode_set(VALUE argf, VALUE val)
12837 {
12838 if (!RTEST(val)) {
12839 ARGF.inplace = Qfalse;
12840 }
12841 else if (StringValueCStr(val), !RSTRING_LEN(val)) {
12842 ARGF.inplace = Qnil;
12843 }
12844 else {
12845 ARGF.inplace = rb_str_new_frozen(val);
12846 }
12847 return argf;
12848 }
12849
12850 static void
12851 opt_i_set(VALUE val, ID id, VALUE *var)
12852 {
12853 argf_inplace_mode_set(*var, val);
12854 }
12855
12856 void
12857 ruby_set_inplace_mode(const char *suffix)
12858 {
12859 ARGF.inplace = !suffix ? Qfalse : !*suffix ? Qnil : rb_fstring_cstr(suffix);
12860 }
12861
12862 /*
12863 * call-seq:
12864 * ARGF.argv -> ARGV
12865 *
12866 * Returns the +ARGV+ array, which contains the arguments passed to your
12867 * script, one per element.
12868 *
12869 * For example:
12870 *
12871 * $ ruby argf.rb -v glark.txt
12872 *
12873 * ARGF.argv #=> ["-v", "glark.txt"]
12874 *
12875 */
12876 static VALUE
12877 argf_argv(VALUE argf)
12878 {
12879 return ARGF.argv;
12880 }
12881
12882 static VALUE
12883 argf_argv_getter(ID id, VALUE *var)
12884 {
12885 return argf_argv(*var);
12886 }
12887
12888 VALUE
12889 rb_get_argv(void)
12890 {
12891 return ARGF.argv;
12892 }
12893
12894 /*
12895 * call-seq:
12896 * ARGF.to_write_io -> io
12897 *
12898 * Returns IO instance tied to _ARGF_ for writing if inplace mode is
12899 * enabled.
12900 */
12901 static VALUE
12902 argf_write_io(VALUE argf)
12903 {
12904 if (!RTEST(ARGF.current_file)) {
12905 rb_raise(rb_eIOError, "not opened for writing");
12906 }
12907 return GetWriteIO(ARGF.current_file);
12908 }
12909
12910 /*
12911 * call-seq:
12912 * ARGF.write(string) -> integer
12913 *
12914 * Writes _string_ if inplace mode.
12915 */
12916 static VALUE
12917 argf_write(VALUE argf, VALUE str)
12918 {
12919 return rb_io_write(argf_write_io(argf), str);
12920 }
12921
12922 void
12923 rb_readwrite_sys_fail(enum rb_io_wait_readwrite writable, const char *mesg)
12924 {
12925 rb_readwrite_syserr_fail(writable, errno, mesg);
12926 }
12927
12928 void
12929 rb_readwrite_syserr_fail(enum rb_io_wait_readwrite writable, int n, const char *mesg)
12930 {
12931 VALUE arg;
12932 arg = mesg ? rb_str_new2(mesg) : Qnil;
12933 if (writable == RB_IO_WAIT_WRITABLE) {
12934 switch (n) {
12935 case EAGAIN:
12936 rb_exc_raise(rb_class_new_instance(1, &arg, rb_eEAGAINWaitWritable));
12937 break;
12938 #if EAGAIN != EWOULDBLOCK
12939 case EWOULDBLOCK:
12940 rb_exc_raise(rb_class_new_instance(1, &arg, rb_eEWOULDBLOCKWaitWritable));
12941 break;
12942 #endif
12943 case EINPROGRESS:
12944 rb_exc_raise(rb_class_new_instance(1, &arg, rb_eEINPROGRESSWaitWritable));
12945 break;
12946 default:
12947 rb_mod_sys_fail_str(rb_mWaitWritable, arg);
12948 }
12949 }
12950 else if (writable == RB_IO_WAIT_READABLE) {
12951 switch (n) {
12952 case EAGAIN:
12953 rb_exc_raise(rb_class_new_instance(1, &arg, rb_eEAGAINWaitReadable));
12954 break;
12955 #if EAGAIN != EWOULDBLOCK
12956 case EWOULDBLOCK:
12957 rb_exc_raise(rb_class_new_instance(1, &arg, rb_eEWOULDBLOCKWaitReadable));
12958 break;
12959 #endif
12960 case EINPROGRESS:
12961 rb_exc_raise(rb_class_new_instance(1, &arg, rb_eEINPROGRESSWaitReadable));
12962 break;
12963 default:
12964 rb_mod_sys_fail_str(rb_mWaitReadable, arg);
12965 }
12966 }
12967 else {
12968 rb_bug("invalid read/write type passed to rb_readwrite_sys_fail: %d", writable);
12969 }
12970 }
12971
12972 static VALUE
12973 get_LAST_READ_LINE(ID _x, VALUE *_y)
12974 {
12975 return rb_lastline_get();
12976 }
12977
12978 static void
12979 set_LAST_READ_LINE(VALUE val, ID _x, VALUE *_y)
12980 {
12981 rb_lastline_set(val);
12982 }
12983
12984 /*
12985 * Document-class: IOError
12986 *
12987 * Raised when an IO operation fails.
12988 *
12989 * File.open("/etc/hosts") {|f| f << "example"}
12990 * #=> IOError: not opened for writing
12991 *
12992 * File.open("/etc/hosts") {|f| f.close; f.read }
12993 * #=> IOError: closed stream
12994 *
12995 * Note that some IO failures raise <code>SystemCallError</code>s
12996 * and these are not subclasses of IOError:
12997 *
12998 * File.open("does/not/exist")
12999 * #=> Errno::ENOENT: No such file or directory - does/not/exist
13000 */
13001
13002 /*
13003 * Document-class: EOFError
13004 *
13005 * Raised by some IO operations when reaching the end of file. Many IO
13006 * methods exist in two forms,
13007 *
13008 * one that returns +nil+ when the end of file is reached, the other
13009 * raises +EOFError+.
13010 *
13011 * +EOFError+ is a subclass of +IOError+.
13012 *
13013 * file = File.open("/etc/hosts")
13014 * file.read
13015 * file.gets #=> nil
13016 * file.readline #=> EOFError: end of file reached
13017 */
13018
13019 /*
13020 * Document-class: ARGF
13021 *
13022 * +ARGF+ is a stream designed for use in scripts that process files given as
13023 * command-line arguments or passed in via STDIN.
13024 *
13025 * The arguments passed to your script are stored in the +ARGV+ Array, one
13026 * argument per element. +ARGF+ assumes that any arguments that aren't
13027 * filenames have been removed from +ARGV+. For example:
13028 *
13029 * $ ruby argf.rb --verbose file1 file2
13030 *
13031 * ARGV #=> ["--verbose", "file1", "file2"]
13032 * option = ARGV.shift #=> "--verbose"
13033 * ARGV #=> ["file1", "file2"]
13034 *
13035 * You can now use +ARGF+ to work with a concatenation of each of these named
13036 * files. For instance, +ARGF.read+ will return the contents of _file1_
13037 * followed by the contents of _file2_.
13038 *
13039 * After a file in +ARGV+ has been read +ARGF+ removes it from the Array.
13040 * Thus, after all files have been read +ARGV+ will be empty.
13041 *
13042 * You can manipulate +ARGV+ yourself to control what +ARGF+ operates on. If
13043 * you remove a file from +ARGV+, it is ignored by +ARGF+; if you add files to
13044 * +ARGV+, they are treated as if they were named on the command line. For
13045 * example:
13046 *
13047 * ARGV.replace ["file1"]
13048 * ARGF.readlines # Returns the contents of file1 as an Array
13049 * ARGV #=> []
13050 * ARGV.replace ["file2", "file3"]
13051 * ARGF.read # Returns the contents of file2 and file3
13052 *
13053 * If +ARGV+ is empty, +ARGF+ acts as if it contained STDIN, i.e. the data
13054 * piped to your script. For example:
13055 *
13056 * $ echo "glark" | ruby -e 'p ARGF.read'
13057 * "glark\n"
13058 */
13059
13060 /*
13061 * The IO class is the basis for all input and output in Ruby.
13062 * An I/O stream may be <em>duplexed</em> (that is, bidirectional), and
13063 * so may use more than one native operating system stream.
13064 *
13065 * Many of the examples in this section use the File class, the only standard
13066 * subclass of IO. The two classes are closely associated. Like the File
13067 * class, the Socket library subclasses from IO (such as TCPSocket or
13068 * UDPSocket).
13069 *
13070 * The Kernel#open method can create an IO (or File) object for these types
13071 * of arguments:
13072 *
13073 * * A plain string represents a filename suitable for the underlying
13074 * operating system.
13075 *
13076 * * A string starting with <code>"|"</code> indicates a subprocess.
13077 * The remainder of the string following the <code>"|"</code> is
13078 * invoked as a process with appropriate input/output channels
13079 * connected to it.
13080 *
13081 * * A string equal to <code>"|-"</code> will create another Ruby
13082 * instance as a subprocess.
13083 *
13084 * The IO may be opened with different file modes (read-only, write-only) and
13085 * encodings for proper conversion. See IO.new for these options. See
13086 * Kernel#open for details of the various command formats described above.
13087 *
13088 * IO.popen, the Open3 library, or Process#spawn may also be used to
13089 * communicate with subprocesses through an IO.
13090 *
13091 * Ruby will convert pathnames between different operating system
13092 * conventions if possible. For instance, on a Windows system the
13093 * filename <code>"/gumby/ruby/test.rb"</code> will be opened as
13094 * <code>"\gumby\ruby\test.rb"</code>. When specifying a Windows-style
13095 * filename in a Ruby string, remember to escape the backslashes:
13096 *
13097 * "C:\\gumby\\ruby\\test.rb"
13098 *
13099 * Our examples here will use the Unix-style forward slashes;
13100 * File::ALT_SEPARATOR can be used to get the platform-specific separator
13101 * character.
13102 *
13103 * The global constant ARGF (also accessible as <code>$<</code>) provides an
13104 * IO-like stream which allows access to all files mentioned on the
13105 * command line (or STDIN if no files are mentioned). ARGF#path and its alias
13106 * ARGF#filename are provided to access the name of the file currently being
13107 * read.
13108 *
13109 * == io/console
13110 *
13111 * The io/console extension provides methods for interacting with the
13112 * console. The console can be accessed from IO.console or the standard
13113 * input/output/error IO objects.
13114 *
13115 * Requiring io/console adds the following methods:
13116 *
13117 * * IO::console
13118 * * IO#raw
13119 * * IO#raw!
13120 * * IO#cooked
13121 * * IO#cooked!
13122 * * IO#getch
13123 * * IO#echo=
13124 * * IO#echo?
13125 * * IO#noecho
13126 * * IO#winsize
13127 * * IO#winsize=
13128 * * IO#iflush
13129 * * IO#ioflush
13130 * * IO#oflush
13131 *
13132 * Example:
13133 *
13134 * require 'io/console'
13135 * rows, columns = $stdout.winsize
13136 * puts "Your screen is #{columns} wide and #{rows} tall"
13137 */
13138
13139 void
13140 Init_IO(void)
13141 {
13142 #undef rb_intern
13143 #define rb_intern(str) rb_intern_const(str)
13144
13145 VALUE rb_cARGF;
13146 #ifdef __CYGWIN__
13147 #include <sys/cygwin.h>
13148 static struct __cygwin_perfile pf[] =
13149 {
13150 {"", O_RDONLY | O_BINARY},
13151 {"", O_WRONLY | O_BINARY},
13152 {"", O_RDWR | O_BINARY},
13153 {"", O_APPEND | O_BINARY},
13154 {NULL, 0}
13155 };
13156 cygwin_internal(CW_PERFILE, pf);
13157 #endif
13158
13159 rb_eIOError = rb_define_class("IOError", rb_eStandardError);
13160 rb_eEOFError = rb_define_class("EOFError", rb_eIOError);
13161
13162 id_write = rb_intern("write");
13163 id_read = rb_intern("read");
13164 id_getc = rb_intern("getc");
13165 id_flush = rb_intern("flush");
13166 id_readpartial = rb_intern("readpartial");
13167 id_set_encoding = rb_intern("set_encoding");
13168
13169 rb_define_global_function("syscall", rb_f_syscall, -1);
13170
13171 rb_define_global_function("open", rb_f_open, -1);
13172 rb_define_global_function("printf", rb_f_printf, -1);
13173 rb_define_global_function("print", rb_f_print, -1);
13174 rb_define_global_function("putc", rb_f_putc, 1);
13175 rb_define_global_function("puts", rb_f_puts, -1);
13176 rb_define_global_function("gets", rb_f_gets, -1);
13177 rb_define_global_function("readline", rb_f_readline, -1);
13178 rb_define_global_function("select", rb_f_select, -1);
13179
13180 rb_define_global_function("readlines", rb_f_readlines, -1);
13181
13182 rb_define_global_function("`", rb_f_backquote, 1);
13183
13184 rb_define_global_function("p", rb_f_p, -1);
13185 rb_define_method(rb_mKernel, "display", rb_obj_display, -1);
13186
13187 rb_cIO = rb_define_class("IO", rb_cObject);
13188 rb_include_module(rb_cIO, rb_mEnumerable);
13189
13190 /* exception to wait for reading. see IO.select. */
13191 rb_mWaitReadable = rb_define_module_under(rb_cIO, "WaitReadable");
13192 /* exception to wait for writing. see IO.select. */
13193 rb_mWaitWritable = rb_define_module_under(rb_cIO, "WaitWritable");
13194 /* exception to wait for reading by EAGAIN. see IO.select. */
13195 rb_eEAGAINWaitReadable = rb_define_class_under(rb_cIO, "EAGAINWaitReadable", rb_eEAGAIN);
13196 rb_include_module(rb_eEAGAINWaitReadable, rb_mWaitReadable);
13197 /* exception to wait for writing by EAGAIN. see IO.select. */
13198 rb_eEAGAINWaitWritable = rb_define_class_under(rb_cIO, "EAGAINWaitWritable", rb_eEAGAIN);
13199 rb_include_module(rb_eEAGAINWaitWritable, rb_mWaitWritable);
13200 #if EAGAIN == EWOULDBLOCK
13201 rb_eEWOULDBLOCKWaitReadable = rb_eEAGAINWaitReadable;
13202 /* same as IO::EAGAINWaitReadable */
13203 rb_define_const(rb_cIO, "EWOULDBLOCKWaitReadable", rb_eEAGAINWaitReadable);
13204 rb_eEWOULDBLOCKWaitWritable = rb_eEAGAINWaitWritable;
13205 /* same as IO::EAGAINWaitWritable */
13206 rb_define_const(rb_cIO, "EWOULDBLOCKWaitWritable", rb_eEAGAINWaitWritable);
13207 #else
13208 /* exception to wait for reading by EWOULDBLOCK. see IO.select. */
13209 rb_eEWOULDBLOCKWaitReadable = rb_define_class_under(rb_cIO, "EWOULDBLOCKWaitReadable", rb_eEWOULDBLOCK);
13210 rb_include_module(rb_eEWOULDBLOCKWaitReadable, rb_mWaitReadable);
13211 /* exception to wait for writing by EWOULDBLOCK. see IO.select. */
13212 rb_eEWOULDBLOCKWaitWritable = rb_define_class_under(rb_cIO, "EWOULDBLOCKWaitWritable", rb_eEWOULDBLOCK);
13213 rb_include_module(rb_eEWOULDBLOCKWaitWritable, rb_mWaitWritable);
13214 #endif
13215 /* exception to wait for reading by EINPROGRESS. see IO.select. */
13216 rb_eEINPROGRESSWaitReadable = rb_define_class_under(rb_cIO, "EINPROGRESSWaitReadable", rb_eEINPROGRESS);
13217 rb_include_module(rb_eEINPROGRESSWaitReadable, rb_mWaitReadable);
13218 /* exception to wait for writing by EINPROGRESS. see IO.select. */
13219 rb_eEINPROGRESSWaitWritable = rb_define_class_under(rb_cIO, "EINPROGRESSWaitWritable", rb_eEINPROGRESS);
13220 rb_include_module(rb_eEINPROGRESSWaitWritable, rb_mWaitWritable);
13221
13222 #if 0
13223 /* This is necessary only for forcing rdoc handle File::open */
13224 rb_define_singleton_method(rb_cFile, "open", rb_io_s_open, -1);
13225 #endif
13226
13227 rb_define_alloc_func(rb_cIO, io_alloc);
13228 rb_define_singleton_method(rb_cIO, "new", rb_io_s_new, -1);
13229 rb_define_singleton_method(rb_cIO, "open", rb_io_s_open, -1);
13230 rb_define_singleton_method(rb_cIO, "sysopen", rb_io_s_sysopen, -1);
13231 rb_define_singleton_method(rb_cIO, "for_fd", rb_io_s_for_fd, -1);
13232 rb_define_singleton_method(rb_cIO, "popen", rb_io_s_popen, -1);
13233 rb_define_singleton_method(rb_cIO, "foreach", rb_io_s_foreach, -1);
13234 rb_define_singleton_method(rb_cIO, "readlines", rb_io_s_readlines, -1);
13235 rb_define_singleton_method(rb_cIO, "read", rb_io_s_read, -1);
13236 rb_define_singleton_method(rb_cIO, "binread", rb_io_s_binread, -1);
13237 rb_define_singleton_method(rb_cIO, "write", rb_io_s_write, -1);
13238 rb_define_singleton_method(rb_cIO, "binwrite", rb_io_s_binwrite, -1);
13239 rb_define_singleton_method(rb_cIO, "select", rb_f_select, -1);
13240 rb_define_singleton_method(rb_cIO, "pipe", rb_io_s_pipe, -1);
13241 rb_define_singleton_method(rb_cIO, "try_convert", rb_io_s_try_convert, 1);
13242 rb_define_singleton_method(rb_cIO, "copy_stream", rb_io_s_copy_stream, -1);
13243
13244 rb_define_method(rb_cIO, "initialize", rb_io_initialize, -1);
13245
13246 rb_output_fs = Qnil;
13247 rb_define_hooked_variable("$,", &rb_output_fs, 0, rb_output_fs_setter);
13248
13249 rb_default_rs = rb_fstring_lit("\n"); /* avoid modifying RS_default */
13250 rb_gc_register_mark_object(rb_default_rs);
13251 rb_rs = rb_default_rs;
13252 rb_output_rs = Qnil;
13253 rb_define_hooked_variable("$/", &rb_rs, 0, rb_str_setter);
13254 rb_define_hooked_variable("$-0", &rb_rs, 0, rb_str_setter);
13255 rb_define_hooked_variable("$\\", &rb_output_rs, 0, rb_str_setter);
13256
13257 rb_define_virtual_variable("$_", get_LAST_READ_LINE, set_LAST_READ_LINE);
13258
13259 rb_define_method(rb_cIO, "initialize_copy", rb_io_init_copy, 1);
13260 rb_define_method(rb_cIO, "reopen", rb_io_reopen, -1);
13261
13262 rb_define_method(rb_cIO, "print", rb_io_print, -1);
13263 rb_define_method(rb_cIO, "putc", rb_io_putc, 1);
13264 rb_define_method(rb_cIO, "puts", rb_io_puts, -1);
13265 rb_define_method(rb_cIO, "printf", rb_io_printf, -1);
13266
13267 rb_define_method(rb_cIO, "each", rb_io_each_line, -1);
13268 rb_define_method(rb_cIO, "each_line", rb_io_each_line, -1);
13269 rb_define_method(rb_cIO, "each_byte", rb_io_each_byte, 0);
13270 rb_define_method(rb_cIO, "each_char", rb_io_each_char, 0);
13271 rb_define_method(rb_cIO, "each_codepoint", rb_io_each_codepoint, 0);
13272 rb_define_method(rb_cIO, "lines", rb_io_lines, -1);
13273 rb_define_method(rb_cIO, "bytes", rb_io_bytes, 0);
13274 rb_define_method(rb_cIO, "chars", rb_io_chars, 0);
13275 rb_define_method(rb_cIO, "codepoints", rb_io_codepoints, 0);
13276
13277 rb_define_method(rb_cIO, "syswrite", rb_io_syswrite, 1);
13278 rb_define_method(rb_cIO, "sysread", rb_io_sysread, -1);
13279
13280 rb_define_method(rb_cIO, "pread", rb_io_pread, -1);
13281 rb_define_method(rb_cIO, "pwrite", rb_io_pwrite, 2);
13282
13283 rb_define_method(rb_cIO, "fileno", rb_io_fileno, 0);
13284 rb_define_alias(rb_cIO, "to_i", "fileno");
13285 rb_define_method(rb_cIO, "to_io", rb_io_to_io, 0);
13286
13287 rb_define_method(rb_cIO, "fsync", rb_io_fsync, 0);
13288 rb_define_method(rb_cIO, "fdatasync", rb_io_fdatasync, 0);
13289 rb_define_method(rb_cIO, "sync", rb_io_sync, 0);
13290 rb_define_method(rb_cIO, "sync=", rb_io_set_sync, 1);
13291
13292 rb_define_method(rb_cIO, "lineno", rb_io_lineno, 0);
13293 rb_define_method(rb_cIO, "lineno=", rb_io_set_lineno, 1);
13294
13295 rb_define_method(rb_cIO, "readlines", rb_io_readlines, -1);
13296
13297 rb_define_method(rb_cIO, "readpartial", io_readpartial, -1);
13298 rb_define_method(rb_cIO, "read", io_read, -1);
13299 rb_define_method(rb_cIO, "write", io_write_m, -1);
13300 rb_define_method(rb_cIO, "gets", rb_io_gets_m, -1);
13301 rb_define_method(rb_cIO, "readline", rb_io_readline, -1);
13302 rb_define_method(rb_cIO, "getc", rb_io_getc, 0);
13303 rb_define_method(rb_cIO, "getbyte", rb_io_getbyte, 0);
13304 rb_define_method(rb_cIO, "readchar", rb_io_readchar, 0);
13305 rb_define_method(rb_cIO, "readbyte", rb_io_readbyte, 0);
13306 rb_define_method(rb_cIO, "ungetbyte",rb_io_ungetbyte, 1);
13307 rb_define_method(rb_cIO, "ungetc",rb_io_ungetc, 1);
13308 rb_define_method(rb_cIO, "<<", rb_io_addstr, 1);
13309 rb_define_method(rb_cIO, "flush", rb_io_flush, 0);
13310 rb_define_method(rb_cIO, "tell", rb_io_tell, 0);
13311 rb_define_method(rb_cIO, "seek", rb_io_seek_m, -1);
13312 /* Set I/O position from the beginning */
13313 rb_define_const(rb_cIO, "SEEK_SET", INT2FIX(SEEK_SET));
13314 /* Set I/O position from the current position */
13315 rb_define_const(rb_cIO, "SEEK_CUR", INT2FIX(SEEK_CUR));
13316 /* Set I/O position from the end */
13317 rb_define_const(rb_cIO, "SEEK_END", INT2FIX(SEEK_END));
13318 #ifdef SEEK_DATA
13319 /* Set I/O position to the next location containing data */
13320 rb_define_const(rb_cIO, "SEEK_DATA", INT2FIX(SEEK_DATA));
13321 #endif
13322 #ifdef SEEK_HOLE
13323 /* Set I/O position to the next hole */
13324 rb_define_const(rb_cIO, "SEEK_HOLE", INT2FIX(SEEK_HOLE));
13325 #endif
13326 rb_define_method(rb_cIO, "rewind", rb_io_rewind, 0);
13327 rb_define_method(rb_cIO, "pos", rb_io_tell, 0);
13328 rb_define_method(rb_cIO, "pos=", rb_io_set_pos, 1);
13329 rb_define_method(rb_cIO, "eof", rb_io_eof, 0);
13330 rb_define_method(rb_cIO, "eof?", rb_io_eof, 0);
13331
13332 rb_define_method(rb_cIO, "close_on_exec?", rb_io_close_on_exec_p, 0);
13333 rb_define_method(rb_cIO, "close_on_exec=", rb_io_set_close_on_exec, 1);
13334
13335 rb_define_method(rb_cIO, "close", rb_io_close_m, 0);
13336 rb_define_method(rb_cIO, "closed?", rb_io_closed, 0);
13337 rb_define_method(rb_cIO, "close_read", rb_io_close_read, 0);
13338 rb_define_method(rb_cIO, "close_write", rb_io_close_write, 0);
13339
13340 rb_define_method(rb_cIO, "isatty", rb_io_isatty, 0);
13341 rb_define_method(rb_cIO, "tty?", rb_io_isatty, 0);
13342 rb_define_method(rb_cIO, "binmode", rb_io_binmode_m, 0);
13343 rb_define_method(rb_cIO, "binmode?", rb_io_binmode_p, 0);
13344 rb_define_method(rb_cIO, "sysseek", rb_io_sysseek, -1);
13345 rb_define_method(rb_cIO, "advise", rb_io_advise, -1);
13346
13347 rb_define_method(rb_cIO, "ioctl", rb_io_ioctl, -1);
13348 rb_define_method(rb_cIO, "fcntl", rb_io_fcntl, -1);
13349 rb_define_method(rb_cIO, "pid", rb_io_pid, 0);
13350 rb_define_method(rb_cIO, "inspect", rb_io_inspect, 0);
13351
13352 rb_define_method(rb_cIO, "external_encoding", rb_io_external_encoding, 0);
13353 rb_define_method(rb_cIO, "internal_encoding", rb_io_internal_encoding, 0);
13354 rb_define_method(rb_cIO, "set_encoding", rb_io_set_encoding, -1);
13355 rb_define_method(rb_cIO, "set_encoding_by_bom", rb_io_set_encoding_by_bom, 0);
13356
13357 rb_define_method(rb_cIO, "autoclose?", rb_io_autoclose_p, 0);
13358 rb_define_method(rb_cIO, "autoclose=", rb_io_set_autoclose, 1);
13359
13360 rb_define_variable("$stdin", &rb_stdin);
13361 rb_stdin = prep_stdio(stdin, FMODE_READABLE, rb_cIO, "<STDIN>");
13362 rb_define_hooked_variable("$stdout", &rb_stdout, 0, stdout_setter);
13363 rb_stdout = prep_stdio(stdout, FMODE_WRITABLE, rb_cIO, "<STDOUT>");
13364 rb_define_hooked_variable("$stderr", &rb_stderr, 0, stdout_setter);
13365 rb_stderr = prep_stdio(stderr, FMODE_WRITABLE|FMODE_SYNC, rb_cIO, "<STDERR>");
13366 rb_define_hooked_variable("$>", &rb_stdout, 0, stdout_setter);
13367 orig_stdout = rb_stdout;
13368 orig_stderr = rb_stderr;
13369
13370 /* Holds the original stdin */
13371 rb_define_global_const("STDIN", rb_stdin);
13372 /* Holds the original stdout */
13373 rb_define_global_const("STDOUT", rb_stdout);
13374 /* Holds the original stderr */
13375 rb_define_global_const("STDERR", rb_stderr);
13376
13377 #if 0
13378 /* Hack to get rdoc to regard ARGF as a class: */
13379 rb_cARGF = rb_define_class("ARGF", rb_cObject);
13380 #endif
13381
13382 rb_cARGF = rb_class_new(rb_cObject);
13383 rb_set_class_path(rb_cARGF, rb_cObject, "ARGF.class");
13384 rb_define_alloc_func(rb_cARGF, argf_alloc);
13385
13386 rb_include_module(rb_cARGF, rb_mEnumerable);
13387
13388 rb_define_method(rb_cARGF, "initialize", argf_initialize, -2);
13389 rb_define_method(rb_cARGF, "initialize_copy", argf_initialize_copy, 1);
13390 rb_define_method(rb_cARGF, "to_s", argf_to_s, 0);
13391 rb_define_alias(rb_cARGF, "inspect", "to_s");
13392 rb_define_method(rb_cARGF, "argv", argf_argv, 0);
13393
13394 rb_define_method(rb_cARGF, "fileno", argf_fileno, 0);
13395 rb_define_method(rb_cARGF, "to_i", argf_fileno, 0);
13396 rb_define_method(rb_cARGF, "to_io", argf_to_io, 0);
13397 rb_define_method(rb_cARGF, "to_write_io", argf_write_io, 0);
13398 rb_define_method(rb_cARGF, "each", argf_each_line, -1);
13399 rb_define_method(rb_cARGF, "each_line", argf_each_line, -1);
13400 rb_define_method(rb_cARGF, "each_byte", argf_each_byte, 0);
13401 rb_define_method(rb_cARGF, "each_char", argf_each_char, 0);
13402 rb_define_method(rb_cARGF, "each_codepoint", argf_each_codepoint, 0);
13403 rb_define_method(rb_cARGF, "lines", argf_lines, -1);
13404 rb_define_method(rb_cARGF, "bytes", argf_bytes, 0);
13405 rb_define_method(rb_cARGF, "chars", argf_chars, 0);
13406 rb_define_method(rb_cARGF, "codepoints", argf_codepoints, 0);
13407
13408 rb_define_method(rb_cARGF, "read", argf_read, -1);
13409 rb_define_method(rb_cARGF, "readpartial", argf_readpartial, -1);
13410 rb_define_method(rb_cARGF, "read_nonblock", argf_read_nonblock, -1);
13411 rb_define_method(rb_cARGF, "readlines", argf_readlines, -1);
13412 rb_define_method(rb_cARGF, "to_a", argf_readlines, -1);
13413 rb_define_method(rb_cARGF, "gets", argf_gets, -1);
13414 rb_define_method(rb_cARGF, "readline", argf_readline, -1);
13415 rb_define_method(rb_cARGF, "getc", argf_getc, 0);
13416 rb_define_method(rb_cARGF, "getbyte", argf_getbyte, 0);
13417 rb_define_method(rb_cARGF, "readchar", argf_readchar, 0);
13418 rb_define_method(rb_cARGF, "readbyte", argf_readbyte, 0);
13419 rb_define_method(rb_cARGF, "tell", argf_tell, 0);
13420 rb_define_method(rb_cARGF, "seek", argf_seek_m, -1);
13421 rb_define_method(rb_cARGF, "rewind", argf_rewind, 0);
13422 rb_define_method(rb_cARGF, "pos", argf_tell, 0);
13423 rb_define_method(rb_cARGF, "pos=", argf_set_pos, 1);
13424 rb_define_method(rb_cARGF, "eof", argf_eof, 0);
13425 rb_define_method(rb_cARGF, "eof?", argf_eof, 0);
13426 rb_define_method(rb_cARGF, "binmode", argf_binmode_m, 0);
13427 rb_define_method(rb_cARGF, "binmode?", argf_binmode_p, 0);
13428
13429 rb_define_method(rb_cARGF, "write", argf_write, 1);
13430 rb_define_method(rb_cARGF, "print", rb_io_print, -1);
13431 rb_define_method(rb_cARGF, "putc", rb_io_putc, 1);
13432 rb_define_method(rb_cARGF, "puts", rb_io_puts, -1);
13433 rb_define_method(rb_cARGF, "printf", rb_io_printf, -1);
13434
13435 rb_define_method(rb_cARGF, "filename", argf_filename, 0);
13436 rb_define_method(rb_cARGF, "path", argf_filename, 0);
13437 rb_define_method(rb_cARGF, "file", argf_file, 0);
13438 rb_define_method(rb_cARGF, "skip", argf_skip, 0);
13439 rb_define_method(rb_cARGF, "close", argf_close_m, 0);
13440 rb_define_method(rb_cARGF, "closed?", argf_closed, 0);
13441
13442 rb_define_method(rb_cARGF, "lineno", argf_lineno, 0);
13443 rb_define_method(rb_cARGF, "lineno=", argf_set_lineno, 1);
13444
13445 rb_define_method(rb_cARGF, "inplace_mode", argf_inplace_mode_get, 0);
13446 rb_define_method(rb_cARGF, "inplace_mode=", argf_inplace_mode_set, 1);
13447
13448 rb_define_method(rb_cARGF, "external_encoding", argf_external_encoding, 0);
13449 rb_define_method(rb_cARGF, "internal_encoding", argf_internal_encoding, 0);
13450 rb_define_method(rb_cARGF, "set_encoding", argf_set_encoding, -1);
13451
13452 argf = rb_class_new_instance(0, 0, rb_cARGF);
13453
13454 rb_define_readonly_variable("$<", &argf);
13455 /*
13456 * ARGF is a stream designed for use in scripts that process files given
13457 * as command-line arguments or passed in via STDIN.
13458 *
13459 * See ARGF (the class) for more details.
13460 */
13461 rb_define_global_const("ARGF", argf);
13462
13463 rb_define_hooked_variable("$.", &argf, argf_lineno_getter, argf_lineno_setter);
13464 rb_define_hooked_variable("$FILENAME", &argf, argf_filename_getter, rb_gvar_readonly_setter);
13465 ARGF.filename = rb_str_new2("-");
13466
13467 rb_define_hooked_variable("$-i", &argf, opt_i_get, opt_i_set);
13468 rb_define_hooked_variable("$*", &argf, argf_argv_getter, rb_gvar_readonly_setter);
13469
13470 #if defined (_WIN32) || defined(__CYGWIN__)
13471 atexit(pipe_atexit);
13472 #endif
13473
13474 Init_File();
13475
13476 rb_define_method(rb_cFile, "initialize", rb_file_initialize, -1);
13477
13478 sym_mode = ID2SYM(rb_intern("mode"));
13479 sym_perm = ID2SYM(rb_intern("perm"));
13480 sym_flags = ID2SYM(rb_intern("flags"));
13481 sym_extenc = ID2SYM(rb_intern("external_encoding"));
13482 sym_intenc = ID2SYM(rb_intern("internal_encoding"));
13483 sym_encoding = ID2SYM(rb_id_encoding());
13484 sym_open_args = ID2SYM(rb_intern("open_args"));
13485 sym_textmode = ID2SYM(rb_intern("textmode"));
13486 sym_binmode = ID2SYM(rb_intern("binmode"));
13487 sym_autoclose = ID2SYM(rb_intern("autoclose"));
13488 sym_normal = ID2SYM(rb_intern("normal"));
13489 sym_sequential = ID2SYM(rb_intern("sequential"));
13490 sym_random = ID2SYM(rb_intern("random"));
13491 sym_willneed = ID2SYM(rb_intern("willneed"));
13492 sym_dontneed = ID2SYM(rb_intern("dontneed"));
13493 sym_noreuse = ID2SYM(rb_intern("noreuse"));
13494 sym_SET = ID2SYM(rb_intern("SET"));
13495 sym_CUR = ID2SYM(rb_intern("CUR"));
13496 sym_END = ID2SYM(rb_intern("END"));
13497 #ifdef SEEK_DATA
13498 sym_DATA = ID2SYM(rb_intern("DATA"));
13499 #endif
13500 #ifdef SEEK_HOLE
13501 sym_HOLE = ID2SYM(rb_intern("HOLE"));
13502 #endif
13503 sym_wait_readable = ID2SYM(rb_intern("wait_readable"));
13504 sym_wait_writable = ID2SYM(rb_intern("wait_writable"));
13505 }
13506
13507 #include "io.rbinc"
13508
13509 void
13510 Init_IO_nonblock(void)
13511 {
13512 load_io();
13513 }
MODE_BINARY
#define MODE_BINARY(a, b)
rb_eEAGAIN
VALUE rb_eEAGAIN
Definition: error.c:54
rb_mutex_synchronize
VALUE rb_mutex_synchronize(VALUE mutex, VALUE(*func)(VALUE arg), VALUE arg)
Definition: thread_sync.c:522
rb_econv_asciicompat_encoding
const char * rb_econv_asciicompat_encoding(const char *encname)
Definition: transcode.c:1768
rb_str_end_with_asciichar
int rb_str_end_with_asciichar(VALUE str, int c)
Definition: io.c:7685
flock
Definition: rb_mjit_min_header-2.7.0.h:1401
rb_thread_fd_writable
int rb_thread_fd_writable(int)
Definition: thread.c:4048
rb_io_t::writeconv_pre_ecopts
VALUE writeconv_pre_ecopts
Definition: io.h:99
NUM2IOCTLREQ
#define NUM2IOCTLREQ(num)
Definition: io.c:9574
rb_get_kwargs
int rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, VALUE *values)
Definition: class.c:1886
READ_CHAR_PENDING_COUNT
#define READ_CHAR_PENDING_COUNT(fptr)
Definition: io.c:472
foreach_arg::argc
int argc
Definition: io.c:10355
fdopen
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 *)
ISASCII
#define ISASCII(c)
Definition: ruby.h:2304
ID
unsigned long ID
Definition: ruby.h:103
rb_thread_call_without_gvl2
void * rb_thread_call_without_gvl2(void *(*func)(void *), void *data1, rb_unblock_function_t *ubf, void *data2)
Definition: thread.c:1581
rb_check_funcall
VALUE rb_check_funcall(VALUE, ID, int, const VALUE *)
Definition: vm_eval.c:505
rb_econv_prepare_options
int rb_econv_prepare_options(VALUE opthash, VALUE *ecopts, int ecflags)
Definition: transcode.c:2509
rb_define_class
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition: class.c:649
econv_source_buffer_empty
@ econv_source_buffer_empty
Definition: encoding.h:301
rb_execarg_parent_end
void rb_execarg_parent_end(VALUE execarg_obj)
Definition: process.c:2855
stat::st_size
off_t st_size
Definition: rb_mjit_min_header-2.7.0.h:2393
void
void
Definition: rb_mjit_min_header-2.7.0.h:13273
READ_CHAR_PENDING_PTR
#define READ_CHAR_PENDING_PTR(fptr)
Definition: io.c:473
rb_fd_select
int rb_fd_select(int, rb_fdset_t *, rb_fdset_t *, rb_fdset_t *, struct timeval *)
rb_method_basic_definition_p
#define rb_method_basic_definition_p(klass, mid)
Definition: rb_mjit_min_header-2.7.0.h:7900
TypedData_Make_Struct
#define TypedData_Make_Struct(klass, type, data_type, sval)
Definition: ruby.h:1244
Check_Type
#define Check_Type(v, t)
Definition: ruby.h:595
argf::binmode
int8_t binmode
Definition: io.c:213
TRUE
#define TRUE
Definition: nkf.h:175
pipe2
int pipe2(int __fildes[2], int flags)
stat
Definition: rb_mjit_min_header-2.7.0.h:2384
_exit
void _exit(int __status) __attribute__((__noreturn__))
rb_check_convert_type_with_id
VALUE rb_check_convert_type_with_id(VALUE, int, const char *, ID)
Definition: object.c:2957
RSTRING_GETMEM
#define RSTRING_GETMEM(str, ptrvar, lenvar)
Definition: ruby.h:1018
RFILE
#define RFILE(obj)
Definition: ruby.h:1276
rb_thread_check_ints
void rb_thread_check_ints(void)
Definition: thread.c:1362
rb_include_module
void rb_include_module(VALUE klass, VALUE module)
Definition: class.c:869
S_ISREG
#define S_ISREG(m)
Definition: io.c:992
rb_io_t::writeconv_initialized
int writeconv_initialized
Definition: io.h:97
foreach_arg
Definition: io.c:10354
rb_assoc_new
VALUE rb_assoc_new(VALUE car, VALUE cdr)
Definition: array.c:896
rb_str_new2
#define rb_str_new2
Definition: intern.h:903
getline_arg
Definition: stringio.c:1144
getline_arg::io
VALUE io
Definition: io.c:3349
rb_write_error_str
void rb_write_error_str(VALUE mesg)
Definition: io.c:7936
rb_enc_name
#define rb_enc_name(enc)
Definition: encoding.h:177
fwrite
size_t fwrite(const void *__restrict, size_t _size, size_t _n, FILE *)
_IOFBF
#define _IOFBF
Definition: rb_mjit_min_header-2.7.0.h:1470
LONG_MAX
#define LONG_MAX
Definition: ruby.h:220
rb_cloexec_fcntl_dupfd
int rb_cloexec_fcntl_dupfd(int fd, int minfd)
Definition: io.c:419
select_args::write
VALUE write
Definition: io.c:9208
rb_io_t::write_lock
VALUE write_lock
Definition: io.h:101
fstat
int fstat(int __fd, struct stat *__sbuf)
rb_exc_new3
#define rb_exc_new3
Definition: intern.h:293
RB_PASS_CALLED_KEYWORDS
#define RB_PASS_CALLED_KEYWORDS
Definition: ruby.h:1980
env
#define env
rb_io_ungetc
VALUE rb_io_ungetc(VALUE io, VALUE c)
Definition: io.c:4315
MAX_REALLOC_GAP
#define MAX_REALLOC_GAP
Definition: io.c:2694
copy_stream_struct::close_dst
unsigned close_dst
Definition: io.c:10765
rb_mutex_owned_p
VALUE rb_mutex_owned_p(VALUE self)
Definition: thread_sync.c:345
MORE_CHAR_SUSPENDED
#define MORE_CHAR_SUSPENDED
Definition: io.c:2559
rb_io_getbyte
VALUE rb_io_getbyte(VALUE io)
Definition: io.c:4215
rb_enc_codepoint
#define rb_enc_codepoint(p, e, enc)
Definition: encoding.h:207
rb_hash_new
VALUE rb_hash_new(void)
Definition: hash.c:1501
rb_enc_mbclen
int rb_enc_mbclen(const char *p, const char *e, rb_encoding *enc)
Definition: encoding.c:1020
close
int close(int __fildes)
rb_gc_register_mark_object
void rb_gc_register_mark_object(VALUE obj)
Definition: gc.c:7063
rb_execarg_run_options
int rb_execarg_run_options(const struct rb_execarg *e, struct rb_execarg *s, char *errmsg, size_t errmsg_buflen)
Definition: process.c:3385
path
VALUE path
Definition: rb_mjit_min_header-2.7.0.h:7351
rb_stderr_tty_p
int rb_stderr_tty_p(void)
Definition: io.c:7958
rb_define_module_under
VALUE rb_define_module_under(VALUE outer, const char *name)
Definition: class.c:797
rb_execarg_parent_start
void rb_execarg_parent_start(VALUE execarg_obj)
Definition: process.c:2816
rb_warn
void rb_warn(const char *fmt,...)
Definition: error.c:313
ENC_CODERANGE_VALID
#define ENC_CODERANGE_VALID
Definition: encoding.h:105
rb_str_buf_new
VALUE rb_str_buf_new(long)
Definition: string.c:1315
memset
void * memset(void *, int, size_t)
rb_block_given_p
int rb_block_given_p(void)
Determines if the current method is given a block.
Definition: eval.c:897
MBCLEN_NEEDMORE_LEN
#define MBCLEN_NEEDMORE_LEN(ret)
Definition: encoding.h:195
rb_warning
void rb_warning(const char *fmt,...)
Definition: error.c:334
size_t
long unsigned int size_t
Definition: rb_mjit_min_header-2.7.0.h:666
SET_BINARY_MODE
#define SET_BINARY_MODE(fptr)
Definition: io.c:660
ENOSYS
#define ENOSYS
Definition: rb_mjit_min_header-2.7.0.h:11017
rb_funcallv_kw
VALUE rb_funcallv_kw(VALUE, ID, int, const VALUE *, int)
Definition: vm_eval.c:962
io_encoding_set_args::fptr
rb_io_t * fptr
Definition: io.c:10188
rb_io_synchronized
void rb_io_synchronized(rb_io_t *fptr)
Definition: io.c:6356
rb_scan_args
#define rb_scan_args(argc, argvp, fmt,...)
Definition: rb_mjit_min_header-2.7.0.h:6372
rb_str_buf_cat_ascii
VALUE rb_str_buf_cat_ascii(VALUE, const char *)
Definition: string.c:2926
rb_io_oflags_fmode
int rb_io_oflags_fmode(int oflags)
Definition: io.c:5519
isatty
int isatty(int __fildes)
FMODE_TTY
#define FMODE_TTY
Definition: io.h:113
copy_stream_struct::dst_stat
struct stat dst_stat
Definition: io.c:10772
idTo_io
@ idTo_io
Definition: rb_mjit_min_header-2.7.0.h:8719
RB_IO_WAIT_WRITABLE
#define RB_IO_WAIT_WRITABLE
Definition: ruby.h:1931
rb_gc_force_recycle
void rb_gc_force_recycle(VALUE obj)
Definition: gc.c:7011
INT2FIX
#define INT2FIX(i)
Definition: ruby.h:263
NEED_WRITECONV
#define NEED_WRITECONV(fptr)
Definition: io.c:655
ENCINDEX_UTF_16BE
#define ENCINDEX_UTF_16BE
Definition: encindex.h:45
strchr
char * strchr(char *, char)
EINTR
#define EINTR
Definition: rb_mjit_min_header-2.7.0.h:10941
next_argv
#define next_argv()
Definition: io.c:8581
copy_stream_struct::total
off_t total
Definition: io.c:10767
rp
#define rp(obj)
Definition: internal.h:1435
copy_stream_struct::error_no
int error_no
Definition: io.c:10766
rb_file_open_str
VALUE rb_file_open_str(VALUE fname, const char *modestr)
Definition: io.c:6252
select_args::except
VALUE except
Definition: io.c:9208
rb_get_argv
VALUE rb_get_argv(void)
Definition: io.c:12889
rb_enc_uint_chr
VALUE rb_enc_uint_chr(unsigned int code, rb_encoding *enc)
Definition: numeric.c:3375
F_DUPFD_CLOEXEC
#define F_DUPFD_CLOEXEC
Definition: win32.h:609
O_CLOEXEC
#define O_CLOEXEC
Definition: dir.c:28
RSTRING_PTR
#define RSTRING_PTR(str)
Definition: ruby.h:1009
ENOTSUP
#define ENOTSUP
Definition: rb_mjit_min_header-2.7.0.h:11054
rb_str_substr
VALUE rb_str_substr(VALUE, long, long)
Definition: string.c:2584
rb_w32_write_console
long rb_w32_write_console(uintptr_t, int)
Definition: win32.c:7225
rb_io_check_io
VALUE rb_io_check_io(VALUE io)
Definition: io.c:739
NUM2LONG
#define NUM2LONG(x)
Definition: ruby.h:679
off_t
#define off_t
Definition: io.c:83
rb_attr_get
VALUE rb_attr_get(VALUE, ID)
Definition: variable.c:1084
rb_io_t::pathv
VALUE pathv
Definition: io.h:72
O_NONBLOCK
#define O_NONBLOCK
Definition: win32.h:611
rb_io_addstr
VALUE rb_io_addstr(VALUE io, VALUE str)
Definition: io.c:1843
rb_econv_str_convert
VALUE rb_econv_str_convert(rb_econv_t *ec, VALUE src, int flags)
Definition: transcode.c:1859
rb_class_new_instance_kw
VALUE rb_class_new_instance_kw(int, const VALUE *, VALUE, int)
Definition: object.c:1931
rb_fork_async_signal_safe
rb_pid_t rb_fork_async_signal_safe(int *status, int(*chfunc)(void *, char *, size_t), void *charg, VALUE fds, char *errmsg, size_t errmsg_buflen)
fileno
int fileno(FILE *)
rb_hash_aref
VALUE rb_hash_aref(VALUE hash, VALUE key)
Definition: hash.c:1964
popen
FILE * popen(const char *, const char *)
rb_utf8_encindex
int rb_utf8_encindex(void)
Definition: encoding.c:1334
RB_WAITFD_IN
#define RB_WAITFD_IN
Definition: io.h:51
rb_write_error
void rb_write_error(const char *mesg)
Definition: io.c:7930
rb_io_buffer_t
struct rb_io_buffer_t rb_io_buffer_t
Definition: io.h:64
bufread_arg
Definition: io.c:2466
rb_default_external_encoding
rb_encoding * rb_default_external_encoding(void)
Definition: encoding.c:1427
rb_gvar_readonly_setter
void rb_gvar_readonly_setter(VALUE v, ID id, VALUE *_)
Definition: variable.c:412
fsync
int fsync(int __fd)
VALUE
unsigned long VALUE
Definition: ruby.h:102
rb_obj_as_string
VALUE rb_obj_as_string(VALUE)
Definition: string.c:1440
rb_io_t::finalize
void(* finalize)(struct rb_io_t *, int)
Definition: io.h:73
rb_eArgError
VALUE rb_eArgError
Definition: error.c:923
encoding.h
ruby_verbose
#define ruby_verbose
Definition: ruby.h:1925
rb_io_get_io
VALUE rb_io_get_io(VALUE io)
Definition: io.c:733
ZALLOC
#define ZALLOC(type)
Definition: ruby.h:1666
ONIGENC_CONSTRUCT_MBCLEN_CHARFOUND
#define ONIGENC_CONSTRUCT_MBCLEN_CHARFOUND(n)
Definition: onigmo.h:345
FMODE_TRUNC
#define FMODE_TRUNC
Definition: io.h:119
getline_arg::limit
long limit
Definition: stringio.c:1146
ARGF_GENERIC_INPUT_P
#define ARGF_GENERIC_INPUT_P()
Definition: io.c:8582
RB_TYPE_P
#define RB_TYPE_P(obj, type)
Definition: ruby.h:560
rb_intern_const
#define rb_intern_const(str)
Definition: ruby.h:1879
Init_IO_nonblock
void Init_IO_nonblock(void)
Definition: io.c:13510
io_tell
#define io_tell(fptr)
Definition: io.c:862
TYPE
#define TYPE(x)
Definition: ruby.h:554
rb_thread_current
VALUE rb_thread_current(void)
Definition: thread.c:2676
rb_enc_get
rb_encoding * rb_enc_get(VALUE obj)
Definition: encoding.c:872
rb_enc_asciicompat
#define rb_enc_asciicompat(enc)
Definition: encoding.h:245
do_write_retry
#define do_write_retry(code)
Definition: io.c:1039
rb_execarg_commandline
char * rb_execarg_commandline(const struct rb_execarg *eargp, VALUE *prog)
Definition: process.c:4317
rb_io_t::wbuf
rb_io_buffer_t wbuf
Definition: io.h:75
rb_enc_precise_mbclen
int rb_enc_precise_mbclen(const char *p, const char *e, rb_encoding *enc)
Definition: encoding.c:1032
rb_gc_for_fd
int rb_gc_for_fd(int err)
Definition: io.c:953
NEED_READCONV
#define NEED_READCONV(fptr)
Definition: io.c:654
int
__inline__ int
Definition: rb_mjit_min_header-2.7.0.h:2839
rb_io_ascii8bit_binmode
VALUE rb_io_ascii8bit_binmode(VALUE io)
Definition: io.c:5380
rb_sys_fail_path
#define rb_sys_fail_path(path)
Definition: internal.h:1627
rb_bool_expected
int rb_bool_expected(VALUE, const char *)
Definition: object.c:3112
id.h
SIGNED_VALUE
#define SIGNED_VALUE
Definition: ruby.h:104
rb_to_array_type
VALUE rb_to_array_type(VALUE ary)
Definition: array.c:902
rb_define_global_function
void rb_define_global_function(const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a global function.
Definition: class.c:1787
GetWriteIO
#define GetWriteIO(io)
Definition: io.c:464
EINPROGRESS
#define EINPROGRESS
Definition: win32.h:498
binwrite_arg::fptr
rb_io_t * fptr
Definition: io.c:1317
io_internal_write_struct
Definition: io.c:1002
rb_thread_sleep
void rb_thread_sleep(int)
Definition: thread.c:1385
idGets
@ idGets
Definition: rb_mjit_min_header-2.7.0.h:8701
rb_io_pwrite
#define rb_io_pwrite
Definition: io.c:5330
io_internal_read_struct::capa
size_t capa
Definition: io.c:999
UINT2NUM
#define UINT2NUM(x)
Definition: ruby.h:1610
rb_lastline_set
void rb_lastline_set(VALUE)
Definition: vm.c:1322
rb_inspect
VALUE rb_inspect(VALUE)
Convenient wrapper of Object::inspect.
Definition: object.c:551
rb_io_set_close_on_exec
#define rb_io_set_close_on_exec
Definition: io.c:4479
READ_DATA_BUFFERED
#define READ_DATA_BUFFERED(fptr)
Definition: io.c:469
StringValue
use StringValue() instead")))
rb_io_write
VALUE rb_io_write(VALUE io, VALUE str)
Definition: io.c:1804
rb_stdin
VALUE rb_stdin
Definition: io.c:184
rb_str_dup
VALUE rb_str_dup(VALUE)
Definition: string.c:1516
F_DUPFD
#define F_DUPFD
Definition: win32.h:602
argf::argv
VALUE argv
Definition: io.c:210
rb_str_cat2
#define rb_str_cat2
Definition: intern.h:912
rb_hash_lookup2
VALUE rb_hash_lookup2(VALUE hash, VALUE key, VALUE def)
Definition: hash.c:1977
rb_check_string_type
VALUE rb_check_string_type(VALUE)
Definition: string.c:2314
rb_io_gets_internal
VALUE rb_io_gets_internal(VALUE io)
Definition: io.c:3579
SEEK_CUR
#define SEEK_CUR
Definition: io.c:866
SHUT_WR
#define SHUT_WR
copy_stream_struct::src_fd
int src_fd
Definition: io.c:10762
rb_define_readonly_variable
void rb_define_readonly_variable(const char *, const VALUE *)
Definition: variable.c:505
rb_io_check_writable
void rb_io_check_writable(rb_io_t *fptr)
Definition: io.c:923
rb_mWaitReadable
VALUE rb_mWaitReadable
Definition: io.c:174
Qundef
#define Qundef
Definition: ruby.h:470
free
#define free(x)
Definition: io.c:47
rb_define_singleton_method
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
Definition: class.c:1755
rb_io_flush_raw
VALUE rb_io_flush_raw(VALUE io, int sync)
Definition: io.c:1864
rb_write_error2
void rb_write_error2(const char *mesg, long len)
Definition: io.c:7911
rb_str_modify
void rb_str_modify(VALUE)
Definition: string.c:2114
rb_define_method
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1551
ENC_CODERANGE_SET
#define ENC_CODERANGE_SET(obj, cr)
Definition: encoding.h:110
INT2NUM
#define INT2NUM(x)
Definition: ruby.h:1609
bufread_arg::fptr
rb_io_t * fptr
Definition: io.c:2469
rb_eIOError
VALUE rb_eIOError
Definition: io.c:173
rb_econv_convert
rb_econv_result_t rb_econv_convert(rb_econv_t *ec, const unsigned char **source_buffer_ptr, const unsigned char *source_buffer_end, unsigned char **destination_buffer_ptr, unsigned char *destination_buffer_end, int flags)
Definition: transcode.c:1428
rb_ary_shift
VALUE rb_ary_shift(VALUE ary)
Definition: array.c:1294
io_internal_read_struct::nonblock
int nonblock
Definition: io.c:997
ptr
struct RIMemo * ptr
Definition: debug.c:74
READ_DATA_PENDING_PTR
#define READ_DATA_PENDING_PTR(fptr)
Definition: io.c:468
rb_io_eof
VALUE rb_io_eof(VALUE io)
Definition: io.c:2149
rb_io_enc_t
struct rb_io_enc_t rb_io_enc_t
Definition: io.h:104
rb_str_setter
rb_gvar_setter_t rb_str_setter
Definition: intern.h:828
Qfalse
#define Qfalse
Definition: ruby.h:467
ruby_sized_xfree
#define ruby_sized_xfree(ptr, size)
Definition: rb_mjit_min_header-2.7.0.h:7367
rb_hash_dup
VALUE rb_hash_dup(VALUE hash)
Definition: hash.c:1537
IO_CBUF_CAPA_MIN
#define IO_CBUF_CAPA_MIN
Definition: io.c:150
BUFSIZ
#define BUFSIZ
Definition: rb_mjit_min_header-2.7.0.h:1474
ssize_t
_ssize_t ssize_t
Definition: rb_mjit_min_header-2.7.0.h:1329
fdatasync
int fdatasync(int __fd)
FMODE_DUPLEX
#define FMODE_DUPLEX
Definition: io.h:114
FilePathValue
#define FilePathValue(v)
Definition: ruby.h:624
rb_id2str
#define rb_id2str(id)
Definition: vm_backtrace.c:30
argf::last_lineno
long last_lineno
Definition: io.c:208
dp
#define dp(v)
Definition: vm_debug.h:21
chown
int chown(const char *, int, int)
Definition: win32.c:4763
rb_io_t::fd
int fd
Definition: io.h:68
sysopen_struct::perm
mode_t perm
Definition: io.c:6007
rb_set_class_path
void rb_set_class_path(VALUE, VALUE, const char *)
Definition: variable.c:218
rb_scan_args_kw
int rb_scan_args_kw(int kw_flag, int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:2180
NULL
#define NULL
Definition: _sdbm.c:101
rb_waitpid
rb_pid_t rb_waitpid(rb_pid_t pid, int *status, int flags)
Definition: process.c:1213
sync
void sync(void)
SafeStringValue
#define SafeStringValue(v)
Definition: ruby.h:607
rb_thread_interrupted
int rb_thread_interrupted(VALUE thval)
Definition: thread.c:1379
FL_TEST
#define FL_TEST(x, f)
Definition: ruby.h:1353
rb_execarg::cmd
struct rb_execarg::@110::@112 cmd
PRIsVALUE
#define PRIsVALUE
Definition: ruby.h:166
select_args::read
VALUE read
Definition: io.c:9208
fcntl
int fcntl(int, int,...)
Definition: win32.c:4282
RBASIC_SET_CLASS
#define RBASIC_SET_CLASS(obj, cls)
Definition: internal.h:1983
rb_io_get_write_io
VALUE rb_io_get_write_io(VALUE io)
Definition: io.c:745
rb_readwrite_syserr_fail
void rb_readwrite_syserr_fail(enum rb_io_wait_readwrite writable, int n, const char *mesg)
Definition: io.c:12929
rb_enc_from_encoding
VALUE rb_enc_from_encoding(rb_encoding *encoding)
Definition: encoding.c:116
last
unsigned int last
Definition: nkf.c:4324
rb_io_t::rbuf
rb_io_buffer_t rbuf
Definition: io.h:75
rb_str_cat_conv_enc_opts
VALUE rb_str_cat_conv_enc_opts(VALUE newstr, long ofs, const char *ptr, long len, rb_encoding *from, int ecflags, VALUE ecopts)
Definition: string.c:943
rb_fatal
void rb_fatal(const char *fmt,...)
Definition: error.c:2720
FIX2LONG
#define FIX2LONG(x)
Definition: ruby.h:394
ID2SYM
#define ID2SYM(x)
Definition: ruby.h:414
error
const rb_iseq_t const char * error
Definition: rb_mjit_min_header-2.7.0.h:13506
strlen
size_t strlen(const char *)
OBJ_FREEZE
#define OBJ_FREEZE(x)
Definition: ruby.h:1377
rb_eof_error
void rb_eof_error(void)
Definition: io.c:697
rb_str_locktmp
VALUE rb_str_locktmp(VALUE)
atexit
int atexit(void(*__func)(void))
rb_find_encoding
rb_encoding * rb_find_encoding(VALUE enc)
Definition: encoding.c:252
rb_io_t::pid
rb_pid_t pid
Definition: io.h:70
rb_cFile
VALUE rb_cFile
Definition: file.c:159
FMODE_BINMODE
#define FMODE_BINMODE
Definition: io.h:111
rb_io_modestr_fmode
int rb_io_modestr_fmode(const char *modestr)
Definition: io.c:5465
rb_define_alias
void rb_define_alias(VALUE klass, const char *name1, const char *name2)
Defines an alias of a method.
Definition: class.c:1800
L
#define L(x)
Definition: asm.h:125
rb_f_p_arg
Definition: io.c:7812
rb_respond_to
int rb_respond_to(VALUE, ID)
Definition: vm_method.c:2190
RB_BLOCK_CALL_FUNC_ARGLIST
#define RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg)
Definition: ruby.h:1964
rb_protect
VALUE rb_protect(VALUE(*proc)(VALUE), VALUE data, int *pstate)
Protects a function call from potential global escapes from the function.
Definition: eval.c:1071
rb_io_check_readable
void rb_io_check_readable(rb_io_t *fptr)
Definition: io.c:899
rb_check_arity
#define rb_check_arity
Definition: intern.h:347
RUBY_FUNC_EXPORTED
#define RUBY_FUNC_EXPORTED
Definition: defines.h:391
rb_econv_check_error
void rb_econv_check_error(rb_econv_t *ec)
Definition: transcode.c:4223
ENCODING_MAXNAMELEN
#define ENCODING_MAXNAMELEN
Definition: encoding.h:64
RARRAY_LENINT
#define RARRAY_LENINT(ary)
Definition: ruby.h:1071
v
int VALUE v
Definition: rb_mjit_min_header-2.7.0.h:12332
rb_str_locktmp_ensure
VALUE rb_str_locktmp_ensure(VALUE str, VALUE(*func)(VALUE), VALUE arg)
Definition: string.c:2685
IO_WBUF_CAPA_MIN
#define IO_WBUF_CAPA_MIN
Definition: io.c:152
rb_str_capacity
size_t rb_str_capacity(VALUE str)
Definition: string.c:712
ALLOC_N
#define ALLOC_N(type, n)
Definition: ruby.h:1663
MBCLEN_INVALID_P
#define MBCLEN_INVALID_P(ret)
Definition: encoding.h:193
argf::lineno
long lineno
Definition: io.c:209
rb_str_resize
VALUE rb_str_resize(VALUE, long)
Definition: string.c:2709
rb_funcallv
#define rb_funcallv(recv, mid, argc, argv)
Definition: rb_mjit_min_header-2.7.0.h:7899
rb_cloexec_dup
int rb_cloexec_dup(int oldfd)
Definition: io.c:318
copy_stream_struct::th
VALUE th
Definition: io.c:10770
cc
const struct rb_call_cache * cc
Definition: rb_mjit_min_header-2.7.0.h:13228
rb_fdset_t
Definition: rb_mjit_min_header-2.7.0.h:5705
RUBY_TYPED_DEFAULT_FREE
#define RUBY_TYPED_DEFAULT_FREE
Definition: ruby.h:1203
rb_io_t::rb_io_enc_t::ecflags
int ecflags
Definition: io.h:88
idMesg
@ idMesg
Definition: rb_mjit_min_header-2.7.0.h:8728
rb_raise
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2669
rb_io_fdopen
VALUE rb_io_fdopen(int fd, int oflags, const char *path)
Definition: io.c:8004
argf_call_arg
Definition: io.c:12122
copy_stream_struct
Definition: io.c:10756
FMODE_SYNC
#define FMODE_SYNC
Definition: io.h:112
sysopen_struct
Definition: io.c:6004
rb_id_encoding
ID rb_id_encoding(void)
Definition: encoding.c:759
getuid
rb_uid_t getuid(void)
Definition: win32.c:2765
rb_str_tmp_frozen_acquire
VALUE rb_str_tmp_frozen_acquire(VALUE str)
Definition: string.c:1210
rb_ary_entry
VALUE rb_ary_entry(VALUE ary, long offset)
Definition: array.c:1512
rb_notimplement
void rb_notimplement(void)
Definition: error.c:2712
T_FILE
#define T_FILE
Definition: ruby.h:534
WNOHANG
#define WNOHANG
Definition: win32.h:128
ruby_set_inplace_mode
void ruby_set_inplace_mode(const char *suffix)
Definition: io.c:12857
NUM2UINT
#define NUM2UINT(x)
Definition: ruby.h:716
rb_io_puts
VALUE rb_io_puts(int argc, const VALUE *argv, VALUE out)
Definition: io.c:7747
if
if((ID)(DISPID) nameid !=nameid)
Definition: win32ole.c:357
rb_io_extract_modeenc
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:5871
EAGAIN
#define EAGAIN
Definition: rb_mjit_min_header-2.7.0.h:10948
obj
const VALUE VALUE obj
Definition: rb_mjit_min_header-2.7.0.h:5742
NUM2CHR
#define NUM2CHR(x)
Definition: ruby.h:1647
io_internal_read_struct::fd
int fd
Definition: io.c:996
rb_obj_class
VALUE rb_obj_class(VALUE)
Equivalent to Object#class in Ruby.
Definition: object.c:217
read
_ssize_t read(int __fd, void *__buf, size_t __nbyte)
rename
int rename(const char *, const char *)
rb_io_flush
VALUE rb_io_flush(VALUE io)
Definition: io.c:1903
pread
ssize_t pread(int __fd, void *__buf, size_t __nbytes, off_t __offset)
rb_fix_plus
VALUE rb_fix_plus(VALUE x, VALUE y)
Definition: numeric.c:3604
rb_fstring_cstr
#define rb_fstring_cstr(str)
Definition: rb_mjit_min_header-2.7.0.h:7718
rb_io_ioctl
#define rb_io_ioctl
Definition: io.c:9883
rb_fdopen
FILE * rb_fdopen(int fd, const char *modestr)
Definition: io.c:6053
rb_str_new4
#define rb_str_new4
Definition: intern.h:905
lseek
off_t lseek(int __fildes, off_t __offset, int __whence)
memcpy
void * memcpy(void *__restrict, const void *__restrict, size_t)
rb_io_modestr_oflags
int rb_io_modestr_oflags(const char *modestr)
Definition: io.c:5595
rb_fd_term
void rb_fd_term(rb_fdset_t *)
rb_syserr_fail
void rb_syserr_fail(int e, const char *mesg)
Definition: error.c:2781
MODE_BTXMODE
#define MODE_BTXMODE(a, b, c, d, e, f)
Definition: io.c:1462
FMODE_READABLE
#define FMODE_READABLE
Definition: io.h:108
rb_ascii8bit_encoding
rb_encoding * rb_ascii8bit_encoding(void)
Definition: encoding.c:1316
ECONV_STATEFUL_DECORATOR_MASK
#define ECONV_STATEFUL_DECORATOR_MASK
Definition: encoding.h:407
strerror
RUBY_EXTERN char * strerror(int)
Definition: strerror.c:11
io_internal_write_struct::buf
const void * buf
Definition: io.c:1004
rb_econv_open_opts
rb_econv_t * rb_econv_open_opts(const char *source_encoding, const char *destination_encoding, int ecflags, VALUE ecopts)
Definition: transcode.c:2560
argf::encs
struct rb_io_enc_t encs
Definition: io.c:212
MBCLEN_CHARFOUND_LEN
#define MBCLEN_CHARFOUND_LEN(ret)
Definition: encoding.h:192
FMODE_PREP
#define FMODE_PREP
Definition: io.c:4482
Init_IO
void Init_IO(void)
Definition: io.c:13140
VM_UNREACHABLE
#define VM_UNREACHABLE(func)
Definition: vm_core.h:57
io_internal_write_struct::fd
int fd
Definition: io.c:1003
rb_thread_execute_interrupts
void rb_thread_execute_interrupts(VALUE th)
Definition: thread.c:2284
F_GETFD
#define F_GETFD
Definition: win32.h:603
RB_SCAN_ARGS_LAST_HASH_KEYWORDS
#define RB_SCAN_ARGS_LAST_HASH_KEYWORDS
Definition: ruby.h:1905
io_encoding_set_args::v1
VALUE v1
Definition: io.c:10189
rb_encoding
const typedef OnigEncodingType rb_encoding
Definition: encoding.h:115
ALLOCV_END
#define ALLOCV_END(v)
Definition: ruby.h:1750
rb_check_frozen
#define rb_check_frozen(obj)
Definition: intern.h:319
rb_io_t::writeconv
rb_econv_t * writeconv
Definition: io.h:95
select_args
Definition: io.c:9207
rb_io_set_write_io
VALUE rb_io_set_write_io(VALUE io, VALUE w)
Definition: io.c:756
rb_io_t::readconv
rb_econv_t * readconv
Definition: io.h:92
rb_enc_left_char_head
#define rb_enc_left_char_head(s, p, e, enc)
Definition: encoding.h:222
SHUT_RD
#define SHUT_RD
rb_cloexec_pipe
int rb_cloexec_pipe(int fildes[2])
Definition: io.c:378
memmove
#define memmove(dst, src, len)
Definition: rb_mjit_min_header-2.7.0.h:2848
_IOLBF
#define _IOLBF
Definition: rb_mjit_min_header-2.7.0.h:1471
rb_output_rs
VALUE rb_output_rs
Definition: io.c:189
rb_thread_io_blocking_region
VALUE rb_thread_io_blocking_region(rb_blocking_function_t *func, void *data1, int fd)
Definition: thread.c:1595
IOWAIT_SYSCALL
#define IOWAIT_SYSCALL
Definition: io.c:10825
IS_PREP_STDIO
#define IS_PREP_STDIO(f)
Definition: io.c:4483
rb_f_p_arg::argc
int argc
Definition: io.c:7813
list_head
Definition: rb_mjit_min_header-2.7.0.h:8975
rb_thread_wait_fd
void rb_thread_wait_fd(int)
Definition: thread.c:4042
binwrite_arg::length
long length
Definition: io.c:1320
write_arg::nosync
int nosync
Definition: io.c:1326
rb_convert_type_with_id
VALUE rb_convert_type_with_id(VALUE, int, const char *, ID)
Definition: object.c:2914
MORE_CHAR_FINISHED
#define MORE_CHAR_FINISHED
Definition: io.c:2560
ALLOCV_N
#define ALLOCV_N(type, v, n)
Definition: ruby.h:1749
rb_enc_from_index
rb_encoding * rb_enc_from_index(int index)
Definition: encoding.c:609
rb_frame_this_func
ID rb_frame_this_func(void)
The original name of the current method.
Definition: eval.c:1182
ENOMEM
#define ENOMEM
Definition: rb_mjit_min_header-2.7.0.h:10949
T_FIXNUM
#define T_FIXNUM
Definition: ruby.h:535
NUM2SIZET
#define NUM2SIZET(x)
Definition: ruby.h:769
fmode
#define fmode
FMODE_TEXTMODE
#define FMODE_TEXTMODE
Definition: io.h:120
rb_io_memsize
RUBY_FUNC_EXPORTED size_t rb_io_memsize(const rb_io_t *fptr)
Definition: io.c:4760
S_ISSOCK
#define S_ISSOCK(m)
Definition: rb_mjit_min_header-2.7.0.h:2453
EWOULDBLOCK
#define EWOULDBLOCK
Definition: io.c:141
argf
Definition: io.c:206
i
uint32_t i
Definition: rb_mjit_min_header-2.7.0.h:5464
rb_execarg_new
VALUE rb_execarg_new(int argc, const VALUE *argv, int accept_shell, int allow_exc_opt)
Definition: process.c:2633
RB_WAITFD_OUT
#define RB_WAITFD_OUT
Definition: io.h:53
rb_io_extract_encoding_option
int rb_io_extract_encoding_option(VALUE opt, rb_encoding **enc_p, rb_encoding **enc2_p, int *fmode_p)
Definition: io.c:5744
rb_io_t::cbuf
rb_io_buffer_t cbuf
Definition: io.h:93
rb_jump_tag
void rb_jump_tag(int tag)
Continues the exception caught by rb_protect() and rb_eval_string_protect().
Definition: eval.c:883
rb_file_open
VALUE rb_file_open(const char *fname, const char *modestr)
Definition: io.c:6259
RFile
Definition: ruby.h:1134
FMODE_EXCL
#define FMODE_EXCL
Definition: io.h:118
sym
#define sym(x)
Definition: date_core.c:3716
rb_eEOFError
VALUE rb_eEOFError
Definition: io.c:172
rb_check_to_integer
VALUE rb_check_to_integer(VALUE, const char *)
Tries to convert val into Integer.
Definition: object.c:2999
argf_call_arg::argf
VALUE argf
Definition: io.c:12125
rb_io_check_byte_readable
void rb_io_check_byte_readable(rb_io_t *fptr)
Definition: io.c:890
pclose
int pclose(FILE *)
rb_pipe
int rb_pipe(int *pipes)
Definition: io.c:6369
sysopen_struct::oflags
int oflags
Definition: io.c:6006
INT_MAX
#define INT_MAX
Definition: rb_mjit_min_header-2.7.0.h:4052
ruby_strtoul
unsigned long ruby_strtoul(const char *str, char **endptr, int base)
Definition: util.c:130
long
#define long
Definition: rb_mjit_min_header-2.7.0.h:2880
ECONV_UNIVERSAL_NEWLINE_DECORATOR
#define ECONV_UNIVERSAL_NEWLINE_DECORATOR
Definition: encoding.h:402
rb_p
void rb_p(VALUE obj)
Definition: io.c:7798
econv_incomplete_input
@ econv_incomplete_input
Definition: encoding.h:304
rb_hash_lookup
VALUE rb_hash_lookup(VALUE hash, VALUE key)
Definition: hash.c:1990
FOREACH_ARGF
#define FOREACH_ARGF()
Definition: io.c:12389
ECONV_NEWLINE_DECORATOR_READ_MASK
#define ECONV_NEWLINE_DECORATOR_READ_MASK
Definition: encoding.h:400
rb_ary_push
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:1195
rb_execarg_get
struct rb_execarg * rb_execarg_get(VALUE execarg_obj)
Definition: process.c:2608
rb_io_fptr_finalize_internal
void rb_io_fptr_finalize_internal(void *ptr)
Definition: io.c:4730
rb_io_printf
VALUE rb_io_printf(int argc, const VALUE *argv, VALUE out)
Definition: io.c:7505
SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2
#define SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags)
Definition: io.c:662
FMODE_SETENC_BY_BOM
#define FMODE_SETENC_BY_BOM
Definition: io.h:122
rb_cloexec_dup2
int rb_cloexec_dup2(int oldfd, int newfd)
Definition: io.c:325
cnt
rb_atomic_t cnt[RUBY_NSIG]
Definition: signal.c:503
rb_econv_binmode
void rb_econv_binmode(rb_econv_t *ec)
Definition: transcode.c:1924
rb_obj_freeze
VALUE rb_obj_freeze(VALUE)
Make the object unmodifiable.
Definition: object.c:1080
io_seek
#define io_seek(fptr, ofs, whence)
Definition: io.c:861
list_empty
#define list_empty(h)
Definition: rb_mjit_min_header-2.7.0.h:9030
rb_enc_mbminlen
#define rb_enc_mbminlen(enc)
Definition: encoding.h:180
term
const char term
Definition: id.c:37
vm_core.h
stderr
#define stderr
Definition: rb_mjit_min_header-2.7.0.h:1485
RUBY_UBF_IO
#define RUBY_UBF_IO
Definition: intern.h:945
io_internal_read_struct
Definition: io.c:995
econv_invalid_byte_sequence
@ econv_invalid_byte_sequence
Definition: encoding.h:298
SSIZE_MAX
#define SSIZE_MAX
Definition: ruby.h:323
rb_sys_fail
void rb_sys_fail(const char *mesg)
Definition: error.c:2793
rb_eTypeError
VALUE rb_eTypeError
Definition: error.c:922
rb_ary_concat
VALUE rb_ary_concat(VALUE x, VALUE y)
Definition: array.c:4069
rb_econv_putbackable
int rb_econv_putbackable(rb_econv_t *ec)
Definition: transcode.c:1724
argf::current_file
VALUE current_file
Definition: io.c:207
rb_stderr
VALUE rb_stderr
Definition: io.c:184
rb_io_t
struct rb_io_t rb_io_t
rb_update_max_fd
void rb_update_max_fd(int fd)
Definition: io.c:218
rb_io_read_check
void rb_io_read_check(rb_io_t *fptr)
Definition: io.c:944
ALLOC
#define ALLOC(type)
Definition: ruby.h:1664
rb_time_interval
struct timeval rb_time_interval(VALUE num)
Definition: time.c:2669
S_IFMT
#define S_IFMT
Definition: rb_mjit_min_header-2.7.0.h:2424
rb_intern
#define rb_intern(str)
ENFILE
#define ENFILE
Definition: rb_mjit_min_header-2.7.0.h:10960
rb_f_sprintf
VALUE rb_f_sprintf(int, const VALUE *)
Definition: sprintf.c:198
rb_maygvl_fd_fix_cloexec
void rb_maygvl_fd_fix_cloexec(int fd)
Definition: io.c:245
rb_eRuntimeError
VALUE rb_eRuntimeError
Definition: error.c:920
rb_thread_call_without_gvl
void * rb_thread_call_without_gvl(void *(*func)(void *), void *data1, rb_unblock_function_t *ubf, void *data2)
rb_thread_fd_select
int rb_thread_fd_select(int, rb_fdset_t *, rb_fdset_t *, rb_fdset_t *, struct timeval *)
Definition: thread.c:4067
rb_execarg::envp_str
VALUE envp_str
Definition: internal.h:2032
RETURN_ENUMERATOR
#define RETURN_ENUMERATOR(obj, argc, argv)
Definition: intern.h:279
ECONV_AFTER_OUTPUT
#define ECONV_AFTER_OUTPUT
Definition: encoding.h:416
RARRAY_AREF
#define RARRAY_AREF(a, i)
Definition: ruby.h:1101
STRNCASECMP
#define STRNCASECMP(s1, s2, n)
Definition: ruby.h:2324
write_arg::io
VALUE io
Definition: io.c:1324
rb_uninterruptible
VALUE rb_uninterruptible(VALUE(*b_proc)(VALUE), VALUE data)
Definition: thread.c:5554
copy_stream_struct::src
VALUE src
Definition: io.c:10757
FMODE_READWRITE
#define FMODE_READWRITE
Definition: io.h:110
size
int size
Definition: encoding.c:58
EBADF
#define EBADF
Definition: rb_mjit_min_header-2.7.0.h:10946
rb_str_set_len
void rb_str_set_len(VALUE, long)
Definition: string.c:2692
FALSE
#define FALSE
Definition: nkf.h:174
rb_f_p_arg::argv
VALUE * argv
Definition: io.c:7814
argf::init_p
int8_t init_p
Definition: io.c:213
FIXNUM_P
#define FIXNUM_P(f)
Definition: ruby.h:396
ENCINDEX_UTF_32LE
#define ENCINDEX_UTF_32LE
Definition: encindex.h:48
ECONV_NEWLINE_DECORATOR_MASK
#define ECONV_NEWLINE_DECORATOR_MASK
Definition: encoding.h:399
rb_io_set_nonblock
void rb_io_set_nonblock(rb_io_t *fptr)
Definition: io.c:2782
rb_gc
void rb_gc(void)
Definition: gc.c:8679
rb_io_check_initialized
void rb_io_check_initialized(rb_io_t *fptr)
Definition: io.c:710
SEEK_END
#define SEEK_END
Definition: io.c:867
rb_eEWOULDBLOCK
VALUE rb_eEWOULDBLOCK
Definition: error.c:55
rb_to_int
VALUE rb_to_int(VALUE)
Converts val into Integer.
Definition: object.c:3021
chmod
int chmod(const char *__path, mode_t __mode)
O_ACCMODE
#define O_ACCMODE
Definition: io.c:125
READ_DATA_PENDING
#define READ_DATA_PENDING(fptr)
Definition: io.c:466
IOV_MAX
#define IOV_MAX
Definition: rb_mjit_min_header-2.7.0.h:4089
rb_int_modulo
VALUE rb_int_modulo(VALUE x, VALUE y)
Definition: numeric.c:3886
iovec::iov_base
void * iov_base
Definition: win32.h:226
PIDT2NUM
#define PIDT2NUM(v)
Definition: ruby.h:354
MBCLEN_NEEDMORE_P
#define MBCLEN_NEEDMORE_P(ret)
Definition: encoding.h:194
rb_rs
VALUE rb_rs
Definition: io.c:188
list
struct rb_encoding_entry * list
Definition: encoding.c:56
SET_BINARY_MODE_WITH_SEEK_CUR
#define SET_BINARY_MODE_WITH_SEEK_CUR(fptr)
Definition: io.c:663
rb_check_to_int
VALUE rb_check_to_int(VALUE)
Tries to convert val into Integer.
Definition: object.c:3036
rb_execarg_extract_options
VALUE rb_execarg_extract_options(VALUE execarg_obj, VALUE opthash)
Definition: process.c:2279
MEMZERO
#define MEMZERO(p, type, n)
Definition: ruby.h:1752
READ_CHECK
#define READ_CHECK(fptr)
Definition: io.c:482
rb_output_fs
VALUE rb_output_fs
Definition: io.c:187
rb_str_new_frozen
VALUE rb_str_new_frozen(VALUE)
Definition: string.c:1203
argf::next_p
int8_t next_p
Definition: io.c:213
rb_econv_putback
void rb_econv_putback(rb_econv_t *ec, unsigned char *p, int n)
Definition: transcode.c:1735
bufread_arg::len
long len
Definition: io.c:2468
stat::st_mode
mode_t st_mode
Definition: rb_mjit_min_header-2.7.0.h:2388
rb_execarg::use_shell
unsigned use_shell
Definition: internal.h:2035
memcmp
int memcmp(const void *s1, const void *s2, size_t len)
Definition: memcmp.c:7
rb_str_new_cstr
#define rb_str_new_cstr(str)
Definition: rb_mjit_min_header-2.7.0.h:6117
_IONBF
#define _IONBF
Definition: rb_mjit_min_header-2.7.0.h:1472
FD_CLOEXEC
#define FD_CLOEXEC
Definition: win32.h:610
ECONV_NEWLINE_DECORATOR_WRITE_MASK
#define ECONV_NEWLINE_DECORATOR_WRITE_MASK
Definition: encoding.h:401
READ_DATA_PENDING_COUNT
#define READ_DATA_PENDING_COUNT(fptr)
Definition: io.c:467
rb_error_arity
MJIT_STATIC void rb_error_arity(int argc, int min, int max)
Definition: vm_insnhelper.c:387
rb_define_variable
void rb_define_variable(const char *, VALUE *)
Definition: variable.c:499
foreach_arg::argv
VALUE * argv
Definition: io.c:10356
rb_default_rs
VALUE rb_default_rs
Definition: io.c:190
rb_default_internal_encoding
rb_encoding * rb_default_internal_encoding(void)
Definition: encoding.c:1512
rb_notify_fd_close
int rb_notify_fd_close(int fd, struct list_head *)
Definition: thread.c:2364
rb_obj_dup
VALUE rb_obj_dup(VALUE)
Equivalent to Object#dup in Ruby.
Definition: object.c:420
ECONV_ERROR_HANDLER_MASK
#define ECONV_ERROR_HANDLER_MASK
Definition: encoding.h:392
rb_io_close
VALUE rb_io_close(VALUE io)
Definition: io.c:4820
convconfig_t
struct rb_io_enc_t convconfig_t
Definition: io.c:5812
CONST_ID
#define CONST_ID(var, str)
Definition: ruby.h:1841
io_encoding_set_args::opt
VALUE opt
Definition: io.c:10191
EINVAL
#define EINVAL
Definition: rb_mjit_min_header-2.7.0.h:10959
ENCINDEX_UTF_16LE
#define ENCINDEX_UTF_16LE
Definition: encindex.h:46
StringValueCStr
#define StringValueCStr(v)
Definition: ruby.h:604
O_BINARY
#define O_BINARY
Definition: _sdbm.c:87
rb_f_syscall
#define rb_f_syscall
Definition: io.c:10107
ENC_CODERANGE_BROKEN
#define ENC_CODERANGE_BROKEN
Definition: encoding.h:106
rb_check_array_type
VALUE rb_check_array_type(VALUE ary)
Definition: array.c:909
rb_econv_close
void rb_econv_close(rb_econv_t *ec)
Definition: transcode.c:1684
write_arg::str
VALUE str
Definition: io.c:1325
rb_yield_values2
VALUE rb_yield_values2(int n, const VALUE *argv)
Definition: vm_eval.c:1271
copy_stream_struct::notimp
const char * notimp
Definition: io.c:10769
rb_to_encoding_index
int rb_to_encoding_index(VALUE enc)
Definition: encoding.c:197
EPERM
#define EPERM
Definition: _sdbm.c:92
EOF
#define EOF
Definition: vsnprintf.c:203
foreach_arg::io
VALUE io
Definition: io.c:10357
RARRAY_CONST_PTR
#define RARRAY_CONST_PTR(a)
Definition: ruby.h:1072
rb_lastline_get
VALUE rb_lastline_get(void)
Definition: vm.c:1316
rb_close_before_exec
void rb_close_before_exec(int lowfd, int maxhint, VALUE noclose_fds)
NUM2MODET
#define NUM2MODET(v)
Definition: ruby.h:372
rb_eNotImpError
VALUE rb_eNotImpError
Definition: error.c:932
fchown
int fchown(int __fildes, uid_t __owner, gid_t __group)
fchmod
int fchmod(int fd, int mode)
Definition: win32.c:7638
CLASS_OF
#define CLASS_OF(v)
Definition: ruby.h:484
rb_io_wait_readable
int rb_io_wait_readable(int f)
Definition: io.c:1204
src
__inline__ const void *__restrict src
Definition: rb_mjit_min_header-2.7.0.h:2836
rb_obj_method_arity
int rb_obj_method_arity(VALUE, ID)
Definition: proc.c:2640
PRI_OFFT_PREFIX
#define PRI_OFFT_PREFIX
Definition: rb_mjit_min_header-2.7.0.h:145
rb_io_t::writeconv_asciicompat
VALUE writeconv_asciicompat
Definition: io.h:96
strcmp
int strcmp(const char *, const char *)
setvbuf
int setvbuf(FILE *__restrict, char *__restrict, int, size_t)
rb_w32_get_osfhandle
SOCKET rb_w32_get_osfhandle(int)
Definition: win32.c:1078
rb_class_new
VALUE rb_class_new(VALUE super)
Creates a new class.
Definition: class.c:241
copy_stream_struct::src_stat
struct stat src_stat
Definition: io.c:10771
dup2
RUBY_EXTERN int dup2(int, int)
Definition: dup2.c:27
MBCLEN_CHARFOUND_P
#define MBCLEN_CHARFOUND_P(ret)
Definition: encoding.h:191
rb_io_wait_readwrite
rb_io_wait_readwrite
Definition: ruby.h:1929
rb_thread_schedule
void rb_thread_schedule(void)
Definition: thread.c:1408
RARRAY_LEN
#define RARRAY_LEN(a)
Definition: ruby.h:1070
ioctl
int ioctl(int, int,...)
Definition: win32.c:2811
no_exception_p
#define no_exception_p(opts)
Definition: io.c:2803
rb_io_t::lineno
int lineno
Definition: io.h:71
Init_File
void Init_File(void)
Definition: file.c:6435
char
#define char
Definition: rb_mjit_min_header-2.7.0.h:2876
rb_ary_new4
#define rb_ary_new4
Definition: intern.h:105
rb_check_hash_type
VALUE rb_check_hash_type(VALUE hash)
Definition: hash.c:1825
rb_cObject
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:2010
iovec
Definition: win32.h:225
bufread_arg::str_ptr
char * str_ptr
Definition: io.c:2467
rb_ary_new2
#define rb_ary_new2
Definition: intern.h:103
n
const char size_t n
Definition: rb_mjit_min_header-2.7.0.h:5456
buf
unsigned char buf[MIME_BUF_SIZE]
Definition: nkf.c:4322
rb_exc_raise
void rb_exc_raise(VALUE mesg)
Raises an exception in the current thread.
Definition: eval.c:667
rb_io_bufwrite
ssize_t rb_io_bufwrite(VALUE io, const void *buf, size_t size)
Definition: io.c:1549
T_BIGNUM
#define T_BIGNUM
Definition: ruby.h:533
rb_syserr_fail_path
#define rb_syserr_fail_path(err, path)
Definition: internal.h:1628
rb_funcall
#define rb_funcall(recv, mid, argc,...)
Definition: rb_mjit_min_header-2.7.0.h:6585
rb_stdout
VALUE rb_stdout
Definition: io.c:184
rb_thread_atfork
void rb_thread_atfork(void)
Definition: thread.c:4548
IO_RBUF_CAPA_FOR
#define IO_RBUF_CAPA_FOR(fptr)
Definition: io.c:151
seek_arg
Definition: io.c:10506
rb_str_append
VALUE rb_str_append(VALUE, VALUE)
Definition: string.c:2965
F_SETFD
#define F_SETFD
Definition: win32.h:604
rb_enc_str_coderange
int rb_enc_str_coderange(VALUE)
Definition: string.c:657
rb_bug
void rb_bug(const char *fmt,...)
Definition: error.c:634
dup3
int dup3(int __fildes, int __fildes2, int flags)
rb_io_t::rb_io_enc_t::ecopts
VALUE ecopts
Definition: io.h:89
getline_arg::chomp
unsigned int chomp
Definition: stringio.c:1147
internal.h
OBJ_INIT_COPY
#define OBJ_INIT_COPY(obj, orig)
Definition: intern.h:331
rb_to_encoding
rb_encoding * rb_to_encoding(VALUE enc)
Definition: encoding.c:245
T_ARRAY
#define T_ARRAY
Definition: ruby.h:530
arg
VALUE arg
Definition: rb_mjit_min_header-2.7.0.h:5601
select_args::timeout
struct timeval * timeout
Definition: io.c:9209
rb_mKernel
RUBY_EXTERN VALUE rb_mKernel
Definition: ruby.h:1998
finish_writeconv_arg::noalloc
int noalloc
Definition: io.c:4551
argv
char ** argv
Definition: ruby.c:223
f
#define f
io_internal_read_struct::buf
void * buf
Definition: io.c:998
F_SETFL
#define F_SETFL
Definition: win32.h:608
rb_io_t::mode
int mode
Definition: io.h:69
binwrite_arg
Definition: io.c:1316
STATIC_ASSERT
#define STATIC_ASSERT(name, expr)
Definition: internal.h:230
rb_define_global_const
void rb_define_global_const(const char *, VALUE)
Definition: variable.c:2892
stdout
#define stdout
Definition: rb_mjit_min_header-2.7.0.h:1484
iovec::iov_len
size_t iov_len
Definition: win32.h:227
rb_io_taint_check
VALUE rb_io_taint_check(VALUE io)
Definition: io.c:703
UNREACHABLE
#define UNREACHABLE
Definition: ruby.h:63
ENCODING_GET
#define ENCODING_GET(obj)
Definition: encoding.h:62
pipe
int pipe(int __fildes[2])
rb_warn_deprecated
void rb_warn_deprecated(const char *fmt, const char *suggest,...)
Definition: error.c:364
rb_sprintf
VALUE rb_sprintf(const char *format,...)
Definition: sprintf.c:1197
FIX2UINT
#define FIX2UINT(x)
Definition: ruby.h:718
ioctl_arg
#define ioctl_arg
Definition: wait.c:32
rb_execarg_setenv
void rb_execarg_setenv(VALUE execarg_obj, VALUE env)
Definition: process.c:2646
klass
VALUE klass
Definition: rb_mjit_min_header-2.7.0.h:13254
FMODE_APPEND
#define FMODE_APPEND
Definition: io.h:115
rb_execarg::sh
struct rb_execarg::@110::@111 sh
argf_call_arg::argc
int argc
Definition: io.c:12123
rb_io_read_pending
int rb_io_read_pending(rb_io_t *fptr)
Definition: io.c:935
strrchr
char * strrchr(const char *, const char)
T_NIL
#define T_NIL
Definition: ruby.h:522
timeval
Definition: missing.h:53
rb_freopen
int rb_freopen(VALUE fname, const char *mode, FILE *file)
Definition: file.c:693
argf_call_arg::argv
VALUE * argv
Definition: io.c:12124
rb_obj_alloc
VALUE rb_obj_alloc(VALUE)
Allocates an instance of klass.
Definition: object.c:1895
str
char str[HTML_ESCAPE_MAX_LEN+1]
Definition: escape.c:18
rb_execarg
Definition: internal.h:2019
rb_enc_find_index
int rb_enc_find_index(const char *name)
Definition: encoding.c:693
rb_usascii_str_new
#define rb_usascii_str_new(str, len)
Definition: rb_mjit_min_header-2.7.0.h:6118
rb_io_t::stdio_file
FILE * stdio_file
Definition: io.h:67
rb_fd_init
void rb_fd_init(rb_fdset_t *)
io_encoding_set_args::v2
VALUE v2
Definition: io.c:10190
binwrite_arg::str
VALUE str
Definition: io.c:1318
rb_readwrite_sys_fail
void rb_readwrite_sys_fail(enum rb_io_wait_readwrite writable, const char *mesg)
Definition: io.c:12923
RUBY_TYPED_FREE_IMMEDIATELY
#define RUBY_TYPED_FREE_IMMEDIATELY
Definition: ruby.h:1207
rb_fd_fix_cloexec
void rb_fd_fix_cloexec(int fd)
Definition: io.c:268
rb_last_status_clear
void rb_last_status_clear(void)
Definition: process.c:554
PREP_STDIO_NAME
#define PREP_STDIO_NAME(f)
Definition: io.c:4484
ARGVSTR2ARGV
#define ARGVSTR2ARGV(argv_str)
Definition: internal.h:2069
rb_w32_set_nonblock
int rb_w32_set_nonblock(int)
Definition: win32.c:4390
ARGF_FORWARD
#define ARGF_FORWARD(argc, argv)
Definition: io.c:8584
ENC_CODERANGE_7BIT
#define ENC_CODERANGE_7BIT
Definition: encoding.h:104
rb_stdio_set_default_encoding
void rb_stdio_set_default_encoding(void)
Definition: io.c:11758
rb_wait_for_single_fd
int rb_wait_for_single_fd(int fd, int events, struct timeval *tv)
Definition: thread.c:4276
rb_enc_ascget
int rb_enc_ascget(const char *p, const char *e, int *len, rb_encoding *enc)
Definition: encoding.c:1044
econv_finished
@ econv_finished
Definition: encoding.h:302
rb_io_sync
#define rb_io_sync
Definition: io.c:2253
rb_hash_aset
VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val)
Definition: hash.c:2779
FMODE_CREATE
#define FMODE_CREATE
Definition: io.h:116
rb_w32_fd_is_text
char rb_w32_fd_is_text(int)
Definition: win32.c:7756
rb_str_encode_ospath
VALUE rb_str_encode_ospath(VALUE path)
Definition: file.c:236
ruby::backward::cxxanyargs::rb_block_call
VALUE rb_block_call(VALUE q, ID w, int e, const VALUE *r, type *t, VALUE y)
Call a method with a block.
Definition: cxxanyargs.hpp:178
rb_io_fptr_finalize
#define rb_io_fptr_finalize(fptr)
Definition: io.c:4757
NIL_P
#define NIL_P(v)
Definition: ruby.h:482
argf_of
#define argf_of(obj)
Definition: io.c:461
rb_str_modify_expand
void rb_str_modify_expand(VALUE, long)
Definition: string.c:2122
io.h
rb_str_tmp_frozen_release
void rb_str_tmp_frozen_release(VALUE str, VALUE tmp)
Definition: string.c:1217
argc
int argc
Definition: ruby.c:222
rb_io_gets
VALUE rb_io_gets(VALUE io)
Definition: io.c:3573
st
enum ruby_tag_type st
Definition: rb_mjit_min_header-2.7.0.h:11111
rb_enc_warn
void rb_enc_warn(rb_encoding *enc, const char *fmt,...)
Definition: error.c:323
rb_funcall3
#define rb_funcall3
Definition: ruby.h:1896
rb_exec_recursive
VALUE rb_exec_recursive(VALUE(*)(VALUE, VALUE, int), VALUE, VALUE)
Definition: thread.c:5075
rb_io_fsync
#define rb_io_fsync
Definition: io.c:2252
rb_sys_fail_str
void rb_sys_fail_str(VALUE mesg)
Definition: error.c:2799
argf::inplace
VALUE inplace
Definition: io.c:211
econv_undefined_conversion
@ econv_undefined_conversion
Definition: encoding.h:299
rb_fd_isset
int rb_fd_isset(int, const rb_fdset_t *)
rb_define_const
void rb_define_const(VALUE, const char *, VALUE)
Definition: variable.c:2880
fclose
int fclose(FILE *)
recur
#define recur(fmt)
Definition: date_strptime.c:152
ioctl_req_t
int ioctl_req_t
Definition: io.c:9573
rb_eSystemCallError
VALUE rb_eSystemCallError
Definition: error.c:941
err
int err
Definition: win32.c:135
freopen
FILE * freopen(const char *__restrict, const char *__restrict, FILE *__restrict)
seek_arg::mode
int mode
Definition: io.c:10509
rb_thread_to_be_killed
int rb_thread_to_be_killed(VALUE thread)
Definition: thread.c:2472
rb_mWaitWritable
VALUE rb_mWaitWritable
Definition: io.c:175
encindex.h
KEEPGVL
#define KEEPGVL
Definition: io.c:4775
rb_io_make_open_file
rb_io_t * rb_io_make_open_file(VALUE obj)
Definition: io.c:8080
rb_execarg_addopt
int rb_execarg_addopt(VALUE execarg_obj, VALUE key, VALUE val)
Definition: process.c:2013
NOFILE
#define NOFILE
Definition: io.c:97
shutdown
#define shutdown(a, b)
Definition: io.c:667
rb_data_type_struct
Definition: ruby.h:1148
rb_io_fcntl
#define rb_io_fcntl
Definition: io.c:9977
MakeOpenFile
#define MakeOpenFile(obj, fp)
Definition: io.h:129
rb_execarg::invoke
union rb_execarg::@110 invoke
rb_gets
VALUE rb_gets(void)
Definition: io.c:8902
GetOpenFile
#define GetOpenFile(obj, fp)
Definition: io.h:127
rb_str_unlocktmp
VALUE rb_str_unlocktmp(VALUE)
Definition: string.c:2675
SEEK_SET
#define SEEK_SET
Definition: io.c:865
io_encoding_set_args
Definition: io.c:10187
econv_destination_buffer_full
@ econv_destination_buffer_full
Definition: encoding.h:300
NEED_NEWLINE_DECORATOR_ON_WRITE
#define NEED_NEWLINE_DECORATOR_ON_WRITE(fptr)
Definition: io.c:507
rb_str_new
#define rb_str_new(str, len)
Definition: rb_mjit_min_header-2.7.0.h:6116
rb_io_wait_writable
int rb_io_wait_writable(int f)
Definition: io.c:1228
int8_t
__int8_t int8_t
Definition: rb_mjit_min_header-2.7.0.h:1165
S_IFSOCK
#define S_IFSOCK
Definition: rb_mjit_min_header-2.7.0.h:2430
rb_gc_mark
void rb_gc_mark(VALUE ptr)
Definition: gc.c:5212
write_arg
Definition: io.c:1323
rb_io_t::rb_io_enc_t::enc
rb_encoding * enc
Definition: io.h:86
_
#define _(args)
Definition: dln.h:28
pwrite
ssize_t pwrite(int __fd, const void *__buf, size_t __nbytes, off_t __offset)
rb_iter_break_value
void rb_iter_break_value(VALUE val)
Definition: vm.c:1552
count
int count
Definition: encoding.c:57
Qtrue
#define Qtrue
Definition: ruby.h:468
rb_str_catf
VALUE rb_str_catf(VALUE str, const char *format,...)
Definition: sprintf.c:1237
errno
int errno
READ_CHAR_PENDING
#define READ_CHAR_PENDING(fptr)
Definition: io.c:471
NUM2OFFT
#define NUM2OFFT(x)
Definition: ruby.h:761
rb_rescue2
VALUE rb_rescue2(VALUE(*b_proc)(VALUE), VALUE data1, VALUE(*r_proc)(VALUE, VALUE), VALUE data2,...)
An equivalent of rescue clause.
Definition: eval.c:961
NEED_NEWLINE_DECORATOR_ON_READ
#define NEED_NEWLINE_DECORATOR_ON_READ(fptr)
Definition: io.c:506
rb_class_name
VALUE rb_class_name(VALUE)
Definition: variable.c:274
utf_prefix_len
@ utf_prefix_len
Definition: io.c:5456
FMODE_WRITABLE
#define FMODE_WRITABLE
Definition: io.h:109
len
uint8_t len
Definition: escape.c:17
RB_IO_WAIT_READABLE
#define RB_IO_WAIT_READABLE
Definition: ruby.h:1930
SYMBOL_P
#define SYMBOL_P(x)
Definition: ruby.h:413
stdin
#define stdin
Definition: rb_mjit_min_header-2.7.0.h:1483
rb_last_status_set
void rb_last_status_set(int status, rb_pid_t pid)
Definition: process.c:545
intptr_t
int intptr_t
Definition: win32.h:90
rb_eEINPROGRESS
VALUE rb_eEINPROGRESS
Definition: error.c:56
rb_io_check_char_readable
void rb_io_check_char_readable(rb_io_t *fptr)
Definition: io.c:871
rb_enumeratorize
VALUE rb_enumeratorize(VALUE obj, VALUE meth, int argc, const VALUE *argv)
Definition: enumerator.c:516
seek_arg::offset
VALUE offset
Definition: io.c:10508
rb_io_print
VALUE rb_io_print(int argc, const VALUE *argv, VALUE out)
Definition: io.c:7576
rb_class_new_instance
VALUE rb_class_new_instance(int, const VALUE *, VALUE)
Allocates and initializes an instance of klass.
Definition: object.c:1955
MEMMOVE
#define MEMMOVE(p1, p2, type, n)
Definition: ruby.h:1754
copy_stream_struct::src_offset
off_t src_offset
Definition: io.c:10760
ruby_atomic.h
rb_mutex_allow_trap
void rb_mutex_allow_trap(VALUE self, int val)
Definition: thread_sync.c:545
rb_io_t::tied_io_for_writing
VALUE tied_io_for_writing
Definition: io.h:77
LONG2FIX
#define LONG2FIX(i)
Definition: ruby.h:265
rb_ivar_set
VALUE rb_ivar_set(VALUE, ID, VALUE)
Definition: variable.c:1300
T_STRING
#define T_STRING
Definition: ruby.h:528
DEFULT_IOCTL_NARG_LEN
#define DEFULT_IOCTL_NARG_LEN
Definition: io.c:9608
rb_atomic_t
int rb_atomic_t
Definition: ruby_atomic.h:124
FL_SINGLETON
#define FL_SINGLETON
Definition: ruby.h:1278
rb_pid_t
#define rb_pid_t
Definition: rb_mjit_min_header-2.7.0.h:99
ATOMIC_CAS
#define ATOMIC_CAS(var, oldval, newval)
Definition: ruby_atomic.h:136
rb_define_class_under
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
Definition: class.c:698
copy_stream_struct::dst_fd
int dst_fd
Definition: io.c:10763
rb_io_check_closed
void rb_io_check_closed(rb_io_t *fptr)
Definition: io.c:718
NEED_NEWLINE_DECORATOR_ON_READ_CHECK
#define NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr)
Definition: io.c:661
ESPIPE
#define ESPIPE
Definition: rb_mjit_min_header-2.7.0.h:10966
ruby::backward::cxxanyargs::rb_define_hooked_variable
void rb_define_hooked_variable(const char *q, VALUE *w, type *e, void_type *r)
Define a function-backended global variable.
Definition: cxxanyargs.hpp:106
rb_econv_memsize
size_t rb_econv_memsize(rb_econv_t *ec)
Definition: transcode.c:1702
rb_str_encode
VALUE rb_str_encode(VALUE str, VALUE to, int ecflags, VALUE ecopts)
Definition: transcode.c:2869
copy_stream_struct::close_src
unsigned close_src
Definition: io.c:10764
rb_yield
VALUE rb_yield(VALUE)
Definition: vm_eval.c:1237
RB_INTEGER_TYPE_P
#define RB_INTEGER_TYPE_P(obj)
Definition: ruby_missing.h:15
rb_ensure
VALUE rb_ensure(VALUE(*b_proc)(VALUE), VALUE data1, VALUE(*e_proc)(VALUE), VALUE data2)
An equivalent to ensure clause.
Definition: eval.c:1114
finish_writeconv_arg
Definition: io.c:4549
rb_io_pread
#define rb_io_pread
Definition: io.c:5270
rb_io_t::encs
struct rb_io_t::rb_io_enc_t encs
binwrite_arg::ptr
const char * ptr
Definition: io.c:1319
ENCINDEX_UTF_32BE
#define ENCINDEX_UTF_32BE
Definition: encindex.h:47
rb_ary_new
VALUE rb_ary_new(void)
Definition: array.c:723
NEWOBJ_OF
#define NEWOBJ_OF(obj, type, klass, flags)
Definition: ruby.h:785
ruby::backward::cxxanyargs::rb_define_virtual_variable
void rb_define_virtual_variable(const char *q, type *w, void_type *e)
Define a function-backended global variable.
Definition: cxxanyargs.hpp:59
builtin.h
NUM2INT
#define NUM2INT(x)
Definition: ruby.h:715
Qnil
#define Qnil
Definition: ruby.h:469
finish_writeconv_arg::fptr
rb_io_t * fptr
Definition: io.c:4550
select_args::fdsets
rb_fdset_t fdsets[4]
Definition: io.c:9210
rb_fstring_lit
#define rb_fstring_lit(str)
Definition: internal.h:2123
seek_arg::io
VALUE io
Definition: io.c:10507
exc
const rb_iseq_t const VALUE exc
Definition: rb_mjit_min_header-2.7.0.h:13504
rb_str_buf_cat
#define rb_str_buf_cat
Definition: intern.h:910
copy_stream_struct::dst
VALUE dst
Definition: io.c:10758
rb_exec_async_signal_safe
int rb_exec_async_signal_safe(const struct rb_execarg *e, char *errmsg, size_t errmsg_buflen)
Definition: process.c:3516
thread.h
OFFT2NUM
#define OFFT2NUM(v)
Definition: ruby.h:285
rb_mEnumerable
VALUE rb_mEnumerable
Definition: enum.c:20
mode_t
__mode_t mode_t
Definition: rb_mjit_min_header-2.7.0.h:1331
EXDEV
#define EXDEV
Definition: rb_mjit_min_header-2.7.0.h:10955
util.h
ECONV_DEFAULT_NEWLINE_DECORATOR
#define ECONV_DEFAULT_NEWLINE_DECORATOR
Definition: encoding.h:409
sysopen_struct::fname
VALUE fname
Definition: io.c:6005
rb_io_t
Definition: io.h:66
rb_str_chomp_string
VALUE rb_str_chomp_string(VALUE str, VALUE chomp)
Definition: string.c:8921
rb_eStandardError
VALUE rb_eStandardError
Definition: error.c:919
write
_ssize_t write(int __fd, const void *__buf, size_t __nbyte)
rb_fd_set
void rb_fd_set(int, rb_fdset_t *)
rb_econv_make_exception
VALUE rb_econv_make_exception(rb_econv_t *ec)
Definition: transcode.c:4217
RB_GC_GUARD
#define RB_GC_GUARD(v)
Definition: ruby.h:585
numberof
#define numberof(array)
Definition: etc.c:618
rb_reserved_fd_p
int rb_reserved_fd_p(int fd)
rb_str_coderange_scan_restartable
long rb_str_coderange_scan_restartable(const char *, const char *, rb_encoding *, int *)
Definition: string.c:567
rb_io_unbuffered
void rb_io_unbuffered(rb_io_t *fptr)
Definition: io.c:6363
rb_io_t::rb_io_enc_t::enc2
rb_encoding * enc2
Definition: io.h:87
rb_io_t::writeconv_pre_ecflags
int writeconv_pre_ecflags
Definition: io.h:98
RSTRING_LEN
#define RSTRING_LEN(str)
Definition: ruby.h:1005
rb_io_fdatasync
#define rb_io_fdatasync
Definition: io.c:2304
bom_prefix_len
@ bom_prefix_len
Definition: io.c:5455
MODE_BTMODE
#define MODE_BTMODE(a, b, c)
Definition: io.c:1459
rb_io_close_on_exec_p
#define rb_io_close_on_exec_p
Definition: io.c:4421
rb_any_to_s
VALUE rb_any_to_s(VALUE)
Default implementation of #to_s.
Definition: object.c:527
rb_io_binmode
VALUE rb_io_binmode(VALUE io)
Definition: io.c:5334
rb_mutex_new
VALUE rb_mutex_new(void)
Definition: thread_sync.c:165
DEFAULT_TEXTMODE
#define DEFAULT_TEXTMODE
Definition: io.c:653
rb_enc_str_new
VALUE rb_enc_str_new(const char *, long, rb_encoding *)
Definition: string.c:796
RUBY_PIPE_NONBLOCK_DEFAULT
#define RUBY_PIPE_NONBLOCK_DEFAULT
Definition: io.c:168
argf::filename
VALUE filename
Definition: io.c:207
rb_str_cat
VALUE rb_str_cat(VALUE, const char *, long)
Definition: string.c:2812
NEXT_ARGF_FORWARD
#define NEXT_ARGF_FORWARD(argc, argv)
Definition: io.c:8588
rb_io_stdio_file
FILE * rb_io_stdio_file(rb_io_t *fptr)
Definition: io.c:8032
rb_enc_associate
VALUE rb_enc_associate(VALUE obj, rb_encoding *enc)
Definition: encoding.c:866
copy_stream_struct::copy_length
off_t copy_length
Definition: io.c:10759
rb_define_alloc_func
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
rb_thread_fd_close
void rb_thread_fd_close(int)
Definition: thread.c:2386
RTEST
#define RTEST(v)
Definition: ruby.h:481
getline_arg::rs
VALUE rs
Definition: stringio.c:1145
ARGF
#define ARGF
Definition: io.c:462
SSIZET2NUM
#define SSIZET2NUM(v)
Definition: ruby.h:296
rb_econv_result_t
rb_econv_result_t
Definition: encoding.h:297
ECONV_PARTIAL_INPUT
#define ECONV_PARTIAL_INPUT
Definition: encoding.h:415
rb_cIO
VALUE rb_cIO
Definition: io.c:171
rb_cloexec_open
int rb_cloexec_open(const char *pathname, int flags, mode_t mode)
Definition: io.c:292
off_t
__off_t off_t
Definition: rb_mjit_min_header-2.7.0.h:1317
rb_io_ungetbyte
VALUE rb_io_ungetbyte(VALUE io, VALUE b)
Definition: io.c:4276
dup
int dup(int __fildes)
EMFILE
#define EMFILE
Definition: rb_mjit_min_header-2.7.0.h:10961
rb_mod_sys_fail_str
void rb_mod_sys_fail_str(VALUE mod, VALUE mesg)
Definition: error.c:2841
__sFILE
Definition: vsnprintf.c:169
rb_thread_call_with_gvl
RUBY_SYMBOL_EXPORT_BEGIN void * rb_thread_call_with_gvl(void *(*func)(void *), void *data1)
Definition: thread.c:1662
unlink
int unlink(const char *__path)
rb_usascii_encoding
rb_encoding * rb_usascii_encoding(void)
Definition: encoding.c:1340
rb_syserr_fail_str
void rb_syserr_fail_str(int e, VALUE mesg)
Definition: error.c:2787
RSTRING_END
#define RSTRING_END(str)
Definition: ruby.h:1013
copy_stream_struct::syserr
const char * syserr
Definition: io.c:10768
is_socket
#define is_socket(fd, path)
Definition: io.c:673
memchr
void * memchr(const void *, int, size_t)
io_internal_write_struct::capa
size_t capa
Definition: io.c:1005
dln.h
name
const char * name
Definition: nkf.c:208
rb_econv_open_exc
VALUE rb_econv_open_exc(const char *senc, const char *denc, int ecflags)
Definition: transcode.c:2018
rb_execution_context_struct
Definition: vm_core.h:843
rb_fork_ruby
rb_pid_t rb_fork_ruby(int *status)