Ruby 2.1.5p273(2014-11-13revision48405)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

io.c
Go to the documentation of this file.
1 /**********************************************************************
2
3 io.c -
4
5 $Author: nagachika $
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/ruby.h"
15 #include "ruby/io.h"
16 #include "ruby/thread.h"
17 #include "dln.h"
18 #include "internal.h"
19 #include "id.h"
20 #include <ctype.h>
21 #include <errno.h>
22 #include "ruby_atomic.h"
23
24 #define free(x) xfree(x)
25
26 #if defined(DOSISH) || defined(__CYGWIN__)
27 #include <io.h>
28 #endif
29
30 #include <sys/types.h>
31 #if defined HAVE_NET_SOCKET_H
32 # include <net/socket.h>
33 #elif defined HAVE_SYS_SOCKET_H
34 # ifndef __native_client__
35 # include <sys/socket.h>
36 # endif
37 #endif
38
39 #if defined(__BOW__) || defined(__CYGWIN__) || defined(_WIN32) || defined(__EMX__) || defined(__BEOS__) || defined(__HAIKU__)
40 # define NO_SAFE_RENAME
41 #endif
42
43 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__sun) || defined(_nec_ews)
44 # define USE_SETVBUF
45 #endif
46
47 #ifdef __QNXNTO__
48 #include "unix.h"
49 #endif
50
51 #include <sys/types.h>
52 #if defined(HAVE_SYS_IOCTL_H) && !defined(_WIN32)
53 #include <sys/ioctl.h>
54 #endif
55 #if defined(__native_client__) && defined(NACL_NEWLIB)
56 # include "nacl/ioctl.h"
57 #endif
58 #if defined(HAVE_FCNTL_H) || defined(_WIN32)
59 #include <fcntl.h>
60 #elif defined(HAVE_SYS_FCNTL_H)
61 #include <sys/fcntl.h>
62 #endif
63
64 #if !HAVE_OFF_T && !defined(off_t)
65 # define off_t long
66 #endif
67
68 #include <sys/stat.h>
69
70 /* EMX has sys/param.h, but.. */
71 #if defined(HAVE_SYS_PARAM_H) && !(defined(__EMX__) || defined(__HIUX_MPP__))
72 # include <sys/param.h>
73 #endif
74
75 #if !defined NOFILE
76 # define NOFILE 64
77 #endif
78
79 #ifdef HAVE_UNISTD_H
80 #include <unistd.h>
81 #endif
82
83 #ifdef HAVE_SYSCALL_H
84 #include <syscall.h>
85 #elif defined HAVE_SYS_SYSCALL_H
86 #include <sys/syscall.h>
87 #endif
88
89 #if defined(__BEOS__) || defined(__HAIKU__)
90 # ifndef NOFILE
91 # define NOFILE (OPEN_MAX)
92 # endif
93 #endif
94
95 #include "ruby/util.h"
96
97 #ifndef O_ACCMODE
98 #define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR)
99 #endif
100
101 #if SIZEOF_OFF_T > SIZEOF_LONG && !defined(HAVE_LONG_LONG)
102 # error off_t is bigger than long, but you have no long long...
103 #endif
104
105 #ifndef PIPE_BUF
106 # ifdef _POSIX_PIPE_BUF
107 # define PIPE_BUF _POSIX_PIPE_BUF
108 # else
109 # define PIPE_BUF 512 /* is this ok? */
110 # endif
111 #endif
112
113 #ifndef EWOULDBLOCK
114 # define EWOULDBLOCK EAGAIN
115 #endif
116
117 #if defined(HAVE___SYSCALL) && (defined(__APPLE__) || defined(__OpenBSD__))
118 /* Mac OS X and OpenBSD have __syscall but don't define it in headers */
119 off_t __syscall(quad_t number, ...);
120 #endif
121
122 #define IO_RBUF_CAPA_MIN 8192
123 #define IO_CBUF_CAPA_MIN (128*1024)
124 #define IO_RBUF_CAPA_FOR(fptr) (NEED_READCONV(fptr) ? IO_CBUF_CAPA_MIN : IO_RBUF_CAPA_MIN)
125 #define IO_WBUF_CAPA_MIN 8192
126
127 /* define system APIs */
128 #ifdef _WIN32
129 #undef open
130 #define open rb_w32_uopen
131 #endif
132
133 VALUE rb_cIO;
134 VALUE rb_eEOFError;
135 VALUE rb_eIOError;
136 VALUE rb_mWaitReadable;
137 VALUE rb_mWaitWritable;
138 extern VALUE rb_eEAGAIN;
139 extern VALUE rb_eEWOULDBLOCK;
140 extern VALUE rb_eEINPROGRESS;
141
142 static VALUE rb_eEAGAINWaitReadable;
143 static VALUE rb_eEAGAINWaitWritable;
144 static VALUE rb_eEWOULDBLOCKWaitReadable;
145 static VALUE rb_eEWOULDBLOCKWaitWritable;
146 static VALUE rb_eEINPROGRESSWaitWritable;
147 static VALUE rb_eEINPROGRESSWaitReadable;
148
149 VALUE rb_stdin, rb_stdout, rb_stderr;
150 VALUE rb_deferr; /* rescue VIM plugin */
151 static VALUE orig_stdout, orig_stderr;
152
153 VALUE rb_output_fs;
154 VALUE rb_rs;
155 VALUE rb_output_rs;
156 VALUE rb_default_rs;
157
158 static VALUE argf;
159
160 static ID id_write, id_read, id_getc, id_flush, id_readpartial, id_set_encoding;
161 static VALUE sym_mode, sym_perm, sym_extenc, sym_intenc, sym_encoding, sym_open_args;
162 static VALUE sym_textmode, sym_binmode, sym_autoclose, sym_exception;
163 static VALUE sym_SET, sym_CUR, sym_END;
164 #ifdef SEEK_DATA
165 static VALUE sym_DATA;
166 #endif
167 #ifdef SEEK_HOLE
168 static VALUE sym_HOLE;
169 #endif
170
171 struct argf {
172 VALUE filename, current_file;
173 long last_lineno; /* $. */
174 long lineno;
175 VALUE argv;
176 char *inplace;
177 struct rb_io_enc_t encs;
178 int8_t init_p, next_p, binmode;
179 };
180
181 static rb_atomic_t max_file_descriptor = NOFILE;
182 void
183 rb_update_max_fd(int fd)
184 {
185 struct stat buf;
186 rb_atomic_t afd = (rb_atomic_t)fd;
187
188 if (fstat(fd, &buf) != 0 && errno == EBADF) {
189 rb_bug("rb_update_max_fd: invalid fd (%d) given.", fd);
190 }
191
192 while (max_file_descriptor < afd) {
193 ATOMIC_CAS(max_file_descriptor, max_file_descriptor, afd);
194 }
195 }
196
197 void
198 rb_maygvl_fd_fix_cloexec(int fd)
199 {
200 /* MinGW don't have F_GETFD and FD_CLOEXEC. [ruby-core:40281] */
201 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
202 int flags, flags2, ret;
203 flags = fcntl(fd, F_GETFD); /* should not fail except EBADF. */
204 if (flags == -1) {
205 rb_bug("rb_maygvl_fd_fix_cloexec: fcntl(%d, F_GETFD) failed: %s", fd, strerror(errno));
206 }
207 if (fd <= 2)
208 flags2 = flags & ~FD_CLOEXEC; /* Clear CLOEXEC for standard file descriptors: 0, 1, 2. */
209 else
210 flags2 = flags | FD_CLOEXEC; /* Set CLOEXEC for non-standard file descriptors: 3, 4, 5, ... */
211 if (flags != flags2) {
212 ret = fcntl(fd, F_SETFD, flags2);
213 if (ret == -1) {
214 rb_bug("rb_maygvl_fd_fix_cloexec: fcntl(%d, F_SETFD, %d) failed: %s", fd, flags2, strerror(errno));
215 }
216 }
217 #endif
218 }
219
220 void
221 rb_fd_fix_cloexec(int fd)
222 {
223 rb_maygvl_fd_fix_cloexec(fd);
224 rb_update_max_fd(fd);
225 }
226
227 int
228 rb_cloexec_open(const char *pathname, int flags, mode_t mode)
229 {
230 int ret;
231 #ifdef O_CLOEXEC
232 /* O_CLOEXEC is available since Linux 2.6.23. Linux 2.6.18 silently ignore it. */
233 flags |= O_CLOEXEC;
234 #elif defined O_NOINHERIT
235 flags |= O_NOINHERIT;
236 #endif
237 ret = open(pathname, flags, mode);
238 if (ret == -1) return -1;
239 rb_maygvl_fd_fix_cloexec(ret);
240 return ret;
241 }
242
243 int
244 rb_cloexec_dup(int oldfd)
245 {
246 /* Don't allocate standard file descriptors: 0, 1, 2 */
247 return rb_cloexec_fcntl_dupfd(oldfd, 3);
248 }
249
250 int
251 rb_cloexec_dup2(int oldfd, int newfd)
252 {
253 int ret;
254
255 /* When oldfd == newfd, dup2 succeeds but dup3 fails with EINVAL.
256 * rb_cloexec_dup2 succeeds as dup2. */
257 if (oldfd == newfd) {
258 ret = newfd;
259 }
260 else {
261 #if defined(HAVE_DUP3) && defined(O_CLOEXEC)
262 static int try_dup3 = 1;
263 if (2 < newfd && try_dup3) {
264 ret = dup3(oldfd, newfd, O_CLOEXEC);
265 if (ret != -1)
266 return ret;
267 /* dup3 is available since Linux 2.6.27, glibc 2.9. */
268 if (errno == ENOSYS) {
269 try_dup3 = 0;
270 ret = dup2(oldfd, newfd);
271 }
272 }
273 else {
274 ret = dup2(oldfd, newfd);
275 }
276 #else
277 ret = dup2(oldfd, newfd);
278 #endif
279 if (ret == -1) return -1;
280 }
281 rb_maygvl_fd_fix_cloexec(ret);
282 return ret;
283 }
284
285 int
286 rb_cloexec_pipe(int fildes[2])
287 {
288 int ret;
289
290 #if defined(HAVE_PIPE2)
291 static int try_pipe2 = 1;
292 if (try_pipe2) {
293 ret = pipe2(fildes, O_CLOEXEC);
294 if (ret != -1)
295 return ret;
296 /* pipe2 is available since Linux 2.6.27, glibc 2.9. */
297 if (errno == ENOSYS) {
298 try_pipe2 = 0;
299 ret = pipe(fildes);
300 }
301 }
302 else {
303 ret = pipe(fildes);
304 }
305 #else
306 ret = pipe(fildes);
307 #endif
308 if (ret == -1) return -1;
309 #ifdef __CYGWIN__
310 if (ret == 0 && fildes[1] == -1) {
311 close(fildes[0]);
312 fildes[0] = -1;
313 errno = ENFILE;
314 return -1;
315 }
316 #endif
317 rb_maygvl_fd_fix_cloexec(fildes[0]);
318 rb_maygvl_fd_fix_cloexec(fildes[1]);
319 return ret;
320 }
321
322 int
323 rb_cloexec_fcntl_dupfd(int fd, int minfd)
324 {
325 int ret;
326
327 #if defined(HAVE_FCNTL) && defined(F_DUPFD_CLOEXEC) && defined(F_DUPFD)
328 static int try_dupfd_cloexec = 1;
329 if (try_dupfd_cloexec) {
330 ret = fcntl(fd, F_DUPFD_CLOEXEC, minfd);
331 if (ret != -1) {
332 if (ret <= 2)
333 rb_maygvl_fd_fix_cloexec(ret);
334 return ret;
335 }
336 /* F_DUPFD_CLOEXEC is available since Linux 2.6.24. Linux 2.6.18 fails with EINVAL */
337 if (errno == EINVAL) {
338 ret = fcntl(fd, F_DUPFD, minfd);
339 if (ret != -1) {
340 try_dupfd_cloexec = 0;
341 }
342 }
343 }
344 else {
345 ret = fcntl(fd, F_DUPFD, minfd);
346 }
347 #elif defined(HAVE_FCNTL) && defined(F_DUPFD)
348 ret = fcntl(fd, F_DUPFD, minfd);
349 #elif defined(HAVE_DUP)
350 ret = dup(fd);
351 if (ret != -1 && ret < minfd) {
352 const int prev_fd = ret;
353 ret = rb_cloexec_fcntl_dupfd(fd, minfd);
354 close(prev_fd);
355 }
356 return ret;
357 #else
358 # error "dup() or fcntl(F_DUPFD) must be supported."
359 #endif
360 if (ret == -1) return -1;
361 rb_maygvl_fd_fix_cloexec(ret);
362 return ret;
363 }
364
365 #define argf_of(obj) (*(struct argf *)DATA_PTR(obj))
366 #define ARGF argf_of(argf)
367
368 #ifdef _STDIO_USES_IOSTREAM /* GNU libc */
369 # ifdef _IO_fpos_t
370 # define STDIO_READ_DATA_PENDING(fp) ((fp)->_IO_read_ptr != (fp)->_IO_read_end)
371 # else
372 # define STDIO_READ_DATA_PENDING(fp) ((fp)->_gptr < (fp)->_egptr)
373 # endif
374 #elif defined(FILE_COUNT)
375 # define STDIO_READ_DATA_PENDING(fp) ((fp)->FILE_COUNT > 0)
376 #elif defined(FILE_READEND)
377 # define STDIO_READ_DATA_PENDING(fp) ((fp)->FILE_READPTR < (fp)->FILE_READEND)
378 #elif defined(__BEOS__) || defined(__HAIKU__)
379 # define STDIO_READ_DATA_PENDING(fp) ((fp)->_state._eof == 0)
380 #else
381 # define STDIO_READ_DATA_PENDING(fp) (!feof(fp))
382 #endif
383
384 #define GetWriteIO(io) rb_io_get_write_io(io)
385
386 #define READ_DATA_PENDING(fptr) ((fptr)->rbuf.len)
387 #define READ_DATA_PENDING_COUNT(fptr) ((fptr)->rbuf.len)
388 #define READ_DATA_PENDING_PTR(fptr) ((fptr)->rbuf.ptr+(fptr)->rbuf.off)
389 #define READ_DATA_BUFFERED(fptr) READ_DATA_PENDING(fptr)
390
391 #define READ_CHAR_PENDING(fptr) ((fptr)->cbuf.len)
392 #define READ_CHAR_PENDING_COUNT(fptr) ((fptr)->cbuf.len)
393 #define READ_CHAR_PENDING_PTR(fptr) ((fptr)->cbuf.ptr+(fptr)->cbuf.off)
394
395 #if defined(_WIN32)
396 #define WAIT_FD_IN_WIN32(fptr) \
397 (rb_w32_io_cancelable_p((fptr)->fd) ? 0 : rb_thread_wait_fd((fptr)->fd))
398 #else
399 #define WAIT_FD_IN_WIN32(fptr)
400 #endif
401
402 #define READ_CHECK(fptr) do {\
403 if (!READ_DATA_PENDING(fptr)) {\
404 WAIT_FD_IN_WIN32(fptr);\
405 rb_io_check_closed(fptr);\
406 }\
407 } while(0)
408
409 #ifndef S_ISSOCK
410 # ifdef _S_ISSOCK
411 # define S_ISSOCK(m) _S_ISSOCK(m)
412 # else
413 # ifdef _S_IFSOCK
414 # define S_ISSOCK(m) (((m) & S_IFMT) == _S_IFSOCK)
415 # else
416 # ifdef S_IFSOCK
417 # define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
418 # endif
419 # endif
420 # endif
421 #endif
422
423 static int io_fflush(rb_io_t *);
424 static rb_io_t *flush_before_seek(rb_io_t *fptr);
425
426 #define NEED_NEWLINE_DECORATOR_ON_READ(fptr) ((fptr)->mode & FMODE_TEXTMODE)
427 #define NEED_NEWLINE_DECORATOR_ON_WRITE(fptr) ((fptr)->mode & FMODE_TEXTMODE)
428 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
429 /* Windows */
430 # define DEFAULT_TEXTMODE FMODE_TEXTMODE
431 # define TEXTMODE_NEWLINE_DECORATOR_ON_WRITE ECONV_CRLF_NEWLINE_DECORATOR
432 /*
433 * CRLF newline is set as default newline decorator.
434 * If only CRLF newline conversion is needed, we use binary IO process
435 * with OS's text mode for IO performance improvement.
436 * If encoding conversion is needed or a user sets text mode, we use encoding
437 * conversion IO process and universal newline decorator by default.
438 */
439 #define NEED_READCONV(fptr) ((fptr)->encs.enc2 != NULL || (fptr)->encs.ecflags & ~ECONV_CRLF_NEWLINE_DECORATOR)
440 #define NEED_WRITECONV(fptr) (((fptr)->encs.enc != NULL && (fptr)->encs.enc != rb_ascii8bit_encoding()) || ((fptr)->encs.ecflags & ((ECONV_DECORATOR_MASK & ~ECONV_CRLF_NEWLINE_DECORATOR)|ECONV_STATEFUL_DECORATOR_MASK)))
441 #define SET_BINARY_MODE(fptr) setmode((fptr)->fd, O_BINARY)
442
443 #define NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr) do {\
444 if (NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {\
445 if (((fptr)->mode & FMODE_READABLE) &&\
446 !((fptr)->encs.ecflags & ECONV_NEWLINE_DECORATOR_MASK)) {\
447 setmode((fptr)->fd, O_BINARY);\
448 }\
449 else {\
450 setmode((fptr)->fd, O_TEXT);\
451 }\
452 }\
453 } while(0)
454
455 #define SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags) do {\
456 if ((enc2) && ((ecflags) & ECONV_DEFAULT_NEWLINE_DECORATOR)) {\
457 (ecflags) |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;\
458 }\
459 } while(0)
460
461 /*
462 * IO unread with taking care of removed '\r' in text mode.
463 */
464 static void
465 io_unread(rb_io_t *fptr)
466 {
467 off_t r, pos;
468 ssize_t read_size;
469 long i;
470 long newlines = 0;
471 long extra_max;
472 char *p;
473 char *buf;
474
475 rb_io_check_closed(fptr);
476 if (fptr->rbuf.len == 0 || fptr->mode & FMODE_DUPLEX) {
477 return;
478 }
479
480 errno = 0;
481 if (!rb_w32_fd_is_text(fptr->fd)) {
482 r = lseek(fptr->fd, -fptr->rbuf.len, SEEK_CUR);
483 if (r < 0 && errno) {
484 if (errno == ESPIPE)
485 fptr->mode |= FMODE_DUPLEX;
486 return;
487 }
488
489 fptr->rbuf.off = 0;
490 fptr->rbuf.len = 0;
491 return;
492 }
493
494 pos = lseek(fptr->fd, 0, SEEK_CUR);
495 if (pos < 0 && errno) {
496 if (errno == ESPIPE)
497 fptr->mode |= FMODE_DUPLEX;
498 return;
499 }
500
501 /* add extra offset for removed '\r' in rbuf */
502 extra_max = (long)(pos - fptr->rbuf.len);
503 p = fptr->rbuf.ptr + fptr->rbuf.off;
504
505 /* if the end of rbuf is '\r', rbuf doesn't have '\r' within rbuf.len */
506 if (*(fptr->rbuf.ptr + fptr->rbuf.capa - 1) == '\r') {
507 newlines++;
508 }
509
510 for (i = 0; i < fptr->rbuf.len; i++) {
511 if (*p == '\n') newlines++;
512 if (extra_max == newlines) break;
513 p++;
514 }
515
516 buf = ALLOC_N(char, fptr->rbuf.len + newlines);
517 while (newlines >= 0) {
518 r = lseek(fptr->fd, pos - fptr->rbuf.len - newlines, SEEK_SET);
519 if (newlines == 0) break;
520 if (r < 0) {
521 newlines--;
522 continue;
523 }
524 read_size = _read(fptr->fd, buf, fptr->rbuf.len + newlines);
525 if (read_size < 0) {
526 free(buf);
527 rb_sys_fail_path(fptr->pathv);
528 }
529 if (read_size == fptr->rbuf.len) {
530 lseek(fptr->fd, r, SEEK_SET);
531 break;
532 }
533 else {
534 newlines--;
535 }
536 }
537 free(buf);
538 fptr->rbuf.off = 0;
539 fptr->rbuf.len = 0;
540 return;
541 }
542
543 /*
544 * We use io_seek to back cursor position when changing mode from text to binary,
545 * but stdin and pipe cannot seek back. Stdin and pipe read should use encoding
546 * conversion for working properly with mode change.
547 *
548 * Return previous translation mode.
549 */
550 static inline int
551 set_binary_mode_with_seek_cur(rb_io_t *fptr)
552 {
553 if (!rb_w32_fd_is_text(fptr->fd)) return O_BINARY;
554
555 if (fptr->rbuf.len == 0 || fptr->mode & FMODE_DUPLEX) {
556 return setmode(fptr->fd, O_BINARY);
557 }
558 flush_before_seek(fptr);
559 return setmode(fptr->fd, O_BINARY);
560 }
561 #define SET_BINARY_MODE_WITH_SEEK_CUR(fptr) set_binary_mode_with_seek_cur(fptr)
562
563 #else
564 /* Unix */
565 # define DEFAULT_TEXTMODE 0
566 #define NEED_READCONV(fptr) ((fptr)->encs.enc2 != NULL || NEED_NEWLINE_DECORATOR_ON_READ(fptr))
567 #define NEED_WRITECONV(fptr) (((fptr)->encs.enc != NULL && (fptr)->encs.enc != rb_ascii8bit_encoding()) || NEED_NEWLINE_DECORATOR_ON_WRITE(fptr) || ((fptr)->encs.ecflags & (ECONV_DECORATOR_MASK|ECONV_STATEFUL_DECORATOR_MASK)))
568 #define SET_BINARY_MODE(fptr) (void)(fptr)
569 #define NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr) (void)(fptr)
570 #define SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags) ((void)(enc2), (void)(ecflags))
571 #define SET_BINARY_MODE_WITH_SEEK_CUR(fptr) (void)(fptr)
572 #endif
573
574 #if !defined HAVE_SHUTDOWN && !defined shutdown
575 #define shutdown(a,b) 0
576 #endif
577
578 #if defined(_WIN32)
579 #define is_socket(fd, path) rb_w32_is_socket(fd)
580 #elif !defined(S_ISSOCK)
581 #define is_socket(fd, path) 0
582 #else
583 static int
584 is_socket(int fd, VALUE path)
585 {
586 struct stat sbuf;
587 if (fstat(fd, &sbuf) < 0)
588 rb_sys_fail_path(path);
589 return S_ISSOCK(sbuf.st_mode);
590 }
591 #endif
592
593 static const char closed_stream[] = "closed stream";
594
595 void
596 rb_eof_error(void)
597 {
598 rb_raise(rb_eEOFError, "end of file reached");
599 }
600
601 VALUE
602 rb_io_taint_check(VALUE io)
603 {
604 rb_check_frozen(io);
605 return io;
606 }
607
608 void
609 rb_io_check_initialized(rb_io_t *fptr)
610 {
611 if (!fptr) {
612 rb_raise(rb_eIOError, "uninitialized stream");
613 }
614 }
615
616 void
617 rb_io_check_closed(rb_io_t *fptr)
618 {
619 rb_io_check_initialized(fptr);
620 if (fptr->fd < 0) {
621 rb_raise(rb_eIOError, closed_stream);
622 }
623 }
624
625
626 VALUE
627 rb_io_get_io(VALUE io)
628 {
629 return rb_convert_type(io, T_FILE, "IO", "to_io");
630 }
631
632 VALUE
633 rb_io_check_io(VALUE io)
634 {
635 return rb_check_convert_type(io, T_FILE, "IO", "to_io");
636 }
637
638 VALUE
639 rb_io_get_write_io(VALUE io)
640 {
641 VALUE write_io;
642 rb_io_check_initialized(RFILE(io)->fptr);
643 write_io = RFILE(io)->fptr->tied_io_for_writing;
644 if (write_io) {
645 return write_io;
646 }
647 return io;
648 }
649
650 VALUE
651 rb_io_set_write_io(VALUE io, VALUE w)
652 {
653 VALUE write_io;
654 rb_io_check_initialized(RFILE(io)->fptr);
655 if (!RTEST(w)) {
656 w = 0;
657 }
658 else {
659 GetWriteIO(w);
660 }
661 write_io = RFILE(io)->fptr->tied_io_for_writing;
662 RFILE(io)->fptr->tied_io_for_writing = w;
663 return write_io ? write_io : Qnil;
664 }
665
666 /*
667 * call-seq:
668 * IO.try_convert(obj) -> io or nil
669 *
670 * Try to convert <i>obj</i> into an IO, using to_io method.
671 * Returns converted IO or nil if <i>obj</i> cannot be converted
672 * for any reason.
673 *
674 * IO.try_convert(STDOUT) #=> STDOUT
675 * IO.try_convert("STDOUT") #=> nil
676 *
677 * require 'zlib'
678 * f = open("/tmp/zz.gz") #=> #<File:/tmp/zz.gz>
679 * z = Zlib::GzipReader.open(f) #=> #<Zlib::GzipReader:0x81d8744>
680 * IO.try_convert(z) #=> #<File:/tmp/zz.gz>
681 *
682 */
683 static VALUE
684 rb_io_s_try_convert(VALUE dummy, VALUE io)
685 {
686 return rb_io_check_io(io);
687 }
688
689 #if !(defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32))
690 static void
691 io_unread(rb_io_t *fptr)
692 {
693 off_t r;
694 rb_io_check_closed(fptr);
695 if (fptr->rbuf.len == 0 || fptr->mode & FMODE_DUPLEX)
696 return;
697 /* xxx: target position may be negative if buffer is filled by ungetc */
698 errno = 0;
699 r = lseek(fptr->fd, -fptr->rbuf.len, SEEK_CUR);
700 if (r < 0 && errno) {
701 if (errno == ESPIPE)
702 fptr->mode |= FMODE_DUPLEX;
703 return;
704 }
705 fptr->rbuf.off = 0;
706 fptr->rbuf.len = 0;
707 return;
708 }
709 #endif
710
711 static rb_encoding *io_input_encoding(rb_io_t *fptr);
712
713 static void
714 io_ungetbyte(VALUE str, rb_io_t *fptr)
715 {
716 long len = RSTRING_LEN(str);
717
718 if (fptr->rbuf.ptr == NULL) {
719 const int min_capa = IO_RBUF_CAPA_FOR(fptr);
720 fptr->rbuf.off = 0;
721 fptr->rbuf.len = 0;
722 #if SIZEOF_LONG > SIZEOF_INT
723 if (len > INT_MAX)
724 rb_raise(rb_eIOError, "ungetbyte failed");
725 #endif
726 if (len > min_capa)
727 fptr->rbuf.capa = (int)len;
728 else
729 fptr->rbuf.capa = min_capa;
730 fptr->rbuf.ptr = ALLOC_N(char, fptr->rbuf.capa);
731 }
732 if (fptr->rbuf.capa < len + fptr->rbuf.len) {
733 rb_raise(rb_eIOError, "ungetbyte failed");
734 }
735 if (fptr->rbuf.off < len) {
736 MEMMOVE(fptr->rbuf.ptr+fptr->rbuf.capa-fptr->rbuf.len,
737 fptr->rbuf.ptr+fptr->rbuf.off,
738 char, fptr->rbuf.len);
739 fptr->rbuf.off = fptr->rbuf.capa-fptr->rbuf.len;
740 }
741 fptr->rbuf.off-=(int)len;
742 fptr->rbuf.len+=(int)len;
743 MEMMOVE(fptr->rbuf.ptr+fptr->rbuf.off, RSTRING_PTR(str), char, len);
744 }
745
746 static rb_io_t *
747 flush_before_seek(rb_io_t *fptr)
748 {
749 if (io_fflush(fptr) < 0)
750 rb_sys_fail(0);
751 io_unread(fptr);
752 errno = 0;
753 return fptr;
754 }
755
756 #define io_seek(fptr, ofs, whence) (errno = 0, lseek(flush_before_seek(fptr)->fd, (ofs), (whence)))
757 #define io_tell(fptr) lseek(flush_before_seek(fptr)->fd, 0, SEEK_CUR)
758
759 #ifndef SEEK_CUR
760 # define SEEK_SET 0
761 # define SEEK_CUR 1
762 # define SEEK_END 2
763 #endif
764
765 void
766 rb_io_check_char_readable(rb_io_t *fptr)
767 {
768 rb_io_check_closed(fptr);
769 if (!(fptr->mode & FMODE_READABLE)) {
770 rb_raise(rb_eIOError, "not opened for reading");
771 }
772 if (fptr->wbuf.len) {
773 if (io_fflush(fptr) < 0)
774 rb_sys_fail(0);
775 }
776 if (fptr->tied_io_for_writing) {
777 rb_io_t *wfptr;
778 GetOpenFile(fptr->tied_io_for_writing, wfptr);
779 if (io_fflush(wfptr) < 0)
780 rb_sys_fail(0);
781 }
782 }
783
784 void
785 rb_io_check_byte_readable(rb_io_t *fptr)
786 {
787 rb_io_check_char_readable(fptr);
788 if (READ_CHAR_PENDING(fptr)) {
789 rb_raise(rb_eIOError, "byte oriented read for character buffered IO");
790 }
791 }
792
793 void
794 rb_io_check_readable(rb_io_t *fptr)
795 {
796 rb_io_check_byte_readable(fptr);
797 }
798
799 static rb_encoding*
800 io_read_encoding(rb_io_t *fptr)
801 {
802 if (fptr->encs.enc) {
803 return fptr->encs.enc;
804 }
805 return rb_default_external_encoding();
806 }
807
808 static rb_encoding*
809 io_input_encoding(rb_io_t *fptr)
810 {
811 if (fptr->encs.enc2) {
812 return fptr->encs.enc2;
813 }
814 return io_read_encoding(fptr);
815 }
816
817 void
818 rb_io_check_writable(rb_io_t *fptr)
819 {
820 rb_io_check_closed(fptr);
821 if (!(fptr->mode & FMODE_WRITABLE)) {
822 rb_raise(rb_eIOError, "not opened for writing");
823 }
824 if (fptr->rbuf.len) {
825 io_unread(fptr);
826 }
827 }
828
829 int
830 rb_io_read_pending(rb_io_t *fptr)
831 {
832 /* This function is used for bytes and chars. Confusing. */
833 if (READ_CHAR_PENDING(fptr))
834 return 1; /* should raise? */
835 return READ_DATA_PENDING(fptr);
836 }
837
838 void
839 rb_read_check(FILE *fp)
840 {
841 if (!STDIO_READ_DATA_PENDING(fp)) {
842 rb_thread_wait_fd(fileno(fp));
843 }
844 }
845
846 void
847 rb_io_read_check(rb_io_t *fptr)
848 {
849 if (!READ_DATA_PENDING(fptr)) {
850 rb_thread_wait_fd(fptr->fd);
851 }
852 return;
853 }
854
855 static int
856 ruby_dup(int orig)
857 {
858 int fd;
859
860 fd = rb_cloexec_dup(orig);
861 if (fd < 0) {
862 if (errno == EMFILE || errno == ENFILE || errno == ENOMEM) {
863 rb_gc();
864 fd = rb_cloexec_dup(orig);
865 }
866 if (fd < 0) {
867 rb_sys_fail(0);
868 }
869 }
870 rb_update_max_fd(fd);
871 return fd;
872 }
873
874 static VALUE
875 io_alloc(VALUE klass)
876 {
877 NEWOBJ_OF(io, struct RFile, klass, T_FILE);
878
879 io->fptr = 0;
880
881 return (VALUE)io;
882 }
883
884 #ifndef S_ISREG
885 # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
886 #endif
887
888 static int
889 wsplit_p(rb_io_t *fptr)
890 {
891 #if defined(HAVE_FCNTL) && defined(F_GETFL) && defined(O_NONBLOCK)
892 int r;
893 #endif
894
895 if (!(fptr->mode & FMODE_WSPLIT_INITIALIZED)) {
896 struct stat buf;
897 if (fstat(fptr->fd, &buf) == 0 &&
898 !S_ISREG(buf.st_mode)
899 #if defined(HAVE_FCNTL) && defined(F_GETFL) && defined(O_NONBLOCK)
900 && (r = fcntl(fptr->fd, F_GETFL)) != -1 &&
901 !(r & O_NONBLOCK)
902 #endif
903 ) {
904 fptr->mode |= FMODE_WSPLIT;
905 }
906 fptr->mode |= FMODE_WSPLIT_INITIALIZED;
907 }
908 return fptr->mode & FMODE_WSPLIT;
909 }
910
911 struct io_internal_read_struct {
912 int fd;
913 void *buf;
914 size_t capa;
915 };
916
917 struct io_internal_write_struct {
918 int fd;
919 const void *buf;
920 size_t capa;
921 };
922
923 static VALUE
924 internal_read_func(void *ptr)
925 {
926 struct io_internal_read_struct *iis = ptr;
927 return read(iis->fd, iis->buf, iis->capa);
928 }
929
930 static VALUE
931 internal_write_func(void *ptr)
932 {
933 struct io_internal_write_struct *iis = ptr;
934 return write(iis->fd, iis->buf, iis->capa);
935 }
936
937 static void*
938 internal_write_func2(void *ptr)
939 {
940 struct io_internal_write_struct *iis = ptr;
941 return (void*)(intptr_t)write(iis->fd, iis->buf, iis->capa);
942 }
943
944 static ssize_t
945 rb_read_internal(int fd, void *buf, size_t count)
946 {
947 struct io_internal_read_struct iis;
948 iis.fd = fd;
949 iis.buf = buf;
950 iis.capa = count;
951
952 return (ssize_t)rb_thread_io_blocking_region(internal_read_func, &iis, fd);
953 }
954
955 static ssize_t
956 rb_write_internal(int fd, const void *buf, size_t count)
957 {
958 struct io_internal_write_struct iis;
959 iis.fd = fd;
960 iis.buf = buf;
961 iis.capa = count;
962
963 return (ssize_t)rb_thread_io_blocking_region(internal_write_func, &iis, fd);
964 }
965
966 static ssize_t
967 rb_write_internal2(int fd, const void *buf, size_t count)
968 {
969 struct io_internal_write_struct iis;
970 iis.fd = fd;
971 iis.buf = buf;
972 iis.capa = count;
973
974 return (ssize_t)rb_thread_call_without_gvl2(internal_write_func2, &iis,
975 RUBY_UBF_IO, NULL);
976 }
977
978 static long
979 io_writable_length(rb_io_t *fptr, long l)
980 {
981 if (PIPE_BUF < l &&
982 !rb_thread_alone() &&
983 wsplit_p(fptr)) {
984 l = PIPE_BUF;
985 }
986 return l;
987 }
988
989 static VALUE
990 io_flush_buffer_sync(void *arg)
991 {
992 rb_io_t *fptr = arg;
993 long l = io_writable_length(fptr, fptr->wbuf.len);
994 ssize_t r = write(fptr->fd, fptr->wbuf.ptr+fptr->wbuf.off, (size_t)l);
995
996 if (fptr->wbuf.len <= r) {
997 fptr->wbuf.off = 0;
998 fptr->wbuf.len = 0;
999 return 0;
1000 }
1001 if (0 <= r) {
1002 fptr->wbuf.off += (int)r;
1003 fptr->wbuf.len -= (int)r;
1004 errno = EAGAIN;
1005 }
1006 return (VALUE)-1;
1007 }
1008
1009 static void*
1010 io_flush_buffer_sync2(void *arg)
1011 {
1012 VALUE result = io_flush_buffer_sync(arg);
1013
1014 /*
1015 * rb_thread_call_without_gvl2 uses 0 as interrupted.
1016 * So, we need to avoid to use 0.
1017 */
1018 return !result ? (void*)1 : (void*)result;
1019 }
1020
1021 static VALUE
1022 io_flush_buffer_async(VALUE arg)
1023 {
1024 rb_io_t *fptr = (rb_io_t *)arg;
1025 return rb_thread_io_blocking_region(io_flush_buffer_sync, fptr, fptr->fd);
1026 }
1027
1028 static VALUE
1029 io_flush_buffer_async2(VALUE arg)
1030 {
1031 rb_io_t *fptr = (rb_io_t *)arg;
1032 VALUE ret;
1033
1034 ret = (VALUE)rb_thread_call_without_gvl2(io_flush_buffer_sync2, fptr,
1035 RUBY_UBF_IO, NULL);
1036
1037 if (!ret) {
1038 /* pending async interrupt is there. */
1039 errno = EAGAIN;
1040 return -1;
1041 } else if (ret == 1) {
1042 return 0;
1043 } else
1044 return ret;
1045 }
1046
1047 static inline int
1048 io_flush_buffer(rb_io_t *fptr)
1049 {
1050 if (fptr->write_lock) {
1051 if (rb_mutex_owned_p(fptr->write_lock))
1052 return (int)io_flush_buffer_async2((VALUE)fptr);
1053 else
1054 return (int)rb_mutex_synchronize(fptr->write_lock, io_flush_buffer_async2, (VALUE)fptr);
1055 }
1056 else {
1057 return (int)io_flush_buffer_async((VALUE)fptr);
1058 }
1059 }
1060
1061 static int
1062 io_fflush(rb_io_t *fptr)
1063 {
1064 rb_io_check_closed(fptr);
1065 if (fptr->wbuf.len == 0)
1066 return 0;
1067 rb_io_check_closed(fptr);
1068 while (fptr->wbuf.len > 0 && io_flush_buffer(fptr) != 0) {
1069 if (!rb_io_wait_writable(fptr->fd))
1070 return -1;
1071 rb_io_check_closed(fptr);
1072 }
1073 return 0;
1074 }
1075
1076 int
1077 rb_io_wait_readable(int f)
1078 {
1079 if (f < 0) {
1080 rb_raise(rb_eIOError, closed_stream);
1081 }
1082 switch (errno) {
1083 case EINTR:
1084 #if defined(ERESTART)
1085 case ERESTART:
1086 #endif
1087 rb_thread_check_ints();
1088 return TRUE;
1089
1090 case EAGAIN:
1091 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
1092 case EWOULDBLOCK:
1093 #endif
1094 rb_thread_wait_fd(f);
1095 return TRUE;
1096
1097 default:
1098 return FALSE;
1099 }
1100 }
1101
1102 int
1103 rb_io_wait_writable(int f)
1104 {
1105 if (f < 0) {
1106 rb_raise(rb_eIOError, closed_stream);
1107 }
1108 switch (errno) {
1109 case EINTR:
1110 #if defined(ERESTART)
1111 case ERESTART:
1112 #endif
1113 /*
1114 * In old Linux, several special files under /proc and /sys don't handle
1115 * select properly. Thus we need avoid to call if don't use O_NONBLOCK.
1116 * Otherwise, we face nasty hang up. Sigh.
1117 * e.g. http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=31b07093c44a7a442394d44423e21d783f5523b8
1118 * http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=31b07093c44a7a442394d44423e21d783f5523b8
1119 * In EINTR case, we only need to call RUBY_VM_CHECK_INTS_BLOCKING().
1120 * Then rb_thread_check_ints() is enough.
1121 */
1122 rb_thread_check_ints();
1123 return TRUE;
1124
1125 case EAGAIN:
1126 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
1127 case EWOULDBLOCK:
1128 #endif
1129 rb_thread_fd_writable(f);
1130 return TRUE;
1131
1132 default:
1133 return FALSE;
1134 }
1135 }
1136
1137 static void
1138 make_writeconv(rb_io_t *fptr)
1139 {
1140 if (!fptr->writeconv_initialized) {
1141 const char *senc, *denc;
1142 rb_encoding *enc;
1143 int ecflags;
1144 VALUE ecopts;
1145
1146 fptr->writeconv_initialized = 1;
1147
1148 ecflags = fptr->encs.ecflags & ~ECONV_NEWLINE_DECORATOR_READ_MASK;
1149 ecopts = fptr->encs.ecopts;
1150
1151 if (!fptr->encs.enc || (fptr->encs.enc == rb_ascii8bit_encoding() && !fptr->encs.enc2)) {
1152 /* no encoding conversion */
1153 fptr->writeconv_pre_ecflags = 0;
1154 fptr->writeconv_pre_ecopts = Qnil;
1155 fptr->writeconv = rb_econv_open_opts("", "", ecflags, ecopts);
1156 if (!fptr->writeconv)
1157 rb_exc_raise(rb_econv_open_exc("", "", ecflags));
1158 fptr->writeconv_asciicompat = Qnil;
1159 }
1160 else {
1161 enc = fptr->encs.enc2 ? fptr->encs.enc2 : fptr->encs.enc;
1162 senc = rb_econv_asciicompat_encoding(rb_enc_name(enc));
1163 if (!senc && !(fptr->encs.ecflags & ECONV_STATEFUL_DECORATOR_MASK)) {
1164 /* single conversion */
1165 fptr->writeconv_pre_ecflags = ecflags;
1166 fptr->writeconv_pre_ecopts = ecopts;
1167 fptr->writeconv = NULL;
1168 fptr->writeconv_asciicompat = Qnil;
1169 }
1170 else {
1171 /* double conversion */
1172 fptr->writeconv_pre_ecflags = ecflags & ~ECONV_STATEFUL_DECORATOR_MASK;
1173 fptr->writeconv_pre_ecopts = ecopts;
1174 if (senc) {
1175 denc = rb_enc_name(enc);
1176 fptr->writeconv_asciicompat = rb_str_new2(senc);
1177 }
1178 else {
1179 senc = denc = "";
1180 fptr->writeconv_asciicompat = rb_str_new2(rb_enc_name(enc));
1181 }
1182 ecflags = fptr->encs.ecflags & (ECONV_ERROR_HANDLER_MASK|ECONV_STATEFUL_DECORATOR_MASK);
1183 ecopts = fptr->encs.ecopts;
1184 fptr->writeconv = rb_econv_open_opts(senc, denc, ecflags, ecopts);
1185 if (!fptr->writeconv)
1186 rb_exc_raise(rb_econv_open_exc(senc, denc, ecflags));
1187 }
1188 }
1189 }
1190 }
1191
1192 /* writing functions */
1193 struct binwrite_arg {
1194 rb_io_t *fptr;
1195 VALUE str;
1196 const char *ptr;
1197 long length;
1198 };
1199
1200 struct write_arg {
1201 VALUE io;
1202 VALUE str;
1203 int nosync;
1204 };
1205
1206 static VALUE
1207 io_binwrite_string(VALUE arg)
1208 {
1209 struct binwrite_arg *p = (struct binwrite_arg *)arg;
1210 long l = io_writable_length(p->fptr, p->length);
1211 return rb_write_internal2(p->fptr->fd, p->ptr, l);
1212 }
1213
1214 static long
1215 io_binwrite(VALUE str, const char *ptr, long len, rb_io_t *fptr, int nosync)
1216 {
1217 long n, r, offset = 0;
1218
1219 /* don't write anything if current thread has a pending interrupt. */
1220 rb_thread_check_ints();
1221
1222 if ((n = len) <= 0) return n;
1223 if (fptr->wbuf.ptr == NULL && !(!nosync && (fptr->mode & FMODE_SYNC))) {
1224 fptr->wbuf.off = 0;
1225 fptr->wbuf.len = 0;
1226 fptr->wbuf.capa = IO_WBUF_CAPA_MIN;
1227 fptr->wbuf.ptr = ALLOC_N(char, fptr->wbuf.capa);
1228 fptr->write_lock = rb_mutex_new();
1229 rb_mutex_allow_trap(fptr->write_lock, 1);
1230 }
1231 if ((!nosync && (fptr->mode & (FMODE_SYNC|FMODE_TTY))) ||
1232 (fptr->wbuf.ptr && fptr->wbuf.capa <= fptr->wbuf.len + len)) {
1233 struct binwrite_arg arg;
1234
1235 /*
1236 * xxx: use writev to avoid double write if available
1237 * writev may help avoid context switch between "a" and "\n" in
1238 * STDERR.puts "a" [ruby-dev:25080] (rebroken since native threads
1239 * introduced in 1.9)
1240 */
1241 if (fptr->wbuf.len && fptr->wbuf.len+len <= fptr->wbuf.capa) {
1242 if (fptr->wbuf.capa < fptr->wbuf.off+fptr->wbuf.len+len) {
1243 MEMMOVE(fptr->wbuf.ptr, fptr->wbuf.ptr+fptr->wbuf.off, char, fptr->wbuf.len);
1244 fptr->wbuf.off = 0;
1245 }
1246 MEMMOVE(fptr->wbuf.ptr+fptr->wbuf.off+fptr->wbuf.len, ptr+offset, char, len);
1247 fptr->wbuf.len += (int)len;
1248 n = 0;
1249 }
1250 if (io_fflush(fptr) < 0)
1251 return -1L;
1252 if (n == 0)
1253 return len;
1254
1255 rb_io_check_closed(fptr);
1256 arg.fptr = fptr;
1257 arg.str = str;
1258 retry:
1259 arg.ptr = ptr + offset;
1260 arg.length = n;
1261 if (fptr->write_lock) {
1262 r = rb_mutex_synchronize(fptr->write_lock, io_binwrite_string, (VALUE)&arg);
1263 }
1264 else {
1265 long l = io_writable_length(fptr, n);
1266 r = rb_write_internal(fptr->fd, ptr+offset, l);
1267 }
1268 /* xxx: other threads may modify given string. */
1269 if (r == n) return len;
1270 if (0 <= r) {
1271 offset += r;
1272 n -= r;
1273 errno = EAGAIN;
1274 }
1275 if (rb_io_wait_writable(fptr->fd)) {
1276 rb_io_check_closed(fptr);
1277 if (offset < len)
1278 goto retry;
1279 }
1280 return -1L;
1281 }
1282
1283 if (fptr->wbuf.off) {
1284 if (fptr->wbuf.len)
1285 MEMMOVE(fptr->wbuf.ptr, fptr->wbuf.ptr+fptr->wbuf.off, char, fptr->wbuf.len);
1286 fptr->wbuf.off = 0;
1287 }
1288 MEMMOVE(fptr->wbuf.ptr+fptr->wbuf.off+fptr->wbuf.len, ptr+offset, char, len);
1289 fptr->wbuf.len += (int)len;
1290 return len;
1291 }
1292
1293 # define MODE_BTMODE(a,b,c) ((fmode & FMODE_BINMODE) ? (b) : \
1294 (fmode & FMODE_TEXTMODE) ? (c) : (a))
1295 static VALUE
1296 do_writeconv(VALUE str, rb_io_t *fptr)
1297 {
1298 if (NEED_WRITECONV(fptr)) {
1299 VALUE common_encoding = Qnil;
1300 SET_BINARY_MODE(fptr);
1301
1302 make_writeconv(fptr);
1303
1304 if (fptr->writeconv) {
1305 #define fmode (fptr->mode)
1306 if (!NIL_P(fptr->writeconv_asciicompat))
1307 common_encoding = fptr->writeconv_asciicompat;
1308 else if (MODE_BTMODE(DEFAULT_TEXTMODE,0,1) && !rb_enc_asciicompat(rb_enc_get(str))) {
1309 rb_raise(rb_eArgError, "ASCII incompatible string written for text mode IO without encoding conversion: %s",
1310 rb_enc_name(rb_enc_get(str)));
1311 }
1312 #undef fmode
1313 }
1314 else {
1315 if (fptr->encs.enc2)
1316 common_encoding = rb_enc_from_encoding(fptr->encs.enc2);
1317 else if (fptr->encs.enc != rb_ascii8bit_encoding())
1318 common_encoding = rb_enc_from_encoding(fptr->encs.enc);
1319 }
1320
1321 if (!NIL_P(common_encoding)) {
1322 str = rb_str_encode(str, common_encoding,
1323 fptr->writeconv_pre_ecflags, fptr->writeconv_pre_ecopts);
1324 }
1325
1326 if (fptr->writeconv) {
1327 str = rb_econv_str_convert(fptr->writeconv, str, ECONV_PARTIAL_INPUT);
1328 }
1329 }
1330 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
1331 #define fmode (fptr->mode)
1332 else if (MODE_BTMODE(DEFAULT_TEXTMODE,0,1)) {
1333 if ((fptr->mode & FMODE_READABLE) &&
1334 !(fptr->encs.ecflags & ECONV_NEWLINE_DECORATOR_MASK)) {
1335 setmode(fptr->fd, O_BINARY);
1336 }
1337 else {
1338 setmode(fptr->fd, O_TEXT);
1339 }
1340 if (!rb_enc_asciicompat(rb_enc_get(str))) {
1341 rb_raise(rb_eArgError, "ASCII incompatible string written for text mode IO without encoding conversion: %s",
1342 rb_enc_name(rb_enc_get(str)));
1343 }
1344 }
1345 #undef fmode
1346 #endif
1347 return str;
1348 }
1349
1350 static long
1351 io_fwrite(VALUE str, rb_io_t *fptr, int nosync)
1352 {
1353 #ifdef _WIN32
1354 if (fptr->mode & FMODE_TTY) {
1355 long len = rb_w32_write_console(str, fptr->fd);
1356 if (len > 0) return len;
1357 }
1358 #endif
1359 str = do_writeconv(str, fptr);
1360 return io_binwrite(str, RSTRING_PTR(str), RSTRING_LEN(str),
1361 fptr, nosync);
1362 }
1363
1364 ssize_t
1365 rb_io_bufwrite(VALUE io, const void *buf, size_t size)
1366 {
1367 rb_io_t *fptr;
1368
1369 GetOpenFile(io, fptr);
1370 rb_io_check_writable(fptr);
1371 return (ssize_t)io_binwrite(0, buf, (long)size, fptr, 0);
1372 }
1373
1374 static VALUE
1375 io_write(VALUE io, VALUE str, int nosync)
1376 {
1377 rb_io_t *fptr;
1378 long n;
1379 VALUE tmp;
1380
1381 io = GetWriteIO(io);
1382 str = rb_obj_as_string(str);
1383 tmp = rb_io_check_io(io);
1384 if (NIL_P(tmp)) {
1385 /* port is not IO, call write method for it. */
1386 return rb_funcall(io, id_write, 1, str);
1387 }
1388 io = tmp;
1389 if (RSTRING_LEN(str) == 0) return INT2FIX(0);
1390
1391 str = rb_str_new_frozen(str);
1392
1393 GetOpenFile(io, fptr);
1394 rb_io_check_writable(fptr);
1395
1396 n = io_fwrite(str, fptr, nosync);
1397 if (n == -1L) rb_sys_fail_path(fptr->pathv);
1398
1399 return LONG2FIX(n);
1400 }
1401
1402 /*
1403 * call-seq:
1404 * ios.write(string) -> integer
1405 *
1406 * Writes the given string to <em>ios</em>. The stream must be opened
1407 * for writing. If the argument is not a string, it will be converted
1408 * to a string using <code>to_s</code>. Returns the number of bytes
1409 * written.
1410 *
1411 * count = $stdout.write("This is a test\n")
1412 * puts "That was #{count} bytes of data"
1413 *
1414 * <em>produces:</em>
1415 *
1416 * This is a test
1417 * That was 15 bytes of data
1418 */
1419
1420 static VALUE
1421 io_write_m(VALUE io, VALUE str)
1422 {
1423 return io_write(io, str, 0);
1424 }
1425
1426 VALUE
1427 rb_io_write(VALUE io, VALUE str)
1428 {
1429 return rb_funcallv(io, id_write, 1, &str);
1430 }
1431
1432 /*
1433 * call-seq:
1434 * ios << obj -> ios
1435 *
1436 * String Output---Writes <i>obj</i> to <em>ios</em>.
1437 * <i>obj</i> will be converted to a string using
1438 * <code>to_s</code>.
1439 *
1440 * $stdout << "Hello " << "world!\n"
1441 *
1442 * <em>produces:</em>
1443 *
1444 * Hello world!
1445 */
1446
1447
1448 VALUE
1449 rb_io_addstr(VALUE io, VALUE str)
1450 {
1451 rb_io_write(io, str);
1452 return io;
1453 }
1454
1455 #ifdef HAVE_FSYNC
1456 static VALUE
1457 nogvl_fsync(void *ptr)
1458 {
1459 rb_io_t *fptr = ptr;
1460
1461 return (VALUE)fsync(fptr->fd);
1462 }
1463 #endif
1464
1465 VALUE
1466 rb_io_flush_raw(VALUE io, int sync)
1467 {
1468 rb_io_t *fptr;
1469
1470 if (!RB_TYPE_P(io, T_FILE)) {
1471 return rb_funcall(io, id_flush, 0);
1472 }
1473
1474 io = GetWriteIO(io);
1475 GetOpenFile(io, fptr);
1476
1477 if (fptr->mode & FMODE_WRITABLE) {
1478 if (io_fflush(fptr) < 0)
1479 rb_sys_fail(0);
1480 #ifdef _WIN32
1481 if (sync && GetFileType((HANDLE)rb_w32_get_osfhandle(fptr->fd)) == FILE_TYPE_DISK) {
1482 rb_thread_io_blocking_region(nogvl_fsync, fptr, fptr->fd);
1483 }
1484 #endif
1485 }
1486 if (fptr->mode & FMODE_READABLE) {
1487 io_unread(fptr);
1488 }
1489
1490 return io;
1491 }
1492
1493 /*
1494 * call-seq:
1495 * ios.flush -> ios
1496 *
1497 * Flushes any buffered data within <em>ios</em> to the underlying
1498 * operating system (note that this is Ruby internal buffering only;
1499 * the OS may buffer the data as well).
1500 *
1501 * $stdout.print "no newline"
1502 * $stdout.flush
1503 *
1504 * <em>produces:</em>
1505 *
1506 * no newline
1507 */
1508
1509 VALUE
1510 rb_io_flush(VALUE io)
1511 {
1512 return rb_io_flush_raw(io, 1);
1513 }
1514
1515 /*
1516 * call-seq:
1517 * ios.pos -> integer
1518 * ios.tell -> integer
1519 *
1520 * Returns the current offset (in bytes) of <em>ios</em>.
1521 *
1522 * f = File.new("testfile")
1523 * f.pos #=> 0
1524 * f.gets #=> "This is line one\n"
1525 * f.pos #=> 17
1526 */
1527
1528 static VALUE
1529 rb_io_tell(VALUE io)
1530 {
1531 rb_io_t *fptr;
1532 off_t pos;
1533
1534 GetOpenFile(io, fptr);
1535 pos = io_tell(fptr);
1536 if (pos < 0 && errno) rb_sys_fail_path(fptr->pathv);
1537 pos -= fptr->rbuf.len;
1538 return OFFT2NUM(pos);
1539 }
1540
1541 static VALUE
1542 rb_io_seek(VALUE io, VALUE offset, int whence)
1543 {
1544 rb_io_t *fptr;
1545 off_t pos;
1546
1547 pos = NUM2OFFT(offset);
1548 GetOpenFile(io, fptr);
1549 pos = io_seek(fptr, pos, whence);
1550 if (pos < 0 && errno) rb_sys_fail_path(fptr->pathv);
1551
1552 return INT2FIX(0);
1553 }
1554
1555 static int
1556 interpret_seek_whence(VALUE vwhence)
1557 {
1558 if (vwhence == sym_SET)
1559 return SEEK_SET;
1560 if (vwhence == sym_CUR)
1561 return SEEK_CUR;
1562 if (vwhence == sym_END)
1563 return SEEK_END;
1564 #ifdef SEEK_DATA
1565 if (vwhence == sym_DATA)
1566 return SEEK_DATA;
1567 #endif
1568 #ifdef SEEK_HOLE
1569 if (vwhence == sym_HOLE)
1570 return SEEK_HOLE;
1571 #endif
1572 return NUM2INT(vwhence);
1573 }
1574
1575 /*
1576 * call-seq:
1577 * ios.seek(amount, whence=IO::SEEK_SET) -> 0
1578 *
1579 * Seeks to a given offset <i>anInteger</i> in the stream according to
1580 * the value of <i>whence</i>:
1581 *
1582 * :CUR or IO::SEEK_CUR | Seeks to _amount_ plus current position
1583 * ----------------------+--------------------------------------------------
1584 * :END or IO::SEEK_END | Seeks to _amount_ plus end of stream (you
1585 * | probably want a negative value for _amount_)
1586 * ----------------------+--------------------------------------------------
1587 * :SET or IO::SEEK_SET | Seeks to the absolute location given by _amount_
1588 *
1589 * Example:
1590 *
1591 * f = File.new("testfile")
1592 * f.seek(-13, IO::SEEK_END) #=> 0
1593 * f.readline #=> "And so on...\n"
1594 */
1595
1596 static VALUE
1597 rb_io_seek_m(int argc, VALUE *argv, VALUE io)
1598 {
1599 VALUE offset, ptrname;
1600 int whence = SEEK_SET;
1601
1602 if (rb_scan_args(argc, argv, "11", &offset, &ptrname) == 2) {
1603 whence = interpret_seek_whence(ptrname);
1604 }
1605
1606 return rb_io_seek(io, offset, whence);
1607 }
1608
1609 /*
1610 * call-seq:
1611 * ios.pos = integer -> integer
1612 *
1613 * Seeks to the given position (in bytes) in <em>ios</em>.
1614 * It is not guaranteed that seeking to the right position when <em>ios</em>
1615 * is textmode.
1616 *
1617 * f = File.new("testfile")
1618 * f.pos = 17
1619 * f.gets #=> "This is line two\n"
1620 */
1621
1622 static VALUE
1623 rb_io_set_pos(VALUE io, VALUE offset)
1624 {
1625 rb_io_t *fptr;
1626 off_t pos;
1627
1628 pos = NUM2OFFT(offset);
1629 GetOpenFile(io, fptr);
1630 pos = io_seek(fptr, pos, SEEK_SET);
1631 if (pos < 0 && errno) rb_sys_fail_path(fptr->pathv);
1632
1633 return OFFT2NUM(pos);
1634 }
1635
1636 static void clear_readconv(rb_io_t *fptr);
1637
1638 /*
1639 * call-seq:
1640 * ios.rewind -> 0
1641 *
1642 * Positions <em>ios</em> to the beginning of input, resetting
1643 * <code>lineno</code> to zero.
1644 *
1645 * f = File.new("testfile")
1646 * f.readline #=> "This is line one\n"
1647 * f.rewind #=> 0
1648 * f.lineno #=> 0
1649 * f.readline #=> "This is line one\n"
1650 *
1651 * Note that it cannot be used with streams such as pipes, ttys, and sockets.
1652 */
1653
1654 static VALUE
1655 rb_io_rewind(VALUE io)
1656 {
1657 rb_io_t *fptr;
1658
1659 GetOpenFile(io, fptr);
1660 if (io_seek(fptr, 0L, 0) < 0 && errno) rb_sys_fail_path(fptr->pathv);
1661 if (io == ARGF.current_file) {
1662 ARGF.lineno -= fptr->lineno;
1663 }
1664 fptr->lineno = 0;
1665 if (fptr->readconv) {
1666 clear_readconv(fptr);
1667 }
1668
1669 return INT2FIX(0);
1670 }
1671
1672 static int
1673 io_fillbuf(rb_io_t *fptr)
1674 {
1675 ssize_t r;
1676
1677 if (fptr->rbuf.ptr == NULL) {
1678 fptr->rbuf.off = 0;
1679 fptr->rbuf.len = 0;
1680 fptr->rbuf.capa = IO_RBUF_CAPA_FOR(fptr);
1681 fptr->rbuf.ptr = ALLOC_N(char, fptr->rbuf.capa);
1682 #ifdef _WIN32
1683 fptr->rbuf.capa--;
1684 #endif
1685 }
1686 if (fptr->rbuf.len == 0) {
1687 retry:
1688 {
1689 r = rb_read_internal(fptr->fd, fptr->rbuf.ptr, fptr->rbuf.capa);
1690 }
1691 if (r < 0) {
1692 if (rb_io_wait_readable(fptr->fd))
1693 goto retry;
1694 {
1695 VALUE path = rb_sprintf("fd:%d ", fptr->fd);
1696 if (!NIL_P(fptr->pathv)) {
1697 rb_str_append(path, fptr->pathv);
1698 }
1699 rb_sys_fail_path(path);
1700 }
1701 }
1702 fptr->rbuf.off = 0;
1703 fptr->rbuf.len = (int)r; /* r should be <= rbuf_capa */
1704 if (r == 0)
1705 return -1; /* EOF */
1706 }
1707 return 0;
1708 }
1709
1710 /*
1711 * call-seq:
1712 * ios.eof -> true or false
1713 * ios.eof? -> true or false
1714 *
1715 * Returns true if <em>ios</em> is at end of file that means
1716 * there are no more data to read.
1717 * The stream must be opened for reading or an <code>IOError</code> will be
1718 * raised.
1719 *
1720 * f = File.new("testfile")
1721 * dummy = f.readlines
1722 * f.eof #=> true
1723 *
1724 * If <em>ios</em> is a stream such as pipe or socket, <code>IO#eof?</code>
1725 * blocks until the other end sends some data or closes it.
1726 *
1727 * r, w = IO.pipe
1728 * Thread.new { sleep 1; w.close }
1729 * r.eof? #=> true after 1 second blocking
1730 *
1731 * r, w = IO.pipe
1732 * Thread.new { sleep 1; w.puts "a" }
1733 * r.eof? #=> false after 1 second blocking
1734 *
1735 * r, w = IO.pipe
1736 * r.eof? # blocks forever
1737 *
1738 * Note that <code>IO#eof?</code> reads data to the input byte buffer.
1739 * So <code>IO#sysread</code> may not behave as you intend with
1740 * <code>IO#eof?</code>, unless you call <code>IO#rewind</code>
1741 * first (which is not available for some streams).
1742 */
1743
1744 VALUE
1745 rb_io_eof(VALUE io)
1746 {
1747 rb_io_t *fptr;
1748
1749 GetOpenFile(io, fptr);
1750 rb_io_check_char_readable(fptr);
1751
1752 if (READ_CHAR_PENDING(fptr)) return Qfalse;
1753 if (READ_DATA_PENDING(fptr)) return Qfalse;
1754 READ_CHECK(fptr);
1755 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
1756 if (!NEED_READCONV(fptr) && NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {
1757 return eof(fptr->fd) ? Qtrue : Qfalse;
1758 }
1759 #endif
1760 if (io_fillbuf(fptr) < 0) {
1761 return Qtrue;
1762 }
1763 return Qfalse;
1764 }
1765
1766 /*
1767 * call-seq:
1768 * ios.sync -> true or false
1769 *
1770 * Returns the current ``sync mode'' of <em>ios</em>. When sync mode is
1771 * true, all output is immediately flushed to the underlying operating
1772 * system and is not buffered by Ruby internally. See also
1773 * <code>IO#fsync</code>.
1774 *
1775 * f = File.new("testfile")
1776 * f.sync #=> false
1777 */
1778
1779 static VALUE
1780 rb_io_sync(VALUE io)
1781 {
1782 rb_io_t *fptr;
1783
1784 io = GetWriteIO(io);
1785 GetOpenFile(io, fptr);
1786 return (fptr->mode & FMODE_SYNC) ? Qtrue : Qfalse;
1787 }
1788
1789 #ifdef HAVE_FSYNC
1790
1791 /*
1792 * call-seq:
1793 * ios.sync = boolean -> boolean
1794 *
1795 * Sets the ``sync mode'' to <code>true</code> or <code>false</code>.
1796 * When sync mode is true, all output is immediately flushed to the
1797 * underlying operating system and is not buffered internally. Returns
1798 * the new state. See also <code>IO#fsync</code>.
1799 *
1800 * f = File.new("testfile")
1801 * f.sync = true
1802 *
1803 * <em>(produces no output)</em>
1804 */
1805
1806 static VALUE
1807 rb_io_set_sync(VALUE io, VALUE sync)
1808 {
1809 rb_io_t *fptr;
1810
1811 io = GetWriteIO(io);
1812 GetOpenFile(io, fptr);
1813 if (RTEST(sync)) {
1814 fptr->mode |= FMODE_SYNC;
1815 }
1816 else {
1817 fptr->mode &= ~FMODE_SYNC;
1818 }
1819 return sync;
1820 }
1821
1822 /*
1823 * call-seq:
1824 * ios.fsync -> 0 or nil
1825 *
1826 * Immediately writes all buffered data in <em>ios</em> to disk.
1827 * Note that <code>fsync</code> differs from
1828 * using <code>IO#sync=</code>. The latter ensures that data is flushed
1829 * from Ruby's buffers, but does not guarantee that the underlying
1830 * operating system actually writes it to disk.
1831 *
1832 * <code>NotImplementedError</code> is raised
1833 * if the underlying operating system does not support <em>fsync(2)</em>.
1834 */
1835
1836 static VALUE
1837 rb_io_fsync(VALUE io)
1838 {
1839 rb_io_t *fptr;
1840
1841 io = GetWriteIO(io);
1842 GetOpenFile(io, fptr);
1843
1844 if (io_fflush(fptr) < 0)
1845 rb_sys_fail(0);
1846 # ifndef _WIN32 /* already called in io_fflush() */
1847 if ((int)rb_thread_io_blocking_region(nogvl_fsync, fptr, fptr->fd) < 0)
1848 rb_sys_fail_path(fptr->pathv);
1849 # endif
1850 return INT2FIX(0);
1851 }
1852 #else
1853 # define rb_io_fsync rb_f_notimplement
1854 # define rb_io_sync rb_f_notimplement
1855 static VALUE
1856 rb_io_set_sync(VALUE io, VALUE sync)
1857 {
1858 rb_notimplement();
1859 UNREACHABLE;
1860 }
1861 #endif
1862
1863 #ifdef HAVE_FDATASYNC
1864 static VALUE
1865 nogvl_fdatasync(void *ptr)
1866 {
1867 rb_io_t *fptr = ptr;
1868
1869 return (VALUE)fdatasync(fptr->fd);
1870 }
1871
1872 /*
1873 * call-seq:
1874 * ios.fdatasync -> 0 or nil
1875 *
1876 * Immediately writes all buffered data in <em>ios</em> to disk.
1877 *
1878 * If the underlying operating system does not support <em>fdatasync(2)</em>,
1879 * <code>IO#fsync</code> is called instead (which might raise a
1880 * <code>NotImplementedError</code>).
1881 */
1882
1883 static VALUE
1884 rb_io_fdatasync(VALUE io)
1885 {
1886 rb_io_t *fptr;
1887
1888 io = GetWriteIO(io);
1889 GetOpenFile(io, fptr);
1890
1891 if (io_fflush(fptr) < 0)
1892 rb_sys_fail(0);
1893
1894 if ((int)rb_thread_io_blocking_region(nogvl_fdatasync, fptr, fptr->fd) == 0)
1895 return INT2FIX(0);
1896
1897 /* fall back */
1898 return rb_io_fsync(io);
1899 }
1900 #else
1901 #define rb_io_fdatasync rb_io_fsync
1902 #endif
1903
1904 /*
1905 * call-seq:
1906 * ios.fileno -> fixnum
1907 * ios.to_i -> fixnum
1908 *
1909 * Returns an integer representing the numeric file descriptor for
1910 * <em>ios</em>.
1911 *
1912 * $stdin.fileno #=> 0
1913 * $stdout.fileno #=> 1
1914 */
1915
1916 static VALUE
1917 rb_io_fileno(VALUE io)
1918 {
1919 rb_io_t *fptr = RFILE(io)->fptr;
1920 int fd;
1921
1922 rb_io_check_closed(fptr);
1923 fd = fptr->fd;
1924 return INT2FIX(fd);
1925 }
1926
1927
1928 /*
1929 * call-seq:
1930 * ios.pid -> fixnum
1931 *
1932 * Returns the process ID of a child process associated with
1933 * <em>ios</em>. This will be set by <code>IO.popen</code>.
1934 *
1935 * pipe = IO.popen("-")
1936 * if pipe
1937 * $stderr.puts "In parent, child pid is #{pipe.pid}"
1938 * else
1939 * $stderr.puts "In child, pid is #{$$}"
1940 * end
1941 *
1942 * <em>produces:</em>
1943 *
1944 * In child, pid is 26209
1945 * In parent, child pid is 26209
1946 */
1947
1948 static VALUE
1949 rb_io_pid(VALUE io)
1950 {
1951 rb_io_t *fptr;
1952
1953 GetOpenFile(io, fptr);
1954 if (!fptr->pid)
1955 return Qnil;
1956 return PIDT2NUM(fptr->pid);
1957 }
1958
1959
1960 /*
1961 * call-seq:
1962 * ios.inspect -> string
1963 *
1964 * Return a string describing this IO object.
1965 */
1966
1967 static VALUE
1968 rb_io_inspect(VALUE obj)
1969 {
1970 rb_io_t *fptr;
1971 VALUE result;
1972 static const char closed[] = " (closed)";
1973
1974 fptr = RFILE(obj)->fptr;
1975 if (!fptr) return rb_any_to_s(obj);
1976 result = rb_str_new_cstr("#<");
1977 rb_str_append(result, rb_class_name(CLASS_OF(obj)));
1978 rb_str_cat2(result, ":");
1979 if (NIL_P(fptr->pathv)) {
1980 if (fptr->fd < 0) {
1981 rb_str_cat(result, closed+1, strlen(closed)-1);
1982 }
1983 else {
1984 rb_str_catf(result, "fd %d", fptr->fd);
1985 }
1986 }
1987 else {
1988 rb_str_append(result, fptr->pathv);
1989 if (fptr->fd < 0) {
1990 rb_str_cat(result, closed, strlen(closed));
1991 }
1992 }
1993 return rb_str_cat2(result, ">");
1994 }
1995
1996 /*
1997 * call-seq:
1998 * ios.to_io -> ios
1999 *
2000 * Returns <em>ios</em>.
2001 */
2002
2003 static VALUE
2004 rb_io_to_io(VALUE io)
2005 {
2006 return io;
2007 }
2008
2009 /* reading functions */
2010 static long
2011 read_buffered_data(char *ptr, long len, rb_io_t *fptr)
2012 {
2013 int n;
2014
2015 n = READ_DATA_PENDING_COUNT(fptr);
2016 if (n <= 0) return 0;
2017 if (n > len) n = (int)len;
2018 MEMMOVE(ptr, fptr->rbuf.ptr+fptr->rbuf.off, char, n);
2019 fptr->rbuf.off += n;
2020 fptr->rbuf.len -= n;
2021 return n;
2022 }
2023
2024 static long
2025 io_bufread(char *ptr, long len, rb_io_t *fptr)
2026 {
2027 long offset = 0;
2028 long n = len;
2029 long c;
2030
2031 if (READ_DATA_PENDING(fptr) == 0) {
2032 while (n > 0) {
2033 again:
2034 c = rb_read_internal(fptr->fd, ptr+offset, n);
2035 if (c == 0) break;
2036 if (c < 0) {
2037 if (rb_io_wait_readable(fptr->fd))
2038 goto again;
2039 return -1;
2040 }
2041 offset += c;
2042 if ((n -= c) <= 0) break;
2043 }
2044 return len - n;
2045 }
2046
2047 while (n > 0) {
2048 c = read_buffered_data(ptr+offset, n, fptr);
2049 if (c > 0) {
2050 offset += c;
2051 if ((n -= c) <= 0) break;
2052 }
2053 rb_io_check_closed(fptr);
2054 if (io_fillbuf(fptr) < 0) {
2055 break;
2056 }
2057 }
2058 return len - n;
2059 }
2060
2061 static void io_setstrbuf(VALUE *str, long len);
2062
2063 struct bufread_arg {
2064 char *str_ptr;
2065 long len;
2066 rb_io_t *fptr;
2067 };
2068
2069 static VALUE
2070 bufread_call(VALUE arg)
2071 {
2072 struct bufread_arg *p = (struct bufread_arg *)arg;
2073 p->len = io_bufread(p->str_ptr, p->len, p->fptr);
2074 return Qundef;
2075 }
2076
2077 static long
2078 io_fread(VALUE str, long offset, long size, rb_io_t *fptr)
2079 {
2080 long len;
2081 struct bufread_arg arg;
2082
2083 io_setstrbuf(&str, offset + size);
2084 arg.str_ptr = RSTRING_PTR(str) + offset;
2085 arg.len = size;
2086 arg.fptr = fptr;
2087 rb_str_locktmp_ensure(str, bufread_call, (VALUE)&arg);
2088 len = arg.len;
2089 if (len < 0) rb_sys_fail_path(fptr->pathv);
2090 return len;
2091 }
2092
2093 ssize_t
2094 rb_io_bufread(VALUE io, void *buf, size_t size)
2095 {
2096 rb_io_t *fptr;
2097
2098 GetOpenFile(io, fptr);
2099 rb_io_check_readable(fptr);
2100 return (ssize_t)io_bufread(buf, (long)size, fptr);
2101 }
2102
2103 #define SMALLBUF 100
2104
2105 static long
2106 remain_size(rb_io_t *fptr)
2107 {
2108 struct stat st;
2109 off_t siz = READ_DATA_PENDING_COUNT(fptr);
2110 off_t pos;
2111
2112 if (fstat(fptr->fd, &st) == 0 && S_ISREG(st.st_mode)
2113 #if defined(__BEOS__) || defined(__HAIKU__)
2114 && (st.st_dev > 3)
2115 #endif
2116 )
2117 {
2118 if (io_fflush(fptr) < 0)
2119 rb_sys_fail(0);
2120 pos = lseek(fptr->fd, 0, SEEK_CUR);
2121 if (st.st_size >= pos && pos >= 0) {
2122 siz += st.st_size - pos;
2123 if (siz > LONG_MAX) {
2124 rb_raise(rb_eIOError, "file too big for single read");
2125 }
2126 }
2127 }
2128 else {
2129 siz += BUFSIZ;
2130 }
2131 return (long)siz;
2132 }
2133
2134 static VALUE
2135 io_enc_str(VALUE str, rb_io_t *fptr)
2136 {
2137 OBJ_TAINT(str);
2138 rb_enc_associate(str, io_read_encoding(fptr));
2139 return str;
2140 }
2141
2142 static void
2143 make_readconv(rb_io_t *fptr, int size)
2144 {
2145 if (!fptr->readconv) {
2146 int ecflags;
2147 VALUE ecopts;
2148 const char *sname, *dname;
2149 ecflags = fptr->encs.ecflags & ~ECONV_NEWLINE_DECORATOR_WRITE_MASK;
2150 ecopts = fptr->encs.ecopts;
2151 if (fptr->encs.enc2) {
2152 sname = rb_enc_name(fptr->encs.enc2);
2153 dname = rb_enc_name(fptr->encs.enc);
2154 }
2155 else {
2156 sname = dname = "";
2157 }
2158 fptr->readconv = rb_econv_open_opts(sname, dname, ecflags, ecopts);
2159 if (!fptr->readconv)
2160 rb_exc_raise(rb_econv_open_exc(sname, dname, ecflags));
2161 fptr->cbuf.off = 0;
2162 fptr->cbuf.len = 0;
2163 if (size < IO_CBUF_CAPA_MIN) size = IO_CBUF_CAPA_MIN;
2164 fptr->cbuf.capa = size;
2165 fptr->cbuf.ptr = ALLOC_N(char, fptr->cbuf.capa);
2166 }
2167 }
2168
2169 #define MORE_CHAR_SUSPENDED Qtrue
2170 #define MORE_CHAR_FINISHED Qnil
2171 static VALUE
2172 fill_cbuf(rb_io_t *fptr, int ec_flags)
2173 {
2174 const unsigned char *ss, *sp, *se;
2175 unsigned char *ds, *dp, *de;
2176 rb_econv_result_t res;
2177 int putbackable;
2178 int cbuf_len0;
2179 VALUE exc;
2180
2181 ec_flags |= ECONV_PARTIAL_INPUT;
2182
2183 if (fptr->cbuf.len == fptr->cbuf.capa)
2184 return MORE_CHAR_SUSPENDED; /* cbuf full */
2185 if (fptr->cbuf.len == 0)
2186 fptr->cbuf.off = 0;
2187 else if (fptr->cbuf.off + fptr->cbuf.len == fptr->cbuf.capa) {
2188 memmove(fptr->cbuf.ptr, fptr->cbuf.ptr+fptr->cbuf.off, fptr->cbuf.len);
2189 fptr->cbuf.off = 0;
2190 }
2191
2192 cbuf_len0 = fptr->cbuf.len;
2193
2194 while (1) {
2195 ss = sp = (const unsigned char *)fptr->rbuf.ptr + fptr->rbuf.off;
2196 se = sp + fptr->rbuf.len;
2197 ds = dp = (unsigned char *)fptr->cbuf.ptr + fptr->cbuf.off + fptr->cbuf.len;
2198 de = (unsigned char *)fptr->cbuf.ptr + fptr->cbuf.capa;
2199 res = rb_econv_convert(fptr->readconv, &sp, se, &dp, de, ec_flags);
2200 fptr->rbuf.off += (int)(sp - ss);
2201 fptr->rbuf.len -= (int)(sp - ss);
2202 fptr->cbuf.len += (int)(dp - ds);
2203
2204 putbackable = rb_econv_putbackable(fptr->readconv);
2205 if (putbackable) {
2206 rb_econv_putback(fptr->readconv, (unsigned char *)fptr->rbuf.ptr + fptr->rbuf.off - putbackable, putbackable);
2207 fptr->rbuf.off -= putbackable;
2208 fptr->rbuf.len += putbackable;
2209 }
2210
2211 exc = rb_econv_make_exception(fptr->readconv);
2212 if (!NIL_P(exc))
2213 return exc;
2214
2215 if (cbuf_len0 != fptr->cbuf.len)
2216 return MORE_CHAR_SUSPENDED;
2217
2218 if (res == econv_finished) {
2219 return MORE_CHAR_FINISHED;
2220 }
2221
2222 if (res == econv_source_buffer_empty) {
2223 if (fptr->rbuf.len == 0) {
2224 READ_CHECK(fptr);
2225 if (io_fillbuf(fptr) == -1) {
2226 if (!fptr->readconv) {
2227 return MORE_CHAR_FINISHED;
2228 }
2229 ds = dp = (unsigned char *)fptr->cbuf.ptr + fptr->cbuf.off + fptr->cbuf.len;
2230 de = (unsigned char *)fptr->cbuf.ptr + fptr->cbuf.capa;
2231 res = rb_econv_convert(fptr->readconv, NULL, NULL, &dp, de, 0);
2232 fptr->cbuf.len += (int)(dp - ds);
2233 rb_econv_check_error(fptr->readconv);
2234 break;
2235 }
2236 }
2237 }
2238 }
2239 if (cbuf_len0 != fptr->cbuf.len)
2240 return MORE_CHAR_SUSPENDED;
2241
2242 return MORE_CHAR_FINISHED;
2243 }
2244
2245 static VALUE
2246 more_char(rb_io_t *fptr)
2247 {
2248 VALUE v;
2249 v = fill_cbuf(fptr, ECONV_AFTER_OUTPUT);
2250 if (v != MORE_CHAR_SUSPENDED && v != MORE_CHAR_FINISHED)
2251 rb_exc_raise(v);
2252 return v;
2253 }
2254
2255 static VALUE
2256 io_shift_cbuf(rb_io_t *fptr, int len, VALUE *strp)
2257 {
2258 VALUE str = Qnil;
2259 if (strp) {
2260 str = *strp;
2261 if (NIL_P(str)) {
2262 *strp = str = rb_str_new(fptr->cbuf.ptr+fptr->cbuf.off, len);
2263 }
2264 else {
2265 rb_str_cat(str, fptr->cbuf.ptr+fptr->cbuf.off, len);
2266 }
2267 OBJ_TAINT(str);
2268 rb_enc_associate(str, fptr->encs.enc);
2269 }
2270 fptr->cbuf.off += len;
2271 fptr->cbuf.len -= len;
2272 /* xxx: set coderange */
2273 if (fptr->cbuf.len == 0)
2274 fptr->cbuf.off = 0;
2275 else if (fptr->cbuf.capa/2 < fptr->cbuf.off) {
2276 memmove(fptr->cbuf.ptr, fptr->cbuf.ptr+fptr->cbuf.off, fptr->cbuf.len);
2277 fptr->cbuf.off = 0;
2278 }
2279 return str;
2280 }
2281
2282 static void
2283 io_setstrbuf(VALUE *str, long len)
2284 {
2285 #ifdef _WIN32
2286 len = (len + 1) & ~1L; /* round up for wide char */
2287 #endif
2288 if (NIL_P(*str)) {
2289 *str = rb_str_new(0, 0);
2290 }
2291 else {
2292 VALUE s = StringValue(*str);
2293 long clen = RSTRING_LEN(s);
2294 if (clen >= len) {
2295 rb_str_modify(s);
2296 return;
2297 }
2298 len -= clen;
2299 }
2300 rb_str_modify_expand(*str, len);
2301 }
2302
2303 static void
2304 io_set_read_length(VALUE str, long n)
2305 {
2306 if (RSTRING_LEN(str) != n) {
2307 rb_str_modify(str);
2308 rb_str_set_len(str, n);
2309 }
2310 }
2311
2312 static VALUE
2313 read_all(rb_io_t *fptr, long siz, VALUE str)
2314 {
2315 long bytes;
2316 long n;
2317 long pos;
2318 rb_encoding *enc;
2319 int cr;
2320
2321 if (NEED_READCONV(fptr)) {
2322 int first = !NIL_P(str);
2323 SET_BINARY_MODE(fptr);
2324 io_setstrbuf(&str,0);
2325 make_readconv(fptr, 0);
2326 while (1) {
2327 VALUE v;
2328 if (fptr->cbuf.len) {
2329 if (first) rb_str_set_len(str, first = 0);
2330 io_shift_cbuf(fptr, fptr->cbuf.len, &str);
2331 }
2332 v = fill_cbuf(fptr, 0);
2333 if (v != MORE_CHAR_SUSPENDED && v != MORE_CHAR_FINISHED) {
2334 if (fptr->cbuf.len) {
2335 if (first) rb_str_set_len(str, first = 0);
2336 io_shift_cbuf(fptr, fptr->cbuf.len, &str);
2337 }
2338 rb_exc_raise(v);
2339 }
2340 if (v == MORE_CHAR_FINISHED) {
2341 clear_readconv(fptr);
2342 if (first) rb_str_set_len(str, first = 0);
2343 return io_enc_str(str, fptr);
2344 }
2345 }
2346 }
2347
2348 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
2349 bytes = 0;
2350 pos = 0;
2351
2352 enc = io_read_encoding(fptr);
2353 cr = 0;
2354
2355 if (siz == 0) siz = BUFSIZ;
2356 io_setstrbuf(&str,siz);
2357 for (;;) {
2358 READ_CHECK(fptr);
2359 n = io_fread(str, bytes, siz - bytes, fptr);
2360 if (n == 0 && bytes == 0) {
2361 rb_str_set_len(str, 0);
2362 break;
2363 }
2364 bytes += n;
2365 rb_str_set_len(str, bytes);
2366 if (cr != ENC_CODERANGE_BROKEN)
2367 pos += rb_str_coderange_scan_restartable(RSTRING_PTR(str) + pos, RSTRING_PTR(str) + bytes, enc, &cr);
2368 if (bytes < siz) break;
2369 siz += BUFSIZ;
2370 rb_str_modify_expand(str, BUFSIZ);
2371 }
2372 str = io_enc_str(str, fptr);
2373 ENC_CODERANGE_SET(str, cr);
2374 return str;
2375 }
2376
2377 void
2378 rb_io_set_nonblock(rb_io_t *fptr)
2379 {
2380 int oflags;
2381 #ifdef F_GETFL
2382 oflags = fcntl(fptr->fd, F_GETFL);
2383 if (oflags == -1) {
2384 rb_sys_fail_path(fptr->pathv);
2385 }
2386 #else
2387 oflags = 0;
2388 #endif
2389 if ((oflags & O_NONBLOCK) == 0) {
2390 oflags |= O_NONBLOCK;
2391 if (fcntl(fptr->fd, F_SETFL, oflags) == -1) {
2392 rb_sys_fail_path(fptr->pathv);
2393 }
2394 }
2395 }
2396
2397 void
2398 rb_readwrite_sys_fail(int writable, const char *mesg);
2399
2400 struct read_internal_arg {
2401 int fd;
2402 char *str_ptr;
2403 long len;
2404 };
2405
2406 static VALUE
2407 read_internal_call(VALUE arg)
2408 {
2409 struct read_internal_arg *p = (struct read_internal_arg *)arg;
2410 p->len = rb_read_internal(p->fd, p->str_ptr, p->len);
2411 return Qundef;
2412 }
2413
2414 static VALUE
2415 io_getpartial(int argc, VALUE *argv, VALUE io, int nonblock, int no_exception)
2416 {
2417 rb_io_t *fptr;
2418 VALUE length, str;
2419 long n, len;
2420 struct read_internal_arg arg;
2421
2422 rb_scan_args(argc, argv, "11:", &length, &str, NULL);
2423
2424 if ((len = NUM2LONG(length)) < 0) {
2425 rb_raise(rb_eArgError, "negative length %ld given", len);
2426 }
2427
2428 io_setstrbuf(&str,len);
2429 OBJ_TAINT(str);
2430
2431 GetOpenFile(io, fptr);
2432 rb_io_check_byte_readable(fptr);
2433
2434 if (len == 0)
2435 return str;
2436
2437 if (!nonblock)
2438 READ_CHECK(fptr);
2439 n = read_buffered_data(RSTRING_PTR(str), len, fptr);
2440 if (n <= 0) {
2441 again:
2442 if (nonblock) {
2443 rb_io_set_nonblock(fptr);
2444 }
2445 io_setstrbuf(&str, len);
2446 arg.fd = fptr->fd;
2447 arg.str_ptr = RSTRING_PTR(str);
2448 arg.len = len;
2449 rb_str_locktmp_ensure(str, read_internal_call, (VALUE)&arg);
2450 n = arg.len;
2451 if (n < 0) {
2452 if (!nonblock && rb_io_wait_readable(fptr->fd))
2453 goto again;
2454 if (nonblock && (errno == EWOULDBLOCK || errno == EAGAIN)) {
2455 if (no_exception)
2456 return ID2SYM(rb_intern("wait_readable"));
2457 else
2458 rb_readwrite_sys_fail(RB_IO_WAIT_READABLE, "read would block");
2459 }
2460 rb_sys_fail_path(fptr->pathv);
2461 }
2462 }
2463 io_set_read_length(str, n);
2464
2465 if (n == 0)
2466 return Qnil;
2467 else
2468 return str;
2469 }
2470
2471 /*
2472 * call-seq:
2473 * ios.readpartial(maxlen) -> string
2474 * ios.readpartial(maxlen, outbuf) -> outbuf
2475 *
2476 * Reads at most <i>maxlen</i> bytes from the I/O stream.
2477 * It blocks only if <em>ios</em> has no data immediately available.
2478 * It doesn't block if some data available.
2479 * If the optional <i>outbuf</i> argument is present,
2480 * it must reference a String, which will receive the data.
2481 * The <i>outbuf</i> will contain only the received data after the method call
2482 * even if it is not empty at the beginning.
2483 * It raises <code>EOFError</code> on end of file.
2484 *
2485 * readpartial is designed for streams such as pipe, socket, tty, etc.
2486 * It blocks only when no data immediately available.
2487 * This means that it blocks only when following all conditions hold.
2488 * * the byte buffer in the IO object is empty.
2489 * * the content of the stream is empty.
2490 * * the stream is not reached to EOF.
2491 *
2492 * When readpartial blocks, it waits data or EOF on the stream.
2493 * If some data is reached, readpartial returns with the data.
2494 * If EOF is reached, readpartial raises EOFError.
2495 *
2496 * When readpartial doesn't blocks, it returns or raises immediately.
2497 * If the byte buffer is not empty, it returns the data in the buffer.
2498 * Otherwise if the stream has some content,
2499 * it returns the data in the stream.
2500 * Otherwise if the stream is reached to EOF, it raises EOFError.
2501 *
2502 * r, w = IO.pipe # buffer pipe content
2503 * w << "abc" # "" "abc".
2504 * r.readpartial(4096) #=> "abc" "" ""
2505 * r.readpartial(4096) # blocks because buffer and pipe is empty.
2506 *
2507 * r, w = IO.pipe # buffer pipe content
2508 * w << "abc" # "" "abc"
2509 * w.close # "" "abc" EOF
2510 * r.readpartial(4096) #=> "abc" "" EOF
2511 * r.readpartial(4096) # raises EOFError
2512 *
2513 * r, w = IO.pipe # buffer pipe content
2514 * w << "abc\ndef\n" # "" "abc\ndef\n"
2515 * r.gets #=> "abc\n" "def\n" ""
2516 * w << "ghi\n" # "def\n" "ghi\n"
2517 * r.readpartial(4096) #=> "def\n" "" "ghi\n"
2518 * r.readpartial(4096) #=> "ghi\n" "" ""
2519 *
2520 * Note that readpartial behaves similar to sysread.
2521 * The differences are:
2522 * * If the byte buffer is not empty, read from the byte buffer instead of "sysread for buffered IO (IOError)".
2523 * * It doesn't cause Errno::EWOULDBLOCK and Errno::EINTR. When readpartial meets EWOULDBLOCK and EINTR by read system call, readpartial retry the system call.
2524 *
2525 * The later means that readpartial is nonblocking-flag insensitive.
2526 * It blocks on the situation IO#sysread causes Errno::EWOULDBLOCK as if the fd is blocking mode.
2527 *
2528 */
2529
2530 static VALUE
2531 io_readpartial(int argc, VALUE *argv, VALUE io)
2532 {
2533 VALUE ret;
2534
2535 ret = io_getpartial(argc, argv, io, 0, 0);
2536 if (NIL_P(ret))
2537 rb_eof_error();
2538 return ret;
2539 }
2540
2541 /*
2542 * call-seq:
2543 * ios.read_nonblock(maxlen) -> string
2544 * ios.read_nonblock(maxlen, outbuf) -> outbuf
2545 *
2546 * Reads at most <i>maxlen</i> bytes from <em>ios</em> using
2547 * the read(2) system call after O_NONBLOCK is set for
2548 * the underlying file descriptor.
2549 *
2550 * If the optional <i>outbuf</i> argument is present,
2551 * it must reference a String, which will receive the data.
2552 * The <i>outbuf</i> will contain only the received data after the method call
2553 * even if it is not empty at the beginning.
2554 *
2555 * read_nonblock just calls the read(2) system call.
2556 * It causes all errors the read(2) system call causes: Errno::EWOULDBLOCK, Errno::EINTR, etc.
2557 * The caller should care such errors.
2558 *
2559 * If the exception is Errno::EWOULDBLOCK or Errno::AGAIN,
2560 * it is extended by IO::WaitReadable.
2561 * So IO::WaitReadable can be used to rescue the exceptions for retrying read_nonblock.
2562 *
2563 * read_nonblock causes EOFError on EOF.
2564 *
2565 * If the read byte buffer is not empty,
2566 * read_nonblock reads from the buffer like readpartial.
2567 * In this case, the read(2) system call is not called.
2568 *
2569 * When read_nonblock raises an exception kind of IO::WaitReadable,
2570 * read_nonblock should not be called
2571 * until io is readable for avoiding busy loop.
2572 * This can be done as follows.
2573 *
2574 * # emulates blocking read (readpartial).
2575 * begin
2576 * result = io.read_nonblock(maxlen)
2577 * rescue IO::WaitReadable
2578 * IO.select([io])
2579 * retry
2580 * end
2581 *
2582 * Although IO#read_nonblock doesn't raise IO::WaitWritable.
2583 * OpenSSL::Buffering#read_nonblock can raise IO::WaitWritable.
2584 * If IO and SSL should be used polymorphically,
2585 * IO::WaitWritable should be rescued too.
2586 * See the document of OpenSSL::Buffering#read_nonblock for sample code.
2587 *
2588 * Note that this method is identical to readpartial
2589 * except the non-blocking flag is set.
2590 */
2591
2592 static VALUE
2593 io_read_nonblock(int argc, VALUE *argv, VALUE io)
2594 {
2595 VALUE ret;
2596 VALUE opts = Qnil;
2597 int no_exception = 0;
2598
2599 rb_scan_args(argc, argv, "11:", NULL, NULL, &opts);
2600
2601 if (!NIL_P(opts) && Qfalse == rb_hash_aref(opts, sym_exception))
2602 no_exception = 1;
2603
2604 ret = io_getpartial(argc, argv, io, 1, no_exception);
2605
2606 if (NIL_P(ret)) {
2607 if (no_exception)
2608 return Qnil;
2609 else
2610 rb_eof_error();
2611 }
2612 return ret;
2613 }
2614
2615 static VALUE
2616 io_write_nonblock(VALUE io, VALUE str, int no_exception)
2617 {
2618 rb_io_t *fptr;
2619 long n;
2620
2621 if (!RB_TYPE_P(str, T_STRING))
2622 str = rb_obj_as_string(str);
2623
2624 io = GetWriteIO(io);
2625 GetOpenFile(io, fptr);
2626 rb_io_check_writable(fptr);
2627
2628 if (io_fflush(fptr) < 0)
2629 rb_sys_fail(0);
2630
2631 rb_io_set_nonblock(fptr);
2632 n = write(fptr->fd, RSTRING_PTR(str), RSTRING_LEN(str));
2633
2634 if (n == -1) {
2635 if (errno == EWOULDBLOCK || errno == EAGAIN) {
2636 if (no_exception) {
2637 return ID2SYM(rb_intern("wait_writable"));
2638 } else {
2639 rb_readwrite_sys_fail(RB_IO_WAIT_WRITABLE, "write would block");
2640 }
2641 }
2642 rb_sys_fail_path(fptr->pathv);
2643 }
2644
2645 return LONG2FIX(n);
2646 }
2647
2648 /*
2649 * call-seq:
2650 * ios.write_nonblock(string) -> integer
2651 * ios.write_nonblock(string [, options]) -> integer
2652 *
2653 * Writes the given string to <em>ios</em> using
2654 * the write(2) system call after O_NONBLOCK is set for
2655 * the underlying file descriptor.
2656 *
2657 * It returns the number of bytes written.
2658 *
2659 * write_nonblock just calls the write(2) system call.
2660 * It causes all errors the write(2) system call causes: Errno::EWOULDBLOCK, Errno::EINTR, etc.
2661 * The result may also be smaller than string.length (partial write).
2662 * The caller should care such errors and partial write.
2663 *
2664 * If the exception is Errno::EWOULDBLOCK or Errno::AGAIN,
2665 * it is extended by IO::WaitWritable.
2666 * So IO::WaitWritable can be used to rescue the exceptions for retrying write_nonblock.
2667 *
2668 * # Creates a pipe.
2669 * r, w = IO.pipe
2670 *
2671 * # write_nonblock writes only 65536 bytes and return 65536.
2672 * # (The pipe size is 65536 bytes on this environment.)
2673 * s = "a" * 100000
2674 * p w.write_nonblock(s) #=> 65536
2675 *
2676 * # write_nonblock cannot write a byte and raise EWOULDBLOCK (EAGAIN).
2677 * p w.write_nonblock("b") # Resource temporarily unavailable (Errno::EAGAIN)
2678 *
2679 * If the write buffer is not empty, it is flushed at first.
2680 *
2681 * When write_nonblock raises an exception kind of IO::WaitWritable,
2682 * write_nonblock should not be called
2683 * until io is writable for avoiding busy loop.
2684 * This can be done as follows.
2685 *
2686 * begin
2687 * result = io.write_nonblock(string)
2688 * rescue IO::WaitWritable, Errno::EINTR
2689 * IO.select(nil, [io])
2690 * retry
2691 * end
2692 *
2693 * Note that this doesn't guarantee to write all data in string.
2694 * The length written is reported as result and it should be checked later.
2695 *
2696 * On some platforms such as Windows, write_nonblock is not supported
2697 * according to the kind of the IO object.
2698 * In such cases, write_nonblock raises <code>Errno::EBADF</code>.
2699 *
2700 * By specifying `exception: false`, the options hash allows you to indicate
2701 * that write_nonblock should not raise an IO::WaitWritable exception, but
2702 * return the symbol :wait_writable instead.
2703 *
2704 */
2705
2706 static VALUE
2707 rb_io_write_nonblock(int argc, VALUE *argv, VALUE io)
2708 {
2709 VALUE str;
2710 VALUE opts = Qnil;
2711 int no_exceptions = 0;
2712
2713 rb_scan_args(argc, argv, "10:", &str, &opts);
2714
2715 if (!NIL_P(opts) && Qfalse == rb_hash_aref(opts, sym_exception))
2716 no_exceptions = 1;
2717
2718 return io_write_nonblock(io, str, no_exceptions);
2719 }
2720
2721 /*
2722 * call-seq:
2723 * ios.read([length [, outbuf]]) -> string, outbuf, or nil
2724 *
2725 * Reads <i>length</i> bytes from the I/O stream.
2726 *
2727 * <i>length</i> must be a non-negative integer or <code>nil</code>.
2728 *
2729 * If <i>length</i> is a positive integer,
2730 * it try to read <i>length</i> bytes without any conversion (binary mode).
2731 * It returns <code>nil</code> or a string whose length is 1 to <i>length</i> bytes.
2732 * <code>nil</code> means it met EOF at beginning.
2733 * The 1 to <i>length</i>-1 bytes string means it met EOF after reading the result.
2734 * The <i>length</i> bytes string means it doesn't meet EOF.
2735 * The resulted string is always ASCII-8BIT encoding.
2736 *
2737 * If <i>length</i> is omitted or is <code>nil</code>,
2738 * it reads until EOF and the encoding conversion is applied.
2739 * It returns a string even if EOF is met at beginning.
2740 *
2741 * If <i>length</i> is zero, it returns <code>""</code>.
2742 *
2743 * If the optional <i>outbuf</i> argument is present, it must reference
2744 * a String, which will receive the data.
2745 * The <i>outbuf</i> will contain only the received data after the method call
2746 * even if it is not empty at the beginning.
2747 *
2748 * At end of file, it returns <code>nil</code> or <code>""</code>
2749 * depend on <i>length</i>.
2750 * <code><i>ios</i>.read()</code> and
2751 * <code><i>ios</i>.read(nil)</code> returns <code>""</code>.
2752 * <code><i>ios</i>.read(<i>positive-integer</i>)</code> returns <code>nil</code>.
2753 *
2754 * f = File.new("testfile")
2755 * f.read(16) #=> "This is line one"
2756 *
2757 * # reads whole file
2758 * open("file") {|f|
2759 * data = f.read # This returns a string even if the file is empty.
2760 * ...
2761 * }
2762 *
2763 * # iterate over fixed length records.
2764 * open("fixed-record-file") {|f|
2765 * while record = f.read(256)
2766 * ...
2767 * end
2768 * }
2769 *
2770 * # iterate over variable length records.
2771 * # record is prefixed by 32-bit length.
2772 * open("variable-record-file") {|f|
2773 * while len = f.read(4)
2774 * len = len.unpack("N")[0] # 32-bit length
2775 * record = f.read(len) # This returns a string even if len is 0.
2776 * end
2777 * }
2778 *
2779 * Note that this method behaves like fread() function in C.
2780 * This means it retry to invoke read(2) system call to read data with the specified length (or until EOF).
2781 * This behavior is preserved even if <i>ios</i> is non-blocking mode.
2782 * (This method is non-blocking flag insensitive as other methods.)
2783 * If you need the behavior like single read(2) system call,
2784 * consider readpartial, read_nonblock and sysread.
2785 */
2786
2787 static VALUE
2788 io_read(int argc, VALUE *argv, VALUE io)
2789 {
2790 rb_io_t *fptr;
2791 long n, len;
2792 VALUE length, str;
2793 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
2794 int previous_mode;
2795 #endif
2796
2797 rb_scan_args(argc, argv, "02", &length, &str);
2798
2799 if (NIL_P(length)) {
2800 GetOpenFile(io, fptr);
2801 rb_io_check_char_readable(fptr);
2802 return read_all(fptr, remain_size(fptr), str);
2803 }
2804 len = NUM2LONG(length);
2805 if (len < 0) {
2806 rb_raise(rb_eArgError, "negative length %ld given", len);
2807 }
2808
2809 io_setstrbuf(&str,len);
2810
2811 GetOpenFile(io, fptr);
2812 rb_io_check_byte_readable(fptr);
2813 if (len == 0) {
2814 io_set_read_length(str, 0);
2815 return str;
2816 }
2817
2818 READ_CHECK(fptr);
2819 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
2820 previous_mode = set_binary_mode_with_seek_cur(fptr);
2821 #endif
2822 n = io_fread(str, 0, len, fptr);
2823 io_set_read_length(str, n);
2824 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
2825 if (previous_mode == O_TEXT) {
2826 setmode(fptr->fd, O_TEXT);
2827 }
2828 #endif
2829 if (n == 0) return Qnil;
2830 OBJ_TAINT(str);
2831
2832 return str;
2833 }
2834
2835 static void
2836 rscheck(const char *rsptr, long rslen, VALUE rs)
2837 {
2838 if (!rs) return;
2839 if (RSTRING_PTR(rs) != rsptr && RSTRING_LEN(rs) != rslen)
2840 rb_raise(rb_eRuntimeError, "rs modified");
2841 }
2842
2843 static int
2844 appendline(rb_io_t *fptr, int delim, VALUE *strp, long *lp)
2845 {
2846 VALUE str = *strp;
2847 long limit = *lp;
2848
2849 if (NEED_READCONV(fptr)) {
2850 SET_BINARY_MODE(fptr);
2851 make_readconv(fptr, 0);
2852 do {
2853 const char *p, *e;
2854 int searchlen = READ_CHAR_PENDING_COUNT(fptr);
2855 if (searchlen) {
2856 p = READ_CHAR_PENDING_PTR(fptr);
2857 if (0 < limit && limit < searchlen)
2858 searchlen = (int)limit;
2859 e = memchr(p, delim, searchlen);
2860 if (e) {
2861 int len = (int)(e-p+1);
2862 if (NIL_P(str))
2863 *strp = str = rb_str_new(p, len);
2864 else
2865 rb_str_buf_cat(str, p, len);
2866 fptr->cbuf.off += len;
2867 fptr->cbuf.len -= len;
2868 limit -= len;
2869 *lp = limit;
2870 return delim;
2871 }
2872
2873 if (NIL_P(str))
2874 *strp = str = rb_str_new(p, searchlen);
2875 else
2876 rb_str_buf_cat(str, p, searchlen);
2877 fptr->cbuf.off += searchlen;
2878 fptr->cbuf.len -= searchlen;
2879 limit -= searchlen;
2880
2881 if (limit == 0) {
2882 *lp = limit;
2883 return (unsigned char)RSTRING_PTR(str)[RSTRING_LEN(str)-1];
2884 }
2885 }
2886 } while (more_char(fptr) != MORE_CHAR_FINISHED);
2887 clear_readconv(fptr);
2888 *lp = limit;
2889 return EOF;
2890 }
2891
2892 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
2893 do {
2894 long pending = READ_DATA_PENDING_COUNT(fptr);
2895 if (pending > 0) {
2896 const char *p = READ_DATA_PENDING_PTR(fptr);
2897 const char *e;
2898 long last;
2899
2900 if (limit > 0 && pending > limit) pending = limit;
2901 e = memchr(p, delim, pending);
2902 if (e) pending = e - p + 1;
2903 if (!NIL_P(str)) {
2904 last = RSTRING_LEN(str);
2905 rb_str_resize(str, last + pending);
2906 }
2907 else {
2908 last = 0;
2909 *strp = str = rb_str_buf_new(pending);
2910 rb_str_set_len(str, pending);
2911 }
2912 read_buffered_data(RSTRING_PTR(str) + last, pending, fptr); /* must not fail */
2913 limit -= pending;
2914 *lp = limit;
2915 if (e) return delim;
2916 if (limit == 0)
2917 return (unsigned char)RSTRING_PTR(str)[RSTRING_LEN(str)-1];
2918 }
2919 READ_CHECK(fptr);
2920 } while (io_fillbuf(fptr) >= 0);
2921 *lp = limit;
2922 return EOF;
2923 }
2924
2925 static inline int
2926 swallow(rb_io_t *fptr, int term)
2927 {
2928 if (NEED_READCONV(fptr)) {
2929 rb_encoding *enc = io_read_encoding(fptr);
2930 int needconv = rb_enc_mbminlen(enc) != 1;
2931 SET_BINARY_MODE(fptr);
2932 make_readconv(fptr, 0);
2933 do {
2934 size_t cnt;
2935 while ((cnt = READ_CHAR_PENDING_COUNT(fptr)) > 0) {
2936 const char *p = READ_CHAR_PENDING_PTR(fptr);
2937 int i;
2938 if (!needconv) {
2939 if (*p != term) return TRUE;
2940 i = (int)cnt;
2941 while (--i && *++p == term);
2942 }
2943 else {
2944 const char *e = p + cnt;
2945 if (rb_enc_ascget(p, e, &i, enc) != term) return TRUE;
2946 while ((p += i) < e && rb_enc_ascget(p, e, &i, enc) == term);
2947 i = (int)(e - p);
2948 }
2949 io_shift_cbuf(fptr, (int)cnt - i, NULL);
2950 }
2951 } while (more_char(fptr) != MORE_CHAR_FINISHED);
2952 return FALSE;
2953 }
2954
2955 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
2956 do {
2957 size_t cnt;
2958 while ((cnt = READ_DATA_PENDING_COUNT(fptr)) > 0) {
2959 char buf[1024];
2960 const char *p = READ_DATA_PENDING_PTR(fptr);
2961 int i;
2962 if (cnt > sizeof buf) cnt = sizeof buf;
2963 if (*p != term) return TRUE;
2964 i = (int)cnt;
2965 while (--i && *++p == term);
2966 if (!read_buffered_data(buf, cnt - i, fptr)) /* must not fail */
2967 rb_sys_fail_path(fptr->pathv);
2968 }
2969 READ_CHECK(fptr);
2970 } while (io_fillbuf(fptr) == 0);
2971 return FALSE;
2972 }
2973
2974 static VALUE
2975 rb_io_getline_fast(rb_io_t *fptr, rb_encoding *enc, VALUE io)
2976 {
2977 VALUE str = Qnil;
2978 int len = 0;
2979 long pos = 0;
2980 int cr = 0;
2981
2982 do {
2983 int pending = READ_DATA_PENDING_COUNT(fptr);
2984
2985 if (pending > 0) {
2986 const char *p = READ_DATA_PENDING_PTR(fptr);
2987 const char *e;
2988
2989 e = memchr(p, '\n', pending);
2990 if (e) {
2991 pending = (int)(e - p + 1);
2992 }
2993 if (NIL_P(str)) {
2994 str = rb_str_new(p, pending);
2995 fptr->rbuf.off += pending;
2996 fptr->rbuf.len -= pending;
2997 }
2998 else {
2999 rb_str_resize(str, len + pending);
3000 read_buffered_data(RSTRING_PTR(str)+len, pending, fptr);
3001 }
3002 len += pending;
3003 if (cr != ENC_CODERANGE_BROKEN)
3004 pos += rb_str_coderange_scan_restartable(RSTRING_PTR(str) + pos, RSTRING_PTR(str) + len, enc, &cr);
3005 if (e) break;
3006 }
3007 READ_CHECK(fptr);
3008 } while (io_fillbuf(fptr) >= 0);
3009 if (NIL_P(str)) return Qnil;
3010
3011 str = io_enc_str(str, fptr);
3012 ENC_CODERANGE_SET(str, cr);
3013 fptr->lineno++;
3014 if (io == ARGF.current_file) {
3015 ARGF.lineno++;
3016 ARGF.last_lineno = ARGF.lineno;
3017 }
3018 else {
3019 ARGF.last_lineno = fptr->lineno;
3020 }
3021
3022 return str;
3023 }
3024
3025 static void
3026 prepare_getline_args(int argc, VALUE *argv, VALUE *rsp, long *limit, VALUE io)
3027 {
3028 VALUE rs = rb_rs, lim = Qnil;
3029 rb_io_t *fptr;
3030
3031 if (argc == 1) {
3032 VALUE tmp = Qnil;
3033
3034 if (NIL_P(argv[0]) || !NIL_P(tmp = rb_check_string_type(argv[0]))) {
3035 rs = tmp;
3036 }
3037 else {
3038 lim = argv[0];
3039 }
3040 }
3041 else if (2 <= argc) {
3042 rb_scan_args(argc, argv, "2", &rs, &lim);
3043 if (!NIL_P(rs))
3044 StringValue(rs);
3045 }
3046 if (!NIL_P(rs)) {
3047 rb_encoding *enc_rs, *enc_io;
3048
3049 GetOpenFile(io, fptr);
3050 enc_rs = rb_enc_get(rs);
3051 enc_io = io_read_encoding(fptr);
3052 if (enc_io != enc_rs &&
3053 (rb_enc_str_coderange(rs) != ENC_CODERANGE_7BIT ||
3054 (RSTRING_LEN(rs) > 0 && !rb_enc_asciicompat(enc_io)))) {
3055 if (rs == rb_default_rs) {
3056 rs = rb_enc_str_new(0, 0, enc_io);
3057 rb_str_buf_cat_ascii(rs, "\n");
3058 }
3059 else {
3060 rb_raise(rb_eArgError, "encoding mismatch: %s IO with %s RS",
3061 rb_enc_name(enc_io),
3062 rb_enc_name(enc_rs));
3063 }
3064 }
3065 }
3066 *rsp = rs;
3067 *limit = NIL_P(lim) ? -1L : NUM2LONG(lim);
3068 }
3069
3070 static VALUE
3071 rb_io_getline_1(VALUE rs, long limit, VALUE io)
3072 {
3073 VALUE str = Qnil;
3074 rb_io_t *fptr;
3075 int nolimit = 0;
3076 rb_encoding *enc;
3077
3078 GetOpenFile(io, fptr);
3079 rb_io_check_char_readable(fptr);
3080 if (NIL_P(rs) && limit < 0) {
3081 str = read_all(fptr, 0, Qnil);
3082 if (RSTRING_LEN(str) == 0) return Qnil;
3083 }
3084 else if (limit == 0) {
3085 return rb_enc_str_new(0, 0, io_read_encoding(fptr));
3086 }
3087 else if (rs == rb_default_rs && limit < 0 && !NEED_READCONV(fptr) &&
3088 rb_enc_asciicompat(enc = io_read_encoding(fptr))) {
3089 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
3090 return rb_io_getline_fast(fptr, enc, io);
3091 }
3092 else {
3093 int c, newline = -1;
3094 const char *rsptr = 0;
3095 long rslen = 0;
3096 int rspara = 0;
3097 int extra_limit = 16;
3098
3099 SET_BINARY_MODE(fptr);
3100 enc = io_read_encoding(fptr);
3101
3102 if (!NIL_P(rs)) {
3103 rslen = RSTRING_LEN(rs);
3104 if (rslen == 0) {
3105 rsptr = "\n\n";
3106 rslen = 2;
3107 rspara = 1;
3108 swallow(fptr, '\n');
3109 rs = 0;
3110 if (!rb_enc_asciicompat(enc)) {
3111 rs = rb_usascii_str_new(rsptr, rslen);
3112 rs = rb_str_encode(rs, rb_enc_from_encoding(enc), 0, Qnil);
3113 OBJ_FREEZE(rs);
3114 rsptr = RSTRING_PTR(rs);
3115 rslen = RSTRING_LEN(rs);
3116 }
3117 }
3118 else {
3119 rsptr = RSTRING_PTR(rs);
3120 }
3121 newline = (unsigned char)rsptr[rslen - 1];
3122 }
3123
3124 /* MS - Optimisation */
3125 while ((c = appendline(fptr, newline, &str, &limit)) != EOF) {
3126 const char *s, *p, *pp, *e;
3127
3128 if (c == newline) {
3129 if (RSTRING_LEN(str) < rslen) continue;
3130 s = RSTRING_PTR(str);
3131 e = RSTRING_END(str);
3132 p = e - rslen;
3133 pp = rb_enc_left_char_head(s, p, e, enc);
3134 if (pp != p) continue;
3135 if (!rspara) rscheck(rsptr, rslen, rs);
3136 if (memcmp(p, rsptr, rslen) == 0) break;
3137 }
3138 if (limit == 0) {
3139 s = RSTRING_PTR(str);
3140 p = RSTRING_END(str);
3141 pp = rb_enc_left_char_head(s, p-1, p, enc);
3142 if (extra_limit &&
3143 MBCLEN_NEEDMORE_P(rb_enc_precise_mbclen(pp, p, enc))) {
3144 /* relax the limit while incomplete character.
3145 * extra_limit limits the relax length */
3146 limit = 1;
3147 extra_limit--;
3148 }
3149 else {
3150 nolimit = 1;
3151 break;
3152 }
3153 }
3154 }
3155
3156 if (rspara && c != EOF)
3157 swallow(fptr, '\n');
3158 if (!NIL_P(str))
3159 str = io_enc_str(str, fptr);
3160 }
3161
3162 if (!NIL_P(str) && !nolimit) {
3163 fptr->lineno++;
3164 if (io == ARGF.current_file) {
3165 ARGF.lineno++;
3166 ARGF.last_lineno = ARGF.lineno;
3167 }
3168 else {
3169 ARGF.last_lineno = fptr->lineno;
3170 }
3171 }
3172
3173 return str;
3174 }
3175
3176 static VALUE
3177 rb_io_getline(int argc, VALUE *argv, VALUE io)
3178 {
3179 VALUE rs;
3180 long limit;
3181
3182 prepare_getline_args(argc, argv, &rs, &limit, io);
3183 return rb_io_getline_1(rs, limit, io);
3184 }
3185
3186 VALUE
3187 rb_io_gets(VALUE io)
3188 {
3189 return rb_io_getline_1(rb_default_rs, -1, io);
3190 }
3191
3192 /*
3193 * call-seq:
3194 * ios.gets(sep=$/) -> string or nil
3195 * ios.gets(limit) -> string or nil
3196 * ios.gets(sep, limit) -> string or nil
3197 *
3198 * Reads the next ``line'' from the I/O stream; lines are separated by
3199 * <i>sep</i>. A separator of <code>nil</code> reads the entire
3200 * contents, and a zero-length separator reads the input a paragraph at
3201 * a time (two successive newlines in the input separate paragraphs).
3202 * The stream must be opened for reading or an <code>IOError</code>
3203 * will be raised. The line read in will be returned and also assigned
3204 * to <code>$_</code>. Returns <code>nil</code> if called at end of
3205 * file. If the first argument is an integer, or optional second
3206 * argument is given, the returning string would not be longer than the
3207 * given value in bytes.
3208 *
3209 * File.new("testfile").gets #=> "This is line one\n"
3210 * $_ #=> "This is line one\n"
3211 */
3212
3213 static VALUE
3214 rb_io_gets_m(int argc, VALUE *argv, VALUE io)
3215 {
3216 VALUE str;
3217
3218 str = rb_io_getline(argc, argv, io);
3219 rb_lastline_set(str);
3220
3221 return str;
3222 }
3223
3224 /*
3225 * call-seq:
3226 * ios.lineno -> integer
3227 *
3228 * Returns the current line number in <em>ios</em>. The stream must be
3229 * opened for reading. <code>lineno</code> counts the number of times
3230 * #gets is called rather than the number of newlines encountered. The two
3231 * values will differ if #gets is called with a separator other than newline.
3232 *
3233 * Methods that use <code>$/</code> like #each, #lines and #readline will
3234 * also increment <code>lineno</code>.
3235 *
3236 * See also the <code>$.</code> variable.
3237 *
3238 * f = File.new("testfile")
3239 * f.lineno #=> 0
3240 * f.gets #=> "This is line one\n"
3241 * f.lineno #=> 1
3242 * f.gets #=> "This is line two\n"
3243 * f.lineno #=> 2
3244 */
3245
3246 static VALUE
3247 rb_io_lineno(VALUE io)
3248 {
3249 rb_io_t *fptr;
3250
3251 GetOpenFile(io, fptr);
3252 rb_io_check_char_readable(fptr);
3253 return INT2NUM(fptr->lineno);
3254 }
3255
3256 /*
3257 * call-seq:
3258 * ios.lineno = integer -> integer
3259 *
3260 * Manually sets the current line number to the given value.
3261 * <code>$.</code> is updated only on the next read.
3262 *
3263 * f = File.new("testfile")
3264 * f.gets #=> "This is line one\n"
3265 * $. #=> 1
3266 * f.lineno = 1000
3267 * f.lineno #=> 1000
3268 * $. #=> 1 # lineno of last read
3269 * f.gets #=> "This is line two\n"
3270 * $. #=> 1001 # lineno of last read
3271 */
3272
3273 static VALUE
3274 rb_io_set_lineno(VALUE io, VALUE lineno)
3275 {
3276 rb_io_t *fptr;
3277
3278 GetOpenFile(io, fptr);
3279 rb_io_check_char_readable(fptr);
3280 fptr->lineno = NUM2INT(lineno);
3281 return lineno;
3282 }
3283
3284 /*
3285 * call-seq:
3286 * ios.readline(sep=$/) -> string
3287 * ios.readline(limit) -> string
3288 * ios.readline(sep, limit) -> string
3289 *
3290 * Reads a line as with <code>IO#gets</code>, but raises an
3291 * <code>EOFError</code> on end of file.
3292 */
3293
3294 static VALUE
3295 rb_io_readline(int argc, VALUE *argv, VALUE io)
3296 {
3297 VALUE line = rb_io_gets_m(argc, argv, io);
3298
3299 if (NIL_P(line)) {
3300 rb_eof_error();
3301 }
3302 return line;
3303 }
3304
3305 /*
3306 * call-seq:
3307 * ios.readlines(sep=$/) -> array
3308 * ios.readlines(limit) -> array
3309 * ios.readlines(sep, limit) -> array
3310 *
3311 * Reads all of the lines in <em>ios</em>, and returns them in
3312 * <i>anArray</i>. Lines are separated by the optional <i>sep</i>. If
3313 * <i>sep</i> is <code>nil</code>, the rest of the stream is returned
3314 * as a single record. If the first argument is an integer, or
3315 * optional second argument is given, the returning string would not be
3316 * longer than the given value in bytes. The stream must be opened for
3317 * reading or an <code>IOError</code> will be raised.
3318 *
3319 * f = File.new("testfile")
3320 * f.readlines[0] #=> "This is line one\n"
3321 */
3322
3323 static VALUE
3324 rb_io_readlines(int argc, VALUE *argv, VALUE io)
3325 {
3326 VALUE line, ary, rs;
3327 long limit;
3328
3329 prepare_getline_args(argc, argv, &rs, &limit, io);
3330 if (limit == 0)
3331 rb_raise(rb_eArgError, "invalid limit: 0 for readlines");
3332 ary = rb_ary_new();
3333 while (!NIL_P(line = rb_io_getline_1(rs, limit, io))) {
3334 rb_ary_push(ary, line);
3335 }
3336 return ary;
3337 }
3338
3339 /*
3340 * call-seq:
3341 * ios.each(sep=$/) {|line| block } -> ios
3342 * ios.each(limit) {|line| block } -> ios
3343 * ios.each(sep,limit) {|line| block } -> ios
3344 * ios.each(...) -> an_enumerator
3345 *
3346 * ios.each_line(sep=$/) {|line| block } -> ios
3347 * ios.each_line(limit) {|line| block } -> ios
3348 * ios.each_line(sep,limit) {|line| block } -> ios
3349 * ios.each_line(...) -> an_enumerator
3350 *
3351 * Executes the block for every line in <em>ios</em>, where lines are
3352 * separated by <i>sep</i>. <em>ios</em> must be opened for
3353 * reading or an <code>IOError</code> will be raised.
3354 *
3355 * If no block is given, an enumerator is returned instead.
3356 *
3357 * f = File.new("testfile")
3358 * f.each {|line| puts "#{f.lineno}: #{line}" }
3359 *
3360 * <em>produces:</em>
3361 *
3362 * 1: This is line one
3363 * 2: This is line two
3364 * 3: This is line three
3365 * 4: And so on...
3366 */
3367
3368 static VALUE
3369 rb_io_each_line(int argc, VALUE *argv, VALUE io)
3370 {
3371 VALUE str, rs;
3372 long limit;
3373
3374 RETURN_ENUMERATOR(io, argc, argv);
3375 prepare_getline_args(argc, argv, &rs, &limit, io);
3376 if (limit == 0)
3377 rb_raise(rb_eArgError, "invalid limit: 0 for each_line");
3378 while (!NIL_P(str = rb_io_getline_1(rs, limit, io))) {
3379 rb_yield(str);
3380 }
3381 return io;
3382 }
3383
3384 /*
3385 * This is a deprecated alias for <code>each_line</code>.
3386 */
3387
3388 static VALUE
3389 rb_io_lines(int argc, VALUE *argv, VALUE io)
3390 {
3391 rb_warn("IO#lines is deprecated; use #each_line instead");
3392 if (!rb_block_given_p())
3393 return rb_enumeratorize(io, ID2SYM(rb_intern("each_line")), argc, argv);
3394 return rb_io_each_line(argc, argv, io);
3395 }
3396
3397 /*
3398 * call-seq:
3399 * ios.each_byte {|byte| block } -> ios
3400 * ios.each_byte -> an_enumerator
3401 *
3402 * Calls the given block once for each byte (0..255) in <em>ios</em>,
3403 * passing the byte as an argument. The stream must be opened for
3404 * reading or an <code>IOError</code> will be raised.
3405 *
3406 * If no block is given, an enumerator is returned instead.
3407 *
3408 * f = File.new("testfile")
3409 * checksum = 0
3410 * f.each_byte {|x| checksum ^= x } #=> #<File:testfile>
3411 * checksum #=> 12
3412 */
3413
3414 static VALUE
3415 rb_io_each_byte(VALUE io)
3416 {
3417 rb_io_t *fptr;
3418
3419 RETURN_ENUMERATOR(io, 0, 0);
3420 GetOpenFile(io, fptr);
3421
3422 do {
3423 while (fptr->rbuf.len > 0) {
3424 char *p = fptr->rbuf.ptr + fptr->rbuf.off++;
3425 fptr->rbuf.len--;
3426 rb_yield(INT2FIX(*p & 0xff));
3427 errno = 0;
3428 }
3429 rb_io_check_byte_readable(fptr);
3430 READ_CHECK(fptr);
3431 } while (io_fillbuf(fptr) >= 0);
3432 return io;
3433 }
3434
3435 /*
3436 * This is a deprecated alias for <code>each_byte</code>.
3437 */
3438
3439 static VALUE
3440 rb_io_bytes(VALUE io)
3441 {
3442 rb_warn("IO#bytes is deprecated; use #each_byte instead");
3443 if (!rb_block_given_p())
3444 return rb_enumeratorize(io, ID2SYM(rb_intern("each_byte")), 0, 0);
3445 return rb_io_each_byte(io);
3446 }
3447
3448 static VALUE
3449 io_getc(rb_io_t *fptr, rb_encoding *enc)
3450 {
3451 int r, n, cr = 0;
3452 VALUE str;
3453
3454 if (NEED_READCONV(fptr)) {
3455 VALUE str = Qnil;
3456 rb_encoding *read_enc = io_read_encoding(fptr);
3457
3458 SET_BINARY_MODE(fptr);
3459 make_readconv(fptr, 0);
3460
3461 while (1) {
3462 if (fptr->cbuf.len) {
3463 r = rb_enc_precise_mbclen(fptr->cbuf.ptr+fptr->cbuf.off,
3464 fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
3465 read_enc);
3466 if (!MBCLEN_NEEDMORE_P(r))
3467 break;
3468 if (fptr->cbuf.len == fptr->cbuf.capa) {
3469 rb_raise(rb_eIOError, "too long character");
3470 }
3471 }
3472
3473 if (more_char(fptr) == MORE_CHAR_FINISHED) {
3474 if (fptr->cbuf.len == 0) {
3475 clear_readconv(fptr);
3476 return Qnil;
3477 }
3478 /* return an unit of an incomplete character just before EOF */
3479 str = rb_enc_str_new(fptr->cbuf.ptr+fptr->cbuf.off, 1, read_enc);
3480 fptr->cbuf.off += 1;
3481 fptr->cbuf.len -= 1;
3482 if (fptr->cbuf.len == 0) clear_readconv(fptr);
3483 ENC_CODERANGE_SET(str, ENC_CODERANGE_BROKEN);
3484 return str;
3485 }
3486 }
3487 if (MBCLEN_INVALID_P(r)) {
3488 r = rb_enc_mbclen(fptr->cbuf.ptr+fptr->cbuf.off,
3489 fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
3490 read_enc);
3491 io_shift_cbuf(fptr, r, &str);
3492 cr = ENC_CODERANGE_BROKEN;
3493 }
3494 else {
3495 io_shift_cbuf(fptr, MBCLEN_CHARFOUND_LEN(r), &str);
3496 cr = ENC_CODERANGE_VALID;
3497 if (MBCLEN_CHARFOUND_LEN(r) == 1 && rb_enc_asciicompat(read_enc) &&
3498 ISASCII(RSTRING_PTR(str)[0])) {
3499 cr = ENC_CODERANGE_7BIT;
3500 }
3501 }
3502 str = io_enc_str(str, fptr);
3503 ENC_CODERANGE_SET(str, cr);
3504 return str;
3505 }
3506
3507 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
3508 if (io_fillbuf(fptr) < 0) {
3509 return Qnil;
3510 }
3511 if (rb_enc_asciicompat(enc) && ISASCII(fptr->rbuf.ptr[fptr->rbuf.off])) {
3512 str = rb_str_new(fptr->rbuf.ptr+fptr->rbuf.off, 1);
3513 fptr->rbuf.off += 1;
3514 fptr->rbuf.len -= 1;
3515 cr = ENC_CODERANGE_7BIT;
3516 }
3517 else {
3518 r = rb_enc_precise_mbclen(fptr->rbuf.ptr+fptr->rbuf.off, fptr->rbuf.ptr+fptr->rbuf.off+fptr->rbuf.len, enc);
3519 if (MBCLEN_CHARFOUND_P(r) &&
3520 (n = MBCLEN_CHARFOUND_LEN(r)) <= fptr->rbuf.len) {
3521 str = rb_str_new(fptr->rbuf.ptr+fptr->rbuf.off, n);
3522 fptr->rbuf.off += n;
3523 fptr->rbuf.len -= n;
3524 cr = ENC_CODERANGE_VALID;
3525 }
3526 else if (MBCLEN_NEEDMORE_P(r)) {
3527 str = rb_str_new(fptr->rbuf.ptr+fptr->rbuf.off, fptr->rbuf.len);
3528 fptr->rbuf.len = 0;
3529 getc_needmore:
3530 if (io_fillbuf(fptr) != -1) {
3531 rb_str_cat(str, fptr->rbuf.ptr+fptr->rbuf.off, 1);
3532 fptr->rbuf.off++;
3533 fptr->rbuf.len--;
3534 r = rb_enc_precise_mbclen(RSTRING_PTR(str), RSTRING_PTR(str)+RSTRING_LEN(str), enc);
3535 if (MBCLEN_NEEDMORE_P(r)) {
3536 goto getc_needmore;
3537 }
3538 else if (MBCLEN_CHARFOUND_P(r)) {
3539 cr = ENC_CODERANGE_VALID;
3540 }
3541 }
3542 }
3543 else {
3544 str = rb_str_new(fptr->rbuf.ptr+fptr->rbuf.off, 1);
3545 fptr->rbuf.off++;
3546 fptr->rbuf.len--;
3547 }
3548 }
3549 if (!cr) cr = ENC_CODERANGE_BROKEN;
3550 str = io_enc_str(str, fptr);
3551 ENC_CODERANGE_SET(str, cr);
3552 return str;
3553 }
3554
3555 /*
3556 * call-seq:
3557 * ios.each_char {|c| block } -> ios
3558 * ios.each_char -> an_enumerator
3559 *
3560 * Calls the given block once for each character in <em>ios</em>,
3561 * passing the character as an argument. The stream must be opened for
3562 * reading or an <code>IOError</code> will be raised.
3563 *
3564 * If no block is given, an enumerator is returned instead.
3565 *
3566 * f = File.new("testfile")
3567 * f.each_char {|c| print c, ' ' } #=> #<File:testfile>
3568 */
3569
3570 static VALUE
3571 rb_io_each_char(VALUE io)
3572 {
3573 rb_io_t *fptr;
3574 rb_encoding *enc;
3575 VALUE c;
3576
3577 RETURN_ENUMERATOR(io, 0, 0);
3578 GetOpenFile(io, fptr);
3579 rb_io_check_char_readable(fptr);
3580
3581 enc = io_input_encoding(fptr);
3582 READ_CHECK(fptr);
3583 while (!NIL_P(c = io_getc(fptr, enc))) {
3584 rb_yield(c);
3585 }
3586 return io;
3587 }
3588
3589 /*
3590 * This is a deprecated alias for <code>each_char</code>.
3591 */
3592
3593 static VALUE
3594 rb_io_chars(VALUE io)
3595 {
3596 rb_warn("IO#chars is deprecated; use #each_char instead");
3597 if (!rb_block_given_p())
3598 return rb_enumeratorize(io, ID2SYM(rb_intern("each_char")), 0, 0);
3599 return rb_io_each_char(io);
3600 }
3601
3602
3603 /*
3604 * call-seq:
3605 * ios.each_codepoint {|c| block } -> ios
3606 * ios.codepoints {|c| block } -> ios
3607 * ios.each_codepoint -> an_enumerator
3608 * ios.codepoints -> an_enumerator
3609 *
3610 * Passes the <code>Integer</code> ordinal of each character in <i>ios</i>,
3611 * passing the codepoint as an argument. The stream must be opened for
3612 * reading or an <code>IOError</code> will be raised.
3613 *
3614 * If no block is given, an enumerator is returned instead.
3615 *
3616 */
3617
3618 static VALUE
3619 rb_io_each_codepoint(VALUE io)
3620 {
3621 rb_io_t *fptr;
3622 rb_encoding *enc;
3623 unsigned int c;
3624 int r, n;
3625
3626 RETURN_ENUMERATOR(io, 0, 0);
3627 GetOpenFile(io, fptr);
3628 rb_io_check_char_readable(fptr);
3629
3630 READ_CHECK(fptr);
3631 if (NEED_READCONV(fptr)) {
3632 SET_BINARY_MODE(fptr);
3633 for (;;) {
3634 make_readconv(fptr, 0);
3635 for (;;) {
3636 if (fptr->cbuf.len) {
3637 if (fptr->encs.enc)
3638 r = rb_enc_precise_mbclen(fptr->cbuf.ptr+fptr->cbuf.off,
3639 fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
3640 fptr->encs.enc);
3641 else
3642 r = ONIGENC_CONSTRUCT_MBCLEN_CHARFOUND(1);
3643 if (!MBCLEN_NEEDMORE_P(r))
3644 break;
3645 if (fptr->cbuf.len == fptr->cbuf.capa) {
3646 rb_raise(rb_eIOError, "too long character");
3647 }
3648 }
3649 if (more_char(fptr) == MORE_CHAR_FINISHED) {
3650 clear_readconv(fptr);
3651 /* ignore an incomplete character before EOF */
3652 return io;
3653 }
3654 }
3655 if (MBCLEN_INVALID_P(r)) {
3656 rb_raise(rb_eArgError, "invalid byte sequence in %s",
3657 rb_enc_name(fptr->encs.enc));
3658 }
3659 n = MBCLEN_CHARFOUND_LEN(r);
3660 if (fptr->encs.enc) {
3661 c = rb_enc_codepoint(fptr->cbuf.ptr+fptr->cbuf.off,
3662 fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
3663 fptr->encs.enc);
3664 }
3665 else {
3666 c = (unsigned char)fptr->cbuf.ptr[fptr->cbuf.off];
3667 }
3668 fptr->cbuf.off += n;
3669 fptr->cbuf.len -= n;
3670 rb_yield(UINT2NUM(c));
3671 }
3672 }
3673 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
3674 enc = io_input_encoding(fptr);
3675 while (io_fillbuf(fptr) >= 0) {
3676 r = rb_enc_precise_mbclen(fptr->rbuf.ptr+fptr->rbuf.off,
3677 fptr->rbuf.ptr+fptr->rbuf.off+fptr->rbuf.len, enc);
3678 if (MBCLEN_CHARFOUND_P(r) &&
3679 (n = MBCLEN_CHARFOUND_LEN(r)) <= fptr->rbuf.len) {
3680 c = rb_enc_codepoint(fptr->rbuf.ptr+fptr->rbuf.off,
3681 fptr->rbuf.ptr+fptr->rbuf.off+fptr->rbuf.len, enc);
3682 fptr->rbuf.off += n;
3683 fptr->rbuf.len -= n;
3684 rb_yield(UINT2NUM(c));
3685 }
3686 else if (MBCLEN_INVALID_P(r)) {
3687 rb_raise(rb_eArgError, "invalid byte sequence in %s", rb_enc_name(enc));
3688 }
3689 else {
3690 continue;
3691 }
3692 }
3693 return io;
3694 }
3695
3696 /*
3697 * This is a deprecated alias for <code>each_codepoint</code>.
3698 */
3699
3700 static VALUE
3701 rb_io_codepoints(VALUE io)
3702 {
3703 rb_warn("IO#codepoints is deprecated; use #each_codepoint instead");
3704 if (!rb_block_given_p())
3705 return rb_enumeratorize(io, ID2SYM(rb_intern("each_codepoint")), 0, 0);
3706 return rb_io_each_codepoint(io);
3707 }
3708
3709
3710 /*
3711 * call-seq:
3712 * ios.getc -> string or nil
3713 *
3714 * Reads a one-character string from <em>ios</em>. Returns
3715 * <code>nil</code> if called at end of file.
3716 *
3717 * f = File.new("testfile")
3718 * f.getc #=> "h"
3719 * f.getc #=> "e"
3720 */
3721
3722 static VALUE
3723 rb_io_getc(VALUE io)
3724 {
3725 rb_io_t *fptr;
3726 rb_encoding *enc;
3727
3728 GetOpenFile(io, fptr);
3729 rb_io_check_char_readable(fptr);
3730
3731 enc = io_input_encoding(fptr);
3732 READ_CHECK(fptr);
3733 return io_getc(fptr, enc);
3734 }
3735
3736 /*
3737 * call-seq:
3738 * ios.readchar -> string
3739 *
3740 * Reads a one-character string from <em>ios</em>. Raises an
3741 * <code>EOFError</code> on end of file.
3742 *
3743 * f = File.new("testfile")
3744 * f.readchar #=> "h"
3745 * f.readchar #=> "e"
3746 */
3747
3748 static VALUE
3749 rb_io_readchar(VALUE io)
3750 {
3751 VALUE c = rb_io_getc(io);
3752
3753 if (NIL_P(c)) {
3754 rb_eof_error();
3755 }
3756 return c;
3757 }
3758
3759 /*
3760 * call-seq:
3761 * ios.getbyte -> fixnum or nil
3762 *
3763 * Gets the next 8-bit byte (0..255) from <em>ios</em>. Returns
3764 * <code>nil</code> if called at end of file.
3765 *
3766 * f = File.new("testfile")
3767 * f.getbyte #=> 84
3768 * f.getbyte #=> 104
3769 */
3770
3771 VALUE
3772 rb_io_getbyte(VALUE io)
3773 {
3774 rb_io_t *fptr;
3775 int c;
3776
3777 GetOpenFile(io, fptr);
3778 rb_io_check_byte_readable(fptr);
3779 READ_CHECK(fptr);
3780 if (fptr->fd == 0 && (fptr->mode & FMODE_TTY) && RB_TYPE_P(rb_stdout, T_FILE)) {
3781 rb_io_t *ofp;
3782 GetOpenFile(rb_stdout, ofp);
3783 if (ofp->mode & FMODE_TTY) {
3784 rb_io_flush(rb_stdout);
3785 }
3786 }
3787 if (io_fillbuf(fptr) < 0) {
3788 return Qnil;
3789 }
3790 fptr->rbuf.off++;
3791 fptr->rbuf.len--;
3792 c = (unsigned char)fptr->rbuf.ptr[fptr->rbuf.off-1];
3793 return INT2FIX(c & 0xff);
3794 }
3795
3796 /*
3797 * call-seq:
3798 * ios.readbyte -> fixnum
3799 *
3800 * Reads a byte as with <code>IO#getbyte</code>, but raises an
3801 * <code>EOFError</code> on end of file.
3802 */
3803
3804 static VALUE
3805 rb_io_readbyte(VALUE io)
3806 {
3807 VALUE c = rb_io_getbyte(io);
3808
3809 if (NIL_P(c)) {
3810 rb_eof_error();
3811 }
3812 return c;
3813 }
3814
3815 /*
3816 * call-seq:
3817 * ios.ungetbyte(string) -> nil
3818 * ios.ungetbyte(integer) -> nil
3819 *
3820 * Pushes back bytes (passed as a parameter) onto <em>ios</em>,
3821 * such that a subsequent buffered read will return it. Only one byte
3822 * may be pushed back before a subsequent read operation (that is,
3823 * you will be able to read only the last of several bytes that have been pushed
3824 * back). Has no effect with unbuffered reads (such as <code>IO#sysread</code>).
3825 *
3826 * f = File.new("testfile") #=> #<File:testfile>
3827 * b = f.getbyte #=> 0x38
3828 * f.ungetbyte(b) #=> nil
3829 * f.getbyte #=> 0x38
3830 */
3831
3832 VALUE
3833 rb_io_ungetbyte(VALUE io, VALUE b)
3834 {
3835 rb_io_t *fptr;
3836
3837 GetOpenFile(io, fptr);
3838 rb_io_check_byte_readable(fptr);
3839 if (NIL_P(b)) return Qnil;
3840 if (FIXNUM_P(b)) {
3841 char cc = FIX2INT(b);
3842 b = rb_str_new(&cc, 1);
3843 }
3844 else {
3845 SafeStringValue(b);
3846 }
3847 io_ungetbyte(b, fptr);
3848 return Qnil;
3849 }
3850
3851 /*
3852 * call-seq:
3853 * ios.ungetc(string) -> nil
3854 *
3855 * Pushes back one character (passed as a parameter) onto <em>ios</em>,
3856 * such that a subsequent buffered character read will return it. Only one character
3857 * may be pushed back before a subsequent read operation (that is,
3858 * you will be able to read only the last of several characters that have been pushed
3859 * back). Has no effect with unbuffered reads (such as <code>IO#sysread</code>).
3860 *
3861 * f = File.new("testfile") #=> #<File:testfile>
3862 * c = f.getc #=> "8"
3863 * f.ungetc(c) #=> nil
3864 * f.getc #=> "8"
3865 */
3866
3867 VALUE
3868 rb_io_ungetc(VALUE io, VALUE c)
3869 {
3870 rb_io_t *fptr;
3871 long len;
3872
3873 GetOpenFile(io, fptr);
3874 rb_io_check_char_readable(fptr);
3875 if (NIL_P(c)) return Qnil;
3876 if (FIXNUM_P(c)) {
3877 c = rb_enc_uint_chr(FIX2UINT(c), io_read_encoding(fptr));
3878 }
3879 else if (RB_TYPE_P(c, T_BIGNUM)) {
3880 c = rb_enc_uint_chr(NUM2UINT(c), io_read_encoding(fptr));
3881 }
3882 else {
3883 SafeStringValue(c);
3884 }
3885 if (NEED_READCONV(fptr)) {
3886 SET_BINARY_MODE(fptr);
3887 len = RSTRING_LEN(c);
3888 #if SIZEOF_LONG > SIZEOF_INT
3889 if (len > INT_MAX)
3890 rb_raise(rb_eIOError, "ungetc failed");
3891 #endif
3892 make_readconv(fptr, (int)len);
3893 if (fptr->cbuf.capa - fptr->cbuf.len < len)
3894 rb_raise(rb_eIOError, "ungetc failed");
3895 if (fptr->cbuf.off < len) {
3896 MEMMOVE(fptr->cbuf.ptr+fptr->cbuf.capa-fptr->cbuf.len,
3897 fptr->cbuf.ptr+fptr->cbuf.off,
3898 char, fptr->cbuf.len);
3899 fptr->cbuf.off = fptr->cbuf.capa-fptr->cbuf.len;
3900 }
3901 fptr->cbuf.off -= (int)len;
3902 fptr->cbuf.len += (int)len;
3903 MEMMOVE(fptr->cbuf.ptr+fptr->cbuf.off, RSTRING_PTR(c), char, len);
3904 }
3905 else {
3906 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
3907 io_ungetbyte(c, fptr);
3908 }
3909 return Qnil;
3910 }
3911
3912 /*
3913 * call-seq:
3914 * ios.isatty -> true or false
3915 * ios.tty? -> true or false
3916 *
3917 * Returns <code>true</code> if <em>ios</em> is associated with a
3918 * terminal device (tty), <code>false</code> otherwise.
3919 *
3920 * File.new("testfile").isatty #=> false
3921 * File.new("/dev/tty").isatty #=> true
3922 */
3923
3924 static VALUE
3925 rb_io_isatty(VALUE io)
3926 {
3927 rb_io_t *fptr;
3928
3929 GetOpenFile(io, fptr);
3930 if (isatty(fptr->fd) == 0)
3931 return Qfalse;
3932 return Qtrue;
3933 }
3934
3935 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
3936 /*
3937 * call-seq:
3938 * ios.close_on_exec? -> true or false
3939 *
3940 * Returns <code>true</code> if <em>ios</em> will be closed on exec.
3941 *
3942 * f = open("/dev/null")
3943 * f.close_on_exec? #=> false
3944 * f.close_on_exec = true
3945 * f.close_on_exec? #=> true
3946 * f.close_on_exec = false
3947 * f.close_on_exec? #=> false
3948 */
3949
3950 static VALUE
3951 rb_io_close_on_exec_p(VALUE io)
3952 {
3953 rb_io_t *fptr;
3954 VALUE write_io;
3955 int fd, ret;
3956
3957 write_io = GetWriteIO(io);
3958 if (io != write_io) {
3959 GetOpenFile(write_io, fptr);
3960 if (fptr && 0 <= (fd = fptr->fd)) {
3961 if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
3962 if (!(ret & FD_CLOEXEC)) return Qfalse;
3963 }
3964 }
3965
3966 GetOpenFile(io, fptr);
3967 if (fptr && 0 <= (fd = fptr->fd)) {
3968 if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
3969 if (!(ret & FD_CLOEXEC)) return Qfalse;
3970 }
3971 return Qtrue;
3972 }
3973 #else
3974 #define rb_io_close_on_exec_p rb_f_notimplement
3975 #endif
3976
3977 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
3978 /*
3979 * call-seq:
3980 * ios.close_on_exec = bool -> true or false
3981 *
3982 * Sets a close-on-exec flag.
3983 *
3984 * f = open("/dev/null")
3985 * f.close_on_exec = true
3986 * system("cat", "/proc/self/fd/#{f.fileno}") # cat: /proc/self/fd/3: No such file or directory
3987 * f.closed? #=> false
3988 *
3989 * Ruby sets close-on-exec flags of all file descriptors by default
3990 * since Ruby 2.0.0.
3991 * So you don't need to set by yourself.
3992 * Also, unsetting a close-on-exec flag can cause file descriptor leak
3993 * if another thread use fork() and exec() (via system() method for example).
3994 * If you really needs file descriptor inheritance to child process,
3995 * use spawn()'s argument such as fd=>fd.
3996 */
3997
3998 static VALUE
3999 rb_io_set_close_on_exec(VALUE io, VALUE arg)
4000 {
4001 int flag = RTEST(arg) ? FD_CLOEXEC : 0;
4002 rb_io_t *fptr;
4003 VALUE write_io;
4004 int fd, ret;
4005
4006 write_io = GetWriteIO(io);
4007 if (io != write_io) {
4008 GetOpenFile(write_io, fptr);
4009 if (fptr && 0 <= (fd = fptr->fd)) {
4010 if ((ret = fcntl(fptr->fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
4011 if ((ret & FD_CLOEXEC) != flag) {
4012 ret = (ret & ~FD_CLOEXEC) | flag;
4013 ret = fcntl(fd, F_SETFD, ret);
4014 if (ret == -1) rb_sys_fail_path(fptr->pathv);
4015 }
4016 }
4017
4018 }
4019
4020 GetOpenFile(io, fptr);
4021 if (fptr && 0 <= (fd = fptr->fd)) {
4022 if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
4023 if ((ret & FD_CLOEXEC) != flag) {
4024 ret = (ret & ~FD_CLOEXEC) | flag;
4025 ret = fcntl(fd, F_SETFD, ret);
4026 if (ret == -1) rb_sys_fail_path(fptr->pathv);
4027 }
4028 }
4029 return Qnil;
4030 }
4031 #else
4032 #define rb_io_set_close_on_exec rb_f_notimplement
4033 #endif
4034
4035 #define FMODE_PREP (1<<16)
4036 #define IS_PREP_STDIO(f) ((f)->mode & FMODE_PREP)
4037 #define PREP_STDIO_NAME(f) (RSTRING_PTR((f)->pathv))
4038
4039 static VALUE
4040 finish_writeconv(rb_io_t *fptr, int noalloc)
4041 {
4042 unsigned char *ds, *dp, *de;
4043 rb_econv_result_t res;
4044
4045 if (!fptr->wbuf.ptr) {
4046 unsigned char buf[1024];
4047 long r;
4048
4049 res = econv_destination_buffer_full;
4050 while (res == econv_destination_buffer_full) {
4051 ds = dp = buf;
4052 de = buf + sizeof(buf);
4053 res = rb_econv_convert(fptr->writeconv, NULL, NULL, &dp, de, 0);
4054 while (dp-ds) {
4055 retry:
4056 if (fptr->write_lock && rb_mutex_owned_p(fptr->write_lock))
4057 r = rb_write_internal2(fptr->fd, ds, dp-ds);
4058 else
4059 r = rb_write_internal(fptr->fd, ds, dp-ds);
4060 if (r == dp-ds)
4061 break;
4062 if (0 <= r) {
4063 ds += r;
4064 }
4065 if (rb_io_wait_writable(fptr->fd)) {
4066 if (fptr->fd < 0)
4067 return noalloc ? Qtrue : rb_exc_new3(rb_eIOError, rb_str_new_cstr(closed_stream));
4068 goto retry;
4069 }
4070 return noalloc ? Qtrue : INT2NUM(errno);
4071 }
4072 if (res == econv_invalid_byte_sequence ||
4073 res == econv_incomplete_input ||
4074 res == econv_undefined_conversion) {
4075 return noalloc ? Qtrue : rb_econv_make_exception(fptr->writeconv);
4076 }
4077 }
4078
4079 return Qnil;
4080 }
4081
4082 res = econv_destination_buffer_full;
4083 while (res == econv_destination_buffer_full) {
4084 if (fptr->wbuf.len == fptr->wbuf.capa) {
4085 if (io_fflush(fptr) < 0)
4086 return noalloc ? Qtrue : INT2NUM(errno);
4087 }
4088
4089 ds = dp = (unsigned char *)fptr->wbuf.ptr + fptr->wbuf.off + fptr->wbuf.len;
4090 de = (unsigned char *)fptr->wbuf.ptr + fptr->wbuf.capa;
4091 res = rb_econv_convert(fptr->writeconv, NULL, NULL, &dp, de, 0);
4092 fptr->wbuf.len += (int)(dp - ds);
4093 if (res == econv_invalid_byte_sequence ||
4094 res == econv_incomplete_input ||
4095 res == econv_undefined_conversion) {
4096 return noalloc ? Qtrue : rb_econv_make_exception(fptr->writeconv);
4097 }
4098 }
4099 return Qnil;
4100 }
4101
4102 struct finish_writeconv_arg {
4103 rb_io_t *fptr;
4104 int noalloc;
4105 };
4106
4107 static VALUE
4108 finish_writeconv_sync(VALUE arg)
4109 {
4110 struct finish_writeconv_arg *p = (struct finish_writeconv_arg *)arg;
4111 return finish_writeconv(p->fptr, p->noalloc);
4112 }
4113
4114 static void*
4115 nogvl_close(void *ptr)
4116 {
4117 int *fd = ptr;
4118
4119 return (void*)(intptr_t)close(*fd);
4120 }
4121
4122 static int
4123 maygvl_close(int fd, int keepgvl)
4124 {
4125 if (keepgvl)
4126 return close(fd);
4127
4128 /*
4129 * close() may block for certain file types (NFS, SO_LINGER sockets,
4130 * inotify), so let other threads run.
4131 */
4132 return (int)(intptr_t)rb_thread_call_without_gvl(nogvl_close, &fd, RUBY_UBF_IO, 0);
4133 }
4134
4135 static void*
4136 nogvl_fclose(void *ptr)
4137 {
4138 FILE *file = ptr;
4139
4140 return (void*)(intptr_t)fclose(file);
4141 }
4142
4143 static int
4144 maygvl_fclose(FILE *file, int keepgvl)
4145 {
4146 if (keepgvl)
4147 return fclose(file);
4148
4149 return (int)(intptr_t)rb_thread_call_without_gvl(nogvl_fclose, file, RUBY_UBF_IO, 0);
4150 }
4151
4152 static void
4153 fptr_finalize(rb_io_t *fptr, int noraise)
4154 {
4155 VALUE err = Qnil;
4156 int fd = fptr->fd;
4157 FILE *stdio_file = fptr->stdio_file;
4158
4159 if (fptr->writeconv) {
4160 if (fptr->write_lock && !noraise) {
4161 struct finish_writeconv_arg arg;
4162 arg.fptr = fptr;
4163 arg.noalloc = noraise;
4164 err = rb_mutex_synchronize(fptr->write_lock, finish_writeconv_sync, (VALUE)&arg);
4165 }
4166 else {
4167 err = finish_writeconv(fptr, noraise);
4168 }
4169 }
4170 if (fptr->wbuf.len) {
4171 if (noraise) {
4172 if ((int)io_flush_buffer_sync(fptr) < 0 && NIL_P(err))
4173 err = Qtrue;
4174 }
4175 else {
4176 if (io_fflush(fptr) < 0 && NIL_P(err))
4177 err = INT2NUM(errno);
4178 }
4179 }
4180
4181 fptr->fd = -1;
4182 fptr->stdio_file = 0;
4183 fptr->mode &= ~(FMODE_READABLE|FMODE_WRITABLE);
4184
4185 if (IS_PREP_STDIO(fptr) || fd <= 2) {
4186 /* need to keep FILE objects of stdin, stdout and stderr */
4187 }
4188 else if (stdio_file) {
4189 /* stdio_file is deallocated anyway
4190 * even if fclose failed. */
4191 if ((maygvl_fclose(stdio_file, noraise) < 0) && NIL_P(err))
4192 err = noraise ? Qtrue : INT2NUM(errno);
4193 }
4194 else if (0 <= fd) {
4195 /* fptr->fd may be closed even if close fails.
4196 * POSIX doesn't specify it.
4197 * We assumes it is closed. */
4198 if ((maygvl_close(fd, noraise) < 0) && NIL_P(err))
4199 err = noraise ? Qtrue : INT2NUM(errno);
4200 }
4201
4202 if (!NIL_P(err) && !noraise) {
4203 switch (TYPE(err)) {
4204 case T_FIXNUM:
4205 case T_BIGNUM:
4206 errno = NUM2INT(err);
4207 rb_sys_fail_path(fptr->pathv);
4208
4209 default:
4210 rb_exc_raise(err);
4211 }
4212 }
4213 }
4214
4215 static void
4216 rb_io_fptr_cleanup(rb_io_t *fptr, int noraise)
4217 {
4218 if (fptr->finalize) {
4219 (*fptr->finalize)(fptr, noraise);
4220 }
4221 else {
4222 fptr_finalize(fptr, noraise);
4223 }
4224 }
4225
4226 static void
4227 clear_readconv(rb_io_t *fptr)
4228 {
4229 if (fptr->readconv) {
4230 rb_econv_close(fptr->readconv);
4231 fptr->readconv = NULL;
4232 }
4233 if (fptr->cbuf.ptr) {
4234 free(fptr->cbuf.ptr);
4235 fptr->cbuf.ptr = NULL;
4236 }
4237 }
4238
4239 static void
4240 clear_writeconv(rb_io_t *fptr)
4241 {
4242 if (fptr->writeconv) {
4243 rb_econv_close(fptr->writeconv);
4244 fptr->writeconv = NULL;
4245 }
4246 fptr->writeconv_initialized = 0;
4247 }
4248
4249 static void
4250 clear_codeconv(rb_io_t *fptr)
4251 {
4252 clear_readconv(fptr);
4253 clear_writeconv(fptr);
4254 }
4255
4256 int
4257 rb_io_fptr_finalize(rb_io_t *fptr)
4258 {
4259 if (!fptr) return 0;
4260 fptr->pathv = Qnil;
4261 if (0 <= fptr->fd)
4262 rb_io_fptr_cleanup(fptr, TRUE);
4263 fptr->write_lock = 0;
4264 if (fptr->rbuf.ptr) {
4265 free(fptr->rbuf.ptr);
4266 fptr->rbuf.ptr = 0;
4267 }
4268 if (fptr->wbuf.ptr) {
4269 free(fptr->wbuf.ptr);
4270 fptr->wbuf.ptr = 0;
4271 }
4272 clear_codeconv(fptr);
4273 free(fptr);
4274 return 1;
4275 }
4276
4277 size_t rb_econv_memsize(rb_econv_t *);
4278
4279 RUBY_FUNC_EXPORTED size_t
4280 rb_io_memsize(const rb_io_t *fptr)
4281 {
4282 size_t size = sizeof(rb_io_t);
4283 size += fptr->rbuf.capa;
4284 size += fptr->wbuf.capa;
4285 size += fptr->cbuf.capa;
4286 if (fptr->readconv) size += rb_econv_memsize(fptr->readconv);
4287 if (fptr->writeconv) size += rb_econv_memsize(fptr->writeconv);
4288 return size;
4289 }
4290
4291 VALUE
4292 rb_io_close(VALUE io)
4293 {
4294 rb_io_t *fptr;
4295 int fd;
4296 VALUE write_io;
4297 rb_io_t *write_fptr;
4298
4299 write_io = GetWriteIO(io);
4300 if (io != write_io) {
4301 write_fptr = RFILE(write_io)->fptr;
4302 if (write_fptr && 0 <= write_fptr->fd) {
4303 rb_io_fptr_cleanup(write_fptr, TRUE);
4304 }
4305 }
4306
4307 fptr = RFILE(io)->fptr;
4308 if (!fptr) return Qnil;
4309 if (fptr->fd < 0) return Qnil;
4310
4311 fd = fptr->fd;
4312 rb_thread_fd_close(fd);
4313 rb_io_fptr_cleanup(fptr, FALSE);
4314
4315 if (fptr->pid) {
4316 rb_last_status_clear();
4317 rb_syswait(fptr->pid);
4318 fptr->pid = 0;
4319 }
4320
4321 return Qnil;
4322 }
4323
4324 /*
4325 * call-seq:
4326 * ios.close -> nil
4327 *
4328 * Closes <em>ios</em> and flushes any pending writes to the operating
4329 * system. The stream is unavailable for any further data operations;
4330 * an <code>IOError</code> is raised if such an attempt is made. I/O
4331 * streams are automatically closed when they are claimed by the
4332 * garbage collector.
4333 *
4334 * If <em>ios</em> is opened by <code>IO.popen</code>,
4335 * <code>close</code> sets <code>$?</code>.
4336 */
4337
4338 static VALUE
4339 rb_io_close_m(VALUE io)
4340 {
4341 rb_io_check_closed(RFILE(io)->fptr);
4342 rb_io_close(io);
4343 return Qnil;
4344 }
4345
4346 static VALUE
4347 io_call_close(VALUE io)
4348 {
4349 rb_check_funcall(io, rb_intern("close"), 0, 0);
4350 return io;
4351 }
4352
4353 static VALUE
4354 ignore_closed_stream(VALUE io, VALUE exc)
4355 {
4356 enum {mesg_len = sizeof(closed_stream)-1};
4357 VALUE mesg = rb_attr_get(exc, rb_intern("mesg"));
4358 if (!RB_TYPE_P(mesg, T_STRING) ||
4359 RSTRING_LEN(mesg) != mesg_len ||
4360 memcmp(RSTRING_PTR(mesg), closed_stream, mesg_len)) {
4361 rb_exc_raise(exc);
4362 }
4363 return io;
4364 }
4365
4366 static VALUE
4367 io_close(VALUE io)
4368 {
4369 VALUE closed = rb_check_funcall(io, rb_intern("closed?"), 0, 0);
4370 if (closed != Qundef && RTEST(closed)) return io;
4371 rb_rescue2(io_call_close, io, ignore_closed_stream, io,
4372 rb_eIOError, (VALUE)0);
4373 return io;
4374 }
4375
4376 /*
4377 * call-seq:
4378 * ios.closed? -> true or false
4379 *
4380 * Returns <code>true</code> if <em>ios</em> is completely closed (for
4381 * duplex streams, both reader and writer), <code>false</code>
4382 * otherwise.
4383 *
4384 * f = File.new("testfile")
4385 * f.close #=> nil
4386 * f.closed? #=> true
4387 * f = IO.popen("/bin/sh","r+")
4388 * f.close_write #=> nil
4389 * f.closed? #=> false
4390 * f.close_read #=> nil
4391 * f.closed? #=> true
4392 */
4393
4394
4395 static VALUE
4396 rb_io_closed(VALUE io)
4397 {
4398 rb_io_t *fptr;
4399 VALUE write_io;
4400 rb_io_t *write_fptr;
4401
4402 write_io = GetWriteIO(io);
4403 if (io != write_io) {
4404 write_fptr = RFILE(write_io)->fptr;
4405 if (write_fptr && 0 <= write_fptr->fd) {
4406 return Qfalse;
4407 }
4408 }
4409
4410 fptr = RFILE(io)->fptr;
4411 rb_io_check_initialized(fptr);
4412 return 0 <= fptr->fd ? Qfalse : Qtrue;
4413 }
4414
4415 /*
4416 * call-seq:
4417 * ios.close_read -> nil
4418 *
4419 * Closes the read end of a duplex I/O stream (i.e., one that contains
4420 * both a read and a write stream, such as a pipe). Will raise an
4421 * <code>IOError</code> if the stream is not duplexed.
4422 *
4423 * f = IO.popen("/bin/sh","r+")
4424 * f.close_read
4425 * f.readlines
4426 *
4427 * <em>produces:</em>
4428 *
4429 * prog.rb:3:in `readlines': not opened for reading (IOError)
4430 * from prog.rb:3
4431 */
4432
4433 static VALUE
4434 rb_io_close_read(VALUE io)
4435 {
4436 rb_io_t *fptr;
4437 VALUE write_io;
4438
4439 GetOpenFile(io, fptr);
4440 if (is_socket(fptr->fd, fptr->pathv)) {
4441 #ifndef SHUT_RD
4442 # define SHUT_RD 0
4443 #endif
4444 if (shutdown(fptr->fd, SHUT_RD) < 0)
4445 rb_sys_fail_path(fptr->pathv);
4446 fptr->mode &= ~FMODE_READABLE;
4447 if (!(fptr->mode & FMODE_WRITABLE))
4448 return rb_io_close(io);
4449 return Qnil;
4450 }
4451
4452 write_io = GetWriteIO(io);
4453 if (io != write_io) {
4454 rb_io_t *wfptr;
4455 GetOpenFile(write_io, wfptr);
4456 wfptr->pid = fptr->pid;
4457 fptr->pid = 0;
4458 RFILE(io)->fptr = wfptr;
4459 /* bind to write_io temporarily to get rid of memory/fd leak */
4460 fptr->tied_io_for_writing = 0;
4461 fptr->mode &= ~FMODE_DUPLEX;
4462 RFILE(write_io)->fptr = fptr;
4463 rb_io_fptr_cleanup(fptr, FALSE);
4464 /* should not finalize fptr because another thread may be reading it */
4465 return Qnil;
4466 }
4467
4468 if (fptr->mode & FMODE_WRITABLE) {
4469 rb_raise(rb_eIOError, "closing non-duplex IO for reading");
4470 }
4471 return rb_io_close(io);
4472 }
4473
4474 /*
4475 * call-seq:
4476 * ios.close_write -> nil
4477 *
4478 * Closes the write end of a duplex I/O stream (i.e., one that contains
4479 * both a read and a write stream, such as a pipe). Will raise an
4480 * <code>IOError</code> if the stream is not duplexed.
4481 *
4482 * f = IO.popen("/bin/sh","r+")
4483 * f.close_write
4484 * f.print "nowhere"
4485 *
4486 * <em>produces:</em>
4487 *
4488 * prog.rb:3:in `write': not opened for writing (IOError)
4489 * from prog.rb:3:in `print'
4490 * from prog.rb:3
4491 */
4492
4493 static VALUE
4494 rb_io_close_write(VALUE io)
4495 {
4496 rb_io_t *fptr;
4497 VALUE write_io;
4498
4499 write_io = GetWriteIO(io);
4500 GetOpenFile(write_io, fptr);
4501 if (is_socket(fptr->fd, fptr->pathv)) {
4502 #ifndef SHUT_WR
4503 # define SHUT_WR 1
4504 #endif
4505 if (shutdown(fptr->fd, SHUT_WR) < 0)
4506 rb_sys_fail_path(fptr->pathv);
4507 fptr->mode &= ~FMODE_WRITABLE;
4508 if (!(fptr->mode & FMODE_READABLE))
4509 return rb_io_close(write_io);
4510 return Qnil;
4511 }
4512
4513 if (fptr->mode & FMODE_READABLE) {
4514 rb_raise(rb_eIOError, "closing non-duplex IO for writing");
4515 }
4516
4517 if (io != write_io) {
4518 GetOpenFile(io, fptr);
4519 fptr->tied_io_for_writing = 0;
4520 fptr->mode &= ~FMODE_DUPLEX;
4521 }
4522 rb_io_close(write_io);
4523 return Qnil;
4524 }
4525
4526 /*
4527 * call-seq:
4528 * ios.sysseek(offset, whence=IO::SEEK_SET) -> integer
4529 *
4530 * Seeks to a given <i>offset</i> in the stream according to the value
4531 * of <i>whence</i> (see <code>IO#seek</code> for values of
4532 * <i>whence</i>). Returns the new offset into the file.
4533 *
4534 * f = File.new("testfile")
4535 * f.sysseek(-13, IO::SEEK_END) #=> 53
4536 * f.sysread(10) #=> "And so on."
4537 */
4538
4539 static VALUE
4540 rb_io_sysseek(int argc, VALUE *argv, VALUE io)
4541 {
4542 VALUE offset, ptrname;
4543 int whence = SEEK_SET;
4544 rb_io_t *fptr;
4545 off_t pos;
4546
4547 if (rb_scan_args(argc, argv, "11", &offset, &ptrname) == 2) {
4548 whence = interpret_seek_whence(ptrname);
4549 }
4550 pos = NUM2OFFT(offset);
4551 GetOpenFile(io, fptr);
4552 if ((fptr->mode & FMODE_READABLE) &&
4553 (READ_DATA_BUFFERED(fptr) || READ_CHAR_PENDING(fptr))) {
4554 rb_raise(rb_eIOError, "sysseek for buffered IO");
4555 }
4556 if ((fptr->mode & FMODE_WRITABLE) && fptr->wbuf.len) {
4557 rb_warn("sysseek for buffered IO");
4558 }
4559 errno = 0;
4560 pos = lseek(fptr->fd, pos, whence);
4561 if (pos == -1 && errno) rb_sys_fail_path(fptr->pathv);
4562
4563 return OFFT2NUM(pos);
4564 }
4565
4566 /*
4567 * call-seq:
4568 * ios.syswrite(string) -> integer
4569 *
4570 * Writes the given string to <em>ios</em> using a low-level write.
4571 * Returns the number of bytes written. Do not mix with other methods
4572 * that write to <em>ios</em> or you may get unpredictable results.
4573 * Raises <code>SystemCallError</code> on error.
4574 *
4575 * f = File.new("out", "w")
4576 * f.syswrite("ABCDEF") #=> 6
4577 */
4578
4579 static VALUE
4580 rb_io_syswrite(VALUE io, VALUE str)
4581 {
4582 rb_io_t *fptr;
4583 long n;
4584
4585 if (!RB_TYPE_P(str, T_STRING))
4586 str = rb_obj_as_string(str);
4587
4588 io = GetWriteIO(io);
4589 GetOpenFile(io, fptr);
4590 rb_io_check_writable(fptr);
4591
4592 str = rb_str_new_frozen(str);
4593
4594 if (fptr->wbuf.len) {
4595 rb_warn("syswrite for buffered IO");
4596 }
4597
4598 n = rb_write_internal(fptr->fd, RSTRING_PTR(str), RSTRING_LEN(str));
4599 RB_GC_GUARD(str);
4600
4601 if (n == -1) rb_sys_fail_path(fptr->pathv);
4602
4603 return LONG2FIX(n);
4604 }
4605
4606 /*
4607 * call-seq:
4608 * ios.sysread(maxlen[, outbuf]) -> string
4609 *
4610 * Reads <i>maxlen</i> bytes from <em>ios</em> using a low-level
4611 * read and returns them as a string. Do not mix with other methods
4612 * that read from <em>ios</em> or you may get unpredictable results.
4613 * If the optional <i>outbuf</i> argument is present, it must reference
4614 * a String, which will receive the data.
4615 * The <i>outbuf</i> will contain only the received data after the method call
4616 * even if it is not empty at the beginning.
4617 * Raises <code>SystemCallError</code> on error and
4618 * <code>EOFError</code> at end of file.
4619 *
4620 * f = File.new("testfile")
4621 * f.sysread(16) #=> "This is line one"
4622 */
4623
4624 static VALUE
4625 rb_io_sysread(int argc, VALUE *argv, VALUE io)
4626 {
4627 VALUE len, str;
4628 rb_io_t *fptr;
4629 long n, ilen;
4630 struct read_internal_arg arg;
4631
4632 rb_scan_args(argc, argv, "11", &len, &str);
4633 ilen = NUM2LONG(len);
4634
4635 io_setstrbuf(&str,ilen);
4636 if (ilen == 0) return str;
4637
4638 GetOpenFile(io, fptr);
4639 rb_io_check_byte_readable(fptr);
4640
4641 if (READ_DATA_BUFFERED(fptr)) {
4642 rb_raise(rb_eIOError, "sysread for buffered IO");
4643 }
4644
4645 n = fptr->fd;
4646
4647 /*
4648 * FIXME: removing rb_thread_wait_fd() here changes sysread semantics
4649 * on non-blocking IOs. However, it's still currently possible
4650 * for sysread to raise Errno::EAGAIN if another thread read()s
4651 * the IO after we return from rb_thread_wait_fd() but before
4652 * we call read()
4653 */
4654 rb_thread_wait_fd(fptr->fd);
4655
4656 rb_io_check_closed(fptr);
4657
4658 io_setstrbuf(&str, ilen);
4659 rb_str_locktmp(str);
4660 arg.fd = fptr->fd;
4661 arg.str_ptr = RSTRING_PTR(str);
4662 arg.len = ilen;
4663 rb_ensure(read_internal_call, (VALUE)&arg, rb_str_unlocktmp, str);
4664 n = arg.len;
4665
4666 if (n == -1) {
4667 rb_sys_fail_path(fptr->pathv);
4668 }
4669 io_set_read_length(str, n);
4670 if (n == 0 && ilen > 0) {
4671 rb_eof_error();
4672 }
4673 OBJ_TAINT(str);
4674
4675 return str;
4676 }
4677
4678 VALUE
4679 rb_io_binmode(VALUE io)
4680 {
4681 rb_io_t *fptr;
4682
4683 GetOpenFile(io, fptr);
4684 if (fptr->readconv)
4685 rb_econv_binmode(fptr->readconv);
4686 if (fptr->writeconv)
4687 rb_econv_binmode(fptr->writeconv);
4688 fptr->mode |= FMODE_BINMODE;
4689 fptr->mode &= ~FMODE_TEXTMODE;
4690 fptr->writeconv_pre_ecflags &= ~ECONV_NEWLINE_DECORATOR_MASK;
4691 #ifdef O_BINARY
4692 if (!fptr->readconv) {
4693 SET_BINARY_MODE_WITH_SEEK_CUR(fptr);
4694 }
4695 else {
4696 setmode(fptr->fd, O_BINARY);
4697 }
4698 #endif
4699 return io;
4700 }
4701
4702 static void
4703 io_ascii8bit_binmode(rb_io_t *fptr)
4704 {
4705 if (fptr->readconv) {
4706 rb_econv_close(fptr->readconv);
4707 fptr->readconv = NULL;
4708 }
4709 if (fptr->writeconv) {
4710 rb_econv_close(fptr->writeconv);
4711 fptr->writeconv = NULL;
4712 }
4713 fptr->mode |= FMODE_BINMODE;
4714 fptr->mode &= ~FMODE_TEXTMODE;
4715 SET_BINARY_MODE_WITH_SEEK_CUR(fptr);
4716
4717 fptr->encs.enc = rb_ascii8bit_encoding();
4718 fptr->encs.enc2 = NULL;
4719 fptr->encs.ecflags = 0;
4720 fptr->encs.ecopts = Qnil;
4721 clear_codeconv(fptr);
4722 }
4723
4724 VALUE
4725 rb_io_ascii8bit_binmode(VALUE io)
4726 {
4727 rb_io_t *fptr;
4728
4729 GetOpenFile(io, fptr);
4730 io_ascii8bit_binmode(fptr);
4731
4732 return io;
4733 }
4734
4735 /*
4736 * call-seq:
4737 * ios.binmode -> ios
4738 *
4739 * Puts <em>ios</em> into binary mode.
4740 * Once a stream is in binary mode, it cannot be reset to nonbinary mode.
4741 *
4742 * - newline conversion disabled
4743 * - encoding conversion disabled
4744 * - content is treated as ASCII-8BIT
4745 *
4746 */
4747
4748 static VALUE
4749 rb_io_binmode_m(VALUE io)
4750 {
4751 VALUE write_io;
4752
4753 rb_io_ascii8bit_binmode(io);
4754
4755 write_io = GetWriteIO(io);
4756 if (write_io != io)
4757 rb_io_ascii8bit_binmode(write_io);
4758 return io;
4759 }
4760
4761 /*
4762 * call-seq:
4763 * ios.binmode? -> true or false
4764 *
4765 * Returns <code>true</code> if <em>ios</em> is binmode.
4766 */
4767 static VALUE
4768 rb_io_binmode_p(VALUE io)
4769 {
4770 rb_io_t *fptr;
4771 GetOpenFile(io, fptr);
4772 return fptr->mode & FMODE_BINMODE ? Qtrue : Qfalse;
4773 }
4774
4775 static const char*
4776 rb_io_fmode_modestr(int fmode)
4777 {
4778 if (fmode & FMODE_APPEND) {
4779 if ((fmode & FMODE_READWRITE) == FMODE_READWRITE) {
4780 return MODE_BTMODE("a+", "ab+", "at+");
4781 }
4782 return MODE_BTMODE("a", "ab", "at");
4783 }
4784 switch (fmode & FMODE_READWRITE) {
4785 default:
4786 rb_raise(rb_eArgError, "invalid access fmode 0x%x", fmode);
4787 case FMODE_READABLE:
4788 return MODE_BTMODE("r", "rb", "rt");
4789 case FMODE_WRITABLE:
4790 return MODE_BTMODE("w", "wb", "wt");
4791 case FMODE_READWRITE:
4792 if (fmode & FMODE_CREATE) {
4793 return MODE_BTMODE("w+", "wb+", "wt+");
4794 }
4795 return MODE_BTMODE("r+", "rb+", "rt+");
4796 }
4797 }
4798
4799 static int
4800 io_encname_bom_p(const char *name, long len)
4801 {
4802 static const char bom_prefix[] = "bom|utf-";
4803 enum {bom_prefix_len = (int)sizeof(bom_prefix) - 1};
4804 if (!len) {
4805 const char *p = strchr(name, ':');
4806 len = p ? (long)(p - name) : (long)strlen(name);
4807 }
4808 return len > bom_prefix_len && STRNCASECMP(name, bom_prefix, bom_prefix_len) == 0;
4809 }
4810
4811 int
4812 rb_io_modestr_fmode(const char *modestr)
4813 {
4814 int fmode = 0;
4815 const char *m = modestr, *p = NULL;
4816
4817 switch (*m++) {
4818 case 'r':
4819 fmode |= FMODE_READABLE;
4820 break;
4821 case 'w':
4822 fmode |= FMODE_WRITABLE | FMODE_TRUNC | FMODE_CREATE;
4823 break;
4824 case 'a':
4825 fmode |= FMODE_WRITABLE | FMODE_APPEND | FMODE_CREATE;
4826 break;
4827 default:
4828 error:
4829 rb_raise(rb_eArgError, "invalid access mode %s", modestr);
4830 }
4831
4832 while (*m) {
4833 switch (*m++) {
4834 case 'b':
4835 fmode |= FMODE_BINMODE;
4836 break;
4837 case 't':
4838 fmode |= FMODE_TEXTMODE;
4839 break;
4840 case '+':
4841 fmode |= FMODE_READWRITE;
4842 break;
4843 default:
4844 goto error;
4845 case ':':
4846 p = m;
4847 goto finished;
4848 }
4849 }
4850
4851 finished:
4852 if ((fmode & FMODE_BINMODE) && (fmode & FMODE_TEXTMODE))
4853 goto error;
4854 if (p && io_encname_bom_p(p, 0))
4855 fmode |= FMODE_SETENC_BY_BOM;
4856
4857 return fmode;
4858 }
4859
4860 int
4861 rb_io_oflags_fmode(int oflags)
4862 {
4863 int fmode = 0;
4864
4865 switch (oflags & (O_RDONLY|O_WRONLY|O_RDWR)) {
4866 case O_RDONLY:
4867 fmode = FMODE_READABLE;
4868 break;
4869 case O_WRONLY:
4870 fmode = FMODE_WRITABLE;
4871 break;
4872 case O_RDWR:
4873 fmode = FMODE_READWRITE;
4874 break;
4875 }
4876
4877 if (oflags & O_APPEND) {
4878 fmode |= FMODE_APPEND;
4879 }
4880 if (oflags & O_TRUNC) {
4881 fmode |= FMODE_TRUNC;
4882 }
4883 if (oflags & O_CREAT) {
4884 fmode |= FMODE_CREATE;
4885 }
4886 #ifdef O_BINARY
4887 if (oflags & O_BINARY) {
4888 fmode |= FMODE_BINMODE;
4889 }
4890 #endif
4891
4892 return fmode;
4893 }
4894
4895 static int
4896 rb_io_fmode_oflags(int fmode)
4897 {
4898 int oflags = 0;
4899
4900 switch (fmode & FMODE_READWRITE) {
4901 case FMODE_READABLE:
4902 oflags |= O_RDONLY;
4903 break;
4904 case FMODE_WRITABLE:
4905 oflags |= O_WRONLY;
4906 break;
4907 case FMODE_READWRITE:
4908 oflags |= O_RDWR;
4909 break;
4910 }
4911
4912 if (fmode & FMODE_APPEND) {
4913 oflags |= O_APPEND;
4914 }
4915 if (fmode & FMODE_TRUNC) {
4916 oflags |= O_TRUNC;
4917 }
4918 if (fmode & FMODE_CREATE) {
4919 oflags |= O_CREAT;
4920 }
4921 #ifdef O_BINARY
4922 if (fmode & FMODE_BINMODE) {
4923 oflags |= O_BINARY;
4924 }
4925 #endif
4926
4927 return oflags;
4928 }
4929
4930 int
4931 rb_io_modestr_oflags(const char *modestr)
4932 {
4933 return rb_io_fmode_oflags(rb_io_modestr_fmode(modestr));
4934 }
4935
4936 static const char*
4937 rb_io_oflags_modestr(int oflags)
4938 {
4939 #ifdef O_BINARY
4940 # define MODE_BINARY(a,b) ((oflags & O_BINARY) ? (b) : (a))
4941 #else
4942 # define MODE_BINARY(a,b) (a)
4943 #endif
4944 int accmode = oflags & (O_RDONLY|O_WRONLY|O_RDWR);
4945 if (oflags & O_APPEND) {
4946 if (accmode == O_WRONLY) {
4947 return MODE_BINARY("a", "ab");
4948 }
4949 if (accmode == O_RDWR) {
4950 return MODE_BINARY("a+", "ab+");
4951 }
4952 }
4953 switch (oflags & (O_RDONLY|O_WRONLY|O_RDWR)) {
4954 default:
4955 rb_raise(rb_eArgError, "invalid access oflags 0x%x", oflags);
4956 case O_RDONLY:
4957 return MODE_BINARY("r", "rb");
4958 case O_WRONLY:
4959 return MODE_BINARY("w", "wb");
4960 case O_RDWR:
4961 return MODE_BINARY("r+", "rb+");
4962 }
4963 }
4964
4965 /*
4966 * Convert external/internal encodings to enc/enc2
4967 * NULL => use default encoding
4968 * Qnil => no encoding specified (internal only)
4969 */
4970 static void
4971 rb_io_ext_int_to_encs(rb_encoding *ext, rb_encoding *intern, rb_encoding **enc, rb_encoding **enc2, int fmode)
4972 {
4973 int default_ext = 0;
4974
4975 if (ext == NULL) {
4976 ext = rb_default_external_encoding();
4977 default_ext = 1;
4978 }
4979 if (ext == rb_ascii8bit_encoding()) {
4980 /* If external is ASCII-8BIT, no transcoding */
4981 intern = NULL;
4982 }
4983 else if (intern == NULL) {
4984 intern = rb_default_internal_encoding();
4985 }
4986 if (intern == NULL || intern == (rb_encoding *)Qnil ||
4987 (!(fmode & FMODE_SETENC_BY_BOM) && (intern == ext))) {
4988 /* No internal encoding => use external + no transcoding */
4989 *enc = (default_ext && intern != ext) ? NULL : ext;
4990 *enc2 = NULL;
4991 }
4992 else {
4993 *enc = intern;
4994 *enc2 = ext;
4995 }
4996 }
4997
4998 static void
4999 unsupported_encoding(const char *name)
5000 {
5001 rb_warn("Unsupported encoding %s ignored", name);
5002 }
5003
5004 static void
5005 parse_mode_enc(const char *estr, rb_encoding **enc_p, rb_encoding **enc2_p, int *fmode_p)
5006 {
5007 const char *p;
5008 char encname[ENCODING_MAXNAMELEN+1];
5009 int idx, idx2;
5010 int fmode = fmode_p ? *fmode_p : 0;
5011 rb_encoding *ext_enc, *int_enc;
5012
5013 /* parse estr as "enc" or "enc2:enc" or "enc:-" */
5014
5015 p = strrchr(estr, ':');
5016 if (p) {
5017 long len = (p++) - estr;
5018 if (len == 0 || len > ENCODING_MAXNAMELEN)
5019 idx = -1;
5020 else {
5021 if (io_encname_bom_p(estr, len)) {
5022 fmode |= FMODE_SETENC_BY_BOM;
5023 estr += 4;
5024 len -= 4;
5025 }
5026 memcpy(encname, estr, len);
5027 encname[len] = '\0';
5028 estr = encname;
5029 idx = rb_enc_find_index(encname);
5030 }
5031 }
5032 else {
5033 long len = strlen(estr);
5034 if (io_encname_bom_p(estr, len)) {
5035 fmode |= FMODE_SETENC_BY_BOM;
5036 estr += 4;
5037 len -= 4;
5038 memcpy(encname, estr, len);
5039 encname[len] = '\0';
5040 estr = encname;
5041 }
5042 idx = rb_enc_find_index(estr);
5043 }
5044 if (fmode_p) *fmode_p = fmode;
5045
5046 if (idx >= 0)
5047 ext_enc = rb_enc_from_index(idx);
5048 else {
5049 if (idx != -2)
5050 unsupported_encoding(estr);
5051 ext_enc = NULL;
5052 }
5053
5054 int_enc = NULL;
5055 if (p) {
5056 if (*p == '-' && *(p+1) == '\0') {
5057 /* Special case - "-" => no transcoding */
5058 int_enc = (rb_encoding *)Qnil;
5059 }
5060 else {
5061 idx2 = rb_enc_find_index(p);
5062 if (idx2 < 0)
5063 unsupported_encoding(p);
5064 else if (!(fmode & FMODE_SETENC_BY_BOM) && (idx2 == idx)) {
5065 int_enc = (rb_encoding *)Qnil;
5066 }
5067 else
5068 int_enc = rb_enc_from_index(idx2);
5069 }
5070 }
5071
5072 rb_io_ext_int_to_encs(ext_enc, int_enc, enc_p, enc2_p, fmode);
5073 }
5074
5075 int
5076 rb_io_extract_encoding_option(VALUE opt, rb_encoding **enc_p, rb_encoding **enc2_p, int *fmode_p)
5077 {
5078 VALUE encoding=Qnil, extenc=Qundef, intenc=Qundef, tmp;
5079 int extracted = 0;
5080 rb_encoding *extencoding = NULL;
5081 rb_encoding *intencoding = NULL;
5082
5083 if (!NIL_P(opt)) {
5084 VALUE v;
5085 v = rb_hash_lookup2(opt, sym_encoding, Qnil);
5086 if (v != Qnil) encoding = v;
5087 v = rb_hash_lookup2(opt, sym_extenc, Qundef);
5088 if (v != Qnil) extenc = v;
5089 v = rb_hash_lookup2(opt, sym_intenc, Qundef);
5090 if (v != Qundef) intenc = v;
5091 }
5092 if ((extenc != Qundef || intenc != Qundef) && !NIL_P(encoding)) {
5093 if (!NIL_P(ruby_verbose)) {
5094 int idx = rb_to_encoding_index(encoding);
5095 rb_warn("Ignoring encoding parameter '%s': %s_encoding is used",
5096 idx < 0 ? StringValueCStr(encoding) : rb_enc_name(rb_enc_from_index(idx)),
5097 extenc == Qundef ? "internal" : "external");
5098 }
5099 encoding = Qnil;
5100 }
5101 if (extenc != Qundef && !NIL_P(extenc)) {
5102 extencoding = rb_to_encoding(extenc);
5103 }
5104 if (intenc != Qundef) {
5105 if (NIL_P(intenc)) {
5106 /* internal_encoding: nil => no transcoding */
5107 intencoding = (rb_encoding *)Qnil;
5108 }
5109 else if (!NIL_P(tmp = rb_check_string_type(intenc))) {
5110 char *p = StringValueCStr(tmp);
5111
5112 if (*p == '-' && *(p+1) == '\0') {
5113 /* Special case - "-" => no transcoding */
5114 intencoding = (rb_encoding *)Qnil;
5115 }
5116 else {
5117 intencoding = rb_to_encoding(intenc);
5118 }
5119 }
5120 else {
5121 intencoding = rb_to_encoding(intenc);
5122 }
5123 if (extencoding == intencoding) {
5124 intencoding = (rb_encoding *)Qnil;
5125 }
5126 }
5127 if (!NIL_P(encoding)) {
5128 extracted = 1;
5129 if (!NIL_P(tmp = rb_check_string_type(encoding))) {
5130 parse_mode_enc(StringValueCStr(tmp), enc_p, enc2_p, fmode_p);
5131 }
5132 else {
5133 rb_io_ext_int_to_encs(rb_to_encoding(encoding), NULL, enc_p, enc2_p, 0);
5134 }
5135 }
5136 else if (extenc != Qundef || intenc != Qundef) {
5137 extracted = 1;
5138 rb_io_ext_int_to_encs(extencoding, intencoding, enc_p, enc2_p, 0);
5139 }
5140 return extracted;
5141 }
5142
5143 typedef struct rb_io_enc_t convconfig_t;
5144
5145 static void
5146 validate_enc_binmode(int *fmode_p, int ecflags, rb_encoding *enc, rb_encoding *enc2)
5147 {
5148 int fmode = *fmode_p;
5149
5150 if ((fmode & FMODE_READABLE) &&
5151 !enc2 &&
5152 !(fmode & FMODE_BINMODE) &&
5153 !rb_enc_asciicompat(enc ? enc : rb_default_external_encoding()))
5154 rb_raise(rb_eArgError, "ASCII incompatible encoding needs binmode");
5155
5156 if (!(fmode & FMODE_BINMODE) &&
5157 (DEFAULT_TEXTMODE || (ecflags & ECONV_NEWLINE_DECORATOR_MASK))) {
5158 fmode |= DEFAULT_TEXTMODE;
5159 *fmode_p = fmode;
5160 }
5161 #if !DEFAULT_TEXTMODE
5162 else if (!(ecflags & ECONV_NEWLINE_DECORATOR_MASK)) {
5163 fmode &= ~FMODE_TEXTMODE;
5164 *fmode_p = fmode;
5165 }
5166 #endif
5167 }
5168
5169 static void
5170 extract_binmode(VALUE opthash, int *fmode)
5171 {
5172 if (!NIL_P(opthash)) {
5173 VALUE v;
5174 v = rb_hash_aref(opthash, sym_textmode);
5175 if (!NIL_P(v)) {
5176 if (*fmode & FMODE_TEXTMODE)
5177 rb_raise(rb_eArgError, "textmode specified twice");
5178 if (*fmode & FMODE_BINMODE)
5179 rb_raise(rb_eArgError, "both textmode and binmode specified");
5180 if (RTEST(v))
5181 *fmode |= FMODE_TEXTMODE;
5182 }
5183 v = rb_hash_aref(opthash, sym_binmode);
5184 if (!NIL_P(v)) {
5185 if (*fmode & FMODE_BINMODE)
5186 rb_raise(rb_eArgError, "binmode specified twice");
5187 if (*fmode & FMODE_TEXTMODE)
5188 rb_raise(rb_eArgError, "both textmode and binmode specified");
5189 if (RTEST(v))
5190 *fmode |= FMODE_BINMODE;
5191 }
5192
5193 if ((*fmode & FMODE_BINMODE) && (*fmode & FMODE_TEXTMODE))
5194 rb_raise(rb_eArgError, "both textmode and binmode specified");
5195 }
5196 }
5197
5198 static void
5199 rb_io_extract_modeenc(VALUE *vmode_p, VALUE *vperm_p, VALUE opthash,
5200 int *oflags_p, int *fmode_p, convconfig_t *convconfig_p)
5201 {
5202 VALUE vmode;
5203 int oflags, fmode;
5204 rb_encoding *enc, *enc2;
5205 int ecflags;
5206 VALUE ecopts;
5207 int has_enc = 0, has_vmode = 0;
5208 VALUE intmode;
5209
5210 vmode = *vmode_p;
5211
5212 /* Set to defaults */
5213 rb_io_ext_int_to_encs(NULL, NULL, &enc, &enc2, 0);
5214
5215 vmode_handle:
5216 if (NIL_P(vmode)) {
5217 fmode = FMODE_READABLE;
5218 oflags = O_RDONLY;
5219 }
5220 else if (!NIL_P(intmode = rb_check_to_integer(vmode, "to_int"))) {
5221 vmode = intmode;
5222 oflags = NUM2INT(intmode);
5223 fmode = rb_io_oflags_fmode(oflags);
5224 }
5225 else {
5226 const char *p;
5227
5228 SafeStringValue(vmode);
5229 p = StringValueCStr(vmode);
5230 fmode = rb_io_modestr_fmode(p);
5231 oflags = rb_io_fmode_oflags(fmode);
5232 p = strchr(p, ':');
5233 if (p) {
5234 has_enc = 1;
5235 parse_mode_enc(p+1, &enc, &enc2, &fmode);
5236 }
5237 else {
5238 rb_encoding *e;
5239
5240 e = (fmode & FMODE_BINMODE) ? rb_ascii8bit_encoding() : NULL;
5241 rb_io_ext_int_to_encs(e, NULL, &enc, &enc2, fmode);
5242 }
5243 }
5244
5245 if (NIL_P(opthash)) {
5246 ecflags = (fmode & FMODE_READABLE) ?
5247 MODE_BTMODE(ECONV_DEFAULT_NEWLINE_DECORATOR,
5248 0, ECONV_UNIVERSAL_NEWLINE_DECORATOR) : 0;
5249 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
5250 ecflags |= (fmode & FMODE_WRITABLE) ?
5251 MODE_BTMODE(TEXTMODE_NEWLINE_DECORATOR_ON_WRITE,
5252 0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE) : 0;
5253 #endif
5254 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
5255 ecopts = Qnil;
5256 }
5257 else {
5258 VALUE v;
5259 extract_binmode(opthash, &fmode);
5260 if (fmode & FMODE_BINMODE) {
5261 #ifdef O_BINARY
5262 oflags |= O_BINARY;
5263 #endif
5264 if (!has_enc)
5265 rb_io_ext_int_to_encs(rb_ascii8bit_encoding(), NULL, &enc, &enc2, fmode);
5266 }
5267 #if DEFAULT_TEXTMODE
5268 else if (NIL_P(vmode)) {
5269 fmode |= DEFAULT_TEXTMODE;
5270 }
5271 #endif
5272 if (!has_vmode) {
5273 v = rb_hash_aref(opthash, sym_mode);
5274 if (!NIL_P(v)) {
5275 if (!NIL_P(vmode)) {
5276 rb_raise(rb_eArgError, "mode specified twice");
5277 }
5278 has_vmode = 1;
5279 vmode = v;
5280 goto vmode_handle;
5281 }
5282 }
5283 v = rb_hash_aref(opthash, sym_perm);
5284 if (!NIL_P(v)) {
5285 if (vperm_p) {
5286 if (!NIL_P(*vperm_p)) {
5287 rb_raise(rb_eArgError, "perm specified twice");
5288 }
5289 *vperm_p = v;
5290 }
5291 else {
5292 /* perm no use, just ignore */
5293 }
5294 }
5295 ecflags = (fmode & FMODE_READABLE) ?
5296 MODE_BTMODE(ECONV_DEFAULT_NEWLINE_DECORATOR,
5297 0, ECONV_UNIVERSAL_NEWLINE_DECORATOR) : 0;
5298 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
5299 ecflags |= (fmode & FMODE_WRITABLE) ?
5300 MODE_BTMODE(TEXTMODE_NEWLINE_DECORATOR_ON_WRITE,
5301 0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE) : 0;
5302 #endif
5303
5304 if (rb_io_extract_encoding_option(opthash, &enc, &enc2, &fmode)) {
5305 if (has_enc) {
5306 rb_raise(rb_eArgError, "encoding specified twice");
5307 }
5308 }
5309 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
5310 ecflags = rb_econv_prepare_options(opthash, &ecopts, ecflags);
5311 }
5312
5313 validate_enc_binmode(&fmode, ecflags, enc, enc2);
5314
5315 *vmode_p = vmode;
5316
5317 *oflags_p = oflags;
5318 *fmode_p = fmode;
5319 convconfig_p->enc = enc;
5320 convconfig_p->enc2 = enc2;
5321 convconfig_p->ecflags = ecflags;
5322 convconfig_p->ecopts = ecopts;
5323 }
5324
5325 struct sysopen_struct {
5326 VALUE fname;
5327 int oflags;
5328 mode_t perm;
5329 };
5330
5331 static void *
5332 sysopen_func(void *ptr)
5333 {
5334 const struct sysopen_struct *data = ptr;
5335 const char *fname = RSTRING_PTR(data->fname);
5336 return (void *)(VALUE)rb_cloexec_open(fname, data->oflags, data->perm);
5337 }
5338
5339 static inline int
5340 rb_sysopen_internal(struct sysopen_struct *data)
5341 {
5342 int fd;
5343 fd = (int)(VALUE)rb_thread_call_without_gvl(sysopen_func, data, RUBY_UBF_IO, 0);
5344 if (0 <= fd)
5345 rb_update_max_fd(fd);
5346 return fd;
5347 }
5348
5349 static int
5350 rb_sysopen(VALUE fname, int oflags, mode_t perm)
5351 {
5352 int fd;
5353 struct sysopen_struct data;
5354
5355 data.fname = rb_str_encode_ospath(fname);
5356 data.oflags = oflags;
5357 data.perm = perm;
5358
5359 fd = rb_sysopen_internal(&data);
5360 if (fd < 0) {
5361 if (errno == EMFILE || errno == ENFILE) {
5362 rb_gc();
5363 fd = rb_sysopen_internal(&data);
5364 }
5365 if (fd < 0) {
5366 rb_sys_fail_path(fname);
5367 }
5368 }
5369 return fd;
5370 }
5371
5372 FILE *
5373 rb_fdopen(int fd, const char *modestr)
5374 {
5375 FILE *file;
5376
5377 #if defined(__sun)
5378 errno = 0;
5379 #endif
5380 file = fdopen(fd, modestr);
5381 if (!file) {
5382 if (
5383 #if defined(__sun)
5384 errno == 0 ||
5385 #endif
5386 errno == EMFILE || errno == ENFILE) {
5387 rb_gc();
5388 #if defined(__sun)
5389 errno = 0;
5390 #endif
5391 file = fdopen(fd, modestr);
5392 }
5393 if (!file) {
5394 #ifdef _WIN32
5395 if (errno == 0) errno = EINVAL;
5396 #elif defined(__sun)
5397 if (errno == 0) errno = EMFILE;
5398 #endif
5399 rb_sys_fail(0);
5400 }
5401 }
5402
5403 /* xxx: should be _IONBF? A buffer in FILE may have trouble. */
5404 #ifdef USE_SETVBUF
5405 if (setvbuf(file, NULL, _IOFBF, 0) != 0)
5406 rb_warn("setvbuf() can't be honoured (fd=%d)", fd);
5407 #endif
5408 return file;
5409 }
5410
5411 static void
5412 io_check_tty(rb_io_t *fptr)
5413 {
5414 if (isatty(fptr->fd))
5415 fptr->mode |= FMODE_TTY|FMODE_DUPLEX;
5416 }
5417
5418 static VALUE rb_io_internal_encoding(VALUE);
5419 static void io_encoding_set(rb_io_t *, VALUE, VALUE, VALUE);
5420
5421 static int
5422 io_strip_bom(VALUE io)
5423 {
5424 VALUE b1, b2, b3, b4;
5425
5426 if (NIL_P(b1 = rb_io_getbyte(io))) return 0;
5427 switch (b1) {
5428 case INT2FIX(0xEF):
5429 if (NIL_P(b2 = rb_io_getbyte(io))) break;
5430 if (b2 == INT2FIX(0xBB) && !NIL_P(b3 = rb_io_getbyte(io))) {
5431 if (b3 == INT2FIX(0xBF)) {
5432 return rb_utf8_encindex();
5433 }
5434 rb_io_ungetbyte(io, b3);
5435 }
5436 rb_io_ungetbyte(io, b2);
5437 break;
5438
5439 case INT2FIX(0xFE):
5440 if (NIL_P(b2 = rb_io_getbyte(io))) break;
5441 if (b2 == INT2FIX(0xFF)) {
5442 return ENCINDEX_UTF_16BE;
5443 }
5444 rb_io_ungetbyte(io, b2);
5445 break;
5446
5447 case INT2FIX(0xFF):
5448 if (NIL_P(b2 = rb_io_getbyte(io))) break;
5449 if (b2 == INT2FIX(0xFE)) {
5450 b3 = rb_io_getbyte(io);
5451 if (b3 == INT2FIX(0) && !NIL_P(b4 = rb_io_getbyte(io))) {
5452 if (b4 == INT2FIX(0)) {
5453 return ENCINDEX_UTF_32LE;
5454 }
5455 rb_io_ungetbyte(io, b4);
5456 rb_io_ungetbyte(io, b3);
5457 }
5458 else {
5459 rb_io_ungetbyte(io, b3);
5460 return ENCINDEX_UTF_16LE;
5461 }
5462 }
5463 rb_io_ungetbyte(io, b2);
5464 break;
5465
5466 case INT2FIX(0):
5467 if (NIL_P(b2 = rb_io_getbyte(io))) break;
5468 if (b2 == INT2FIX(0) && !NIL_P(b3 = rb_io_getbyte(io))) {
5469 if (b3 == INT2FIX(0xFE) && !NIL_P(b4 = rb_io_getbyte(io))) {
5470 if (b4 == INT2FIX(0xFF)) {
5471 return ENCINDEX_UTF_32BE;
5472 }
5473 rb_io_ungetbyte(io, b4);
5474 }
5475 rb_io_ungetbyte(io, b3);
5476 }
5477 rb_io_ungetbyte(io, b2);
5478 break;
5479 }
5480 rb_io_ungetbyte(io, b1);
5481 return 0;
5482 }
5483
5484 static void
5485 io_set_encoding_by_bom(VALUE io)
5486 {
5487 int idx = io_strip_bom(io);
5488 rb_io_t *fptr;
5489
5490 GetOpenFile(io, fptr);
5491 if (idx) {
5492 io_encoding_set(fptr, rb_enc_from_encoding(rb_enc_from_index(idx)),
5493 rb_io_internal_encoding(io), Qnil);
5494 }
5495 else {
5496 fptr->encs.enc2 = NULL;
5497 }
5498 }
5499
5500 static VALUE
5501 rb_file_open_generic(VALUE io, VALUE filename, int oflags, int fmode, convconfig_t *convconfig, mode_t perm)
5502 {
5503 rb_io_t *fptr;
5504 convconfig_t cc;
5505 if (!convconfig) {
5506 /* Set to default encodings */
5507 rb_io_ext_int_to_encs(NULL, NULL, &cc.enc, &cc.enc2, fmode);
5508 cc.ecflags = 0;
5509 cc.ecopts = Qnil;
5510 convconfig = &cc;
5511 }
5512 validate_enc_binmode(&fmode, convconfig->ecflags,
5513 convconfig->enc, convconfig->enc2);
5514
5515 MakeOpenFile(io, fptr);
5516 fptr->mode = fmode;
5517 fptr->encs = *convconfig;
5518 fptr->pathv = rb_str_new_frozen(filename);
5519 fptr->fd = rb_sysopen(fptr->pathv, oflags, perm);
5520 io_check_tty(fptr);
5521 if (fmode & FMODE_SETENC_BY_BOM) io_set_encoding_by_bom(io);
5522
5523 return io;
5524 }
5525
5526 static VALUE
5527 rb_file_open_internal(VALUE io, VALUE filename, const char *modestr)
5528 {
5529 int fmode = rb_io_modestr_fmode(modestr);
5530 const char *p = strchr(modestr, ':');
5531 convconfig_t convconfig;
5532
5533 if (p) {
5534 parse_mode_enc(p+1, &convconfig.enc, &convconfig.enc2, &fmode);
5535 }
5536 else {
5537 rb_encoding *e;
5538 /* Set to default encodings */
5539
5540 e = (fmode & FMODE_BINMODE) ? rb_ascii8bit_encoding() : NULL;
5541 rb_io_ext_int_to_encs(e, NULL, &convconfig.enc, &convconfig.enc2, fmode);
5542 convconfig.ecflags = 0;
5543 convconfig.ecopts = Qnil;
5544 }
5545
5546 return rb_file_open_generic(io, filename,
5547 rb_io_fmode_oflags(fmode),
5548 fmode,
5549 &convconfig,
5550 0666);
5551 }
5552
5553 VALUE
5554 rb_file_open_str(VALUE fname, const char *modestr)
5555 {
5556 FilePathValue(fname);
5557 return rb_file_open_internal(io_alloc(rb_cFile), fname, modestr);
5558 }
5559
5560 VALUE
5561 rb_file_open(const char *fname, const char *modestr)
5562 {
5563 return rb_file_open_internal(io_alloc(rb_cFile), rb_str_new_cstr(fname), modestr);
5564 }
5565
5566 #if defined(__CYGWIN__) || !defined(HAVE_FORK)
5567 static struct pipe_list {
5568 rb_io_t *fptr;
5569 struct pipe_list *next;
5570 } *pipe_list;
5571
5572 static void
5573 pipe_add_fptr(rb_io_t *fptr)
5574 {
5575 struct pipe_list *list;
5576
5577 list = ALLOC(struct pipe_list);
5578 list->fptr = fptr;
5579 list->next = pipe_list;
5580 pipe_list = list;
5581 }
5582
5583 static void
5584 pipe_del_fptr(rb_io_t *fptr)
5585 {
5586 struct pipe_list *list = pipe_list;
5587 struct pipe_list *tmp;
5588
5589 if (list->fptr == fptr) {
5590 pipe_list = list->next;
5591 free(list);
5592 return;
5593 }
5594
5595 while (list->next) {
5596 if (list->next->fptr == fptr) {
5597 tmp = list->next;
5598 list->next = list->next->next;
5599 free(tmp);
5600 return;
5601 }
5602 list = list->next;
5603 }
5604 }
5605
5606 static void
5607 pipe_atexit(void)
5608 {
5609 struct pipe_list *list = pipe_list;
5610 struct pipe_list *tmp;
5611
5612 while (list) {
5613 tmp = list->next;
5614 rb_io_fptr_finalize(list->fptr);
5615 list = tmp;
5616 }
5617 }
5618
5619 static void
5620 pipe_finalize(rb_io_t *fptr, int noraise)
5621 {
5622 #if !defined(HAVE_FORK) && !defined(_WIN32)
5623 int status = 0;
5624 if (fptr->stdio_file) {
5625 status = pclose(fptr->stdio_file);
5626 }
5627 fptr->fd = -1;
5628 fptr->stdio_file = 0;
5629 rb_last_status_set(status, fptr->pid);
5630 #else
5631 fptr_finalize(fptr, noraise);
5632 #endif
5633 pipe_del_fptr(fptr);
5634 }
5635 #endif
5636
5637 void
5638 rb_io_synchronized(rb_io_t *fptr)
5639 {
5640 rb_io_check_initialized(fptr);
5641 fptr->mode |= FMODE_SYNC;
5642 }
5643
5644 void
5645 rb_io_unbuffered(rb_io_t *fptr)
5646 {
5647 rb_io_synchronized(fptr);
5648 }
5649
5650 int
5651 rb_pipe(int *pipes)
5652 {
5653 int ret;
5654 ret = rb_cloexec_pipe(pipes);
5655 if (ret == -1) {
5656 if (errno == EMFILE || errno == ENFILE) {
5657 rb_gc();
5658 ret = rb_cloexec_pipe(pipes);
5659 }
5660 }
5661 if (ret == 0) {
5662 rb_update_max_fd(pipes[0]);
5663 rb_update_max_fd(pipes[1]);
5664 }
5665 return ret;
5666 }
5667
5668 #ifdef _WIN32
5669 #define HAVE_SPAWNV 1
5670 #define spawnv(mode, cmd, args) rb_w32_uaspawn((mode), (cmd), (args))
5671 #define spawn(mode, cmd) rb_w32_uspawn((mode), (cmd), 0)
5672 #endif
5673
5674 #if defined(HAVE_FORK) || defined(HAVE_SPAWNV)
5675 struct popen_arg {
5676 VALUE execarg_obj;
5677 struct rb_execarg *eargp;
5678 int modef;
5679 int pair[2];
5680 int write_pair[2];
5681 };
5682 #endif
5683
5684 #ifdef HAVE_FORK
5685 static void
5686 popen_redirect(struct popen_arg *p)
5687 {
5688 if ((p->modef & FMODE_READABLE) && (p->modef & FMODE_WRITABLE)) {
5689 close(p->write_pair[1]);
5690 if (p->write_pair[0] != 0) {
5691 dup2(p->write_pair[0], 0);
5692 close(p->write_pair[0]);
5693 }
5694 close(p->pair[0]);
5695 if (p->pair[1] != 1) {
5696 dup2(p->pair[1], 1);
5697 close(p->pair[1]);
5698 }
5699 }
5700 else if (p->modef & FMODE_READABLE) {
5701 close(p->pair[0]);
5702 if (p->pair[1] != 1) {
5703 dup2(p->pair[1], 1);
5704 close(p->pair[1]);
5705 }
5706 }
5707 else {
5708 close(p->pair[1]);
5709 if (p->pair[0] != 0) {
5710 dup2(p->pair[0], 0);
5711 close(p->pair[0]);
5712 }
5713 }
5714 }
5715
5716 #if defined(__linux__)
5717 /* Linux /proc/self/status contains a line: "FDSize:\t<nnn>\n"
5718 * Since /proc may not be available, linux_get_maxfd is just a hint.
5719 * This function, linux_get_maxfd, must be async-signal-safe.
5720 * I.e. opendir() is not usable.
5721 *
5722 * Note that memchr() and memcmp is *not* async-signal-safe in POSIX.
5723 * However they are easy to re-implement in async-signal-safe manner.
5724 * (Also note that there is missing/memcmp.c.)
5725 */
5726 static int
5727 linux_get_maxfd(void)
5728 {
5729 int fd;
5730 char buf[4096], *p, *np, *e;
5731 ssize_t ss;
5732 fd = rb_cloexec_open("/proc/self/status", O_RDONLY|O_NOCTTY, 0);
5733 if (fd == -1) return -1;
5734 ss = read(fd, buf, sizeof(buf));
5735 if (ss == -1) goto err;
5736 p = buf;
5737 e = buf + ss;
5738 while ((int)sizeof("FDSize:\t0\n")-1 <= e-p &&
5739 (np = memchr(p, '\n', e-p)) != NULL) {
5740 if (memcmp(p, "FDSize:", sizeof("FDSize:")-1) == 0) {
5741 int fdsize;
5742 p += sizeof("FDSize:")-1;
5743 *np = '\0';
5744 fdsize = (int)ruby_strtoul(p, (char **)NULL, 10);
5745 close(fd);
5746 return fdsize;
5747 }
5748 p = np+1;
5749 }
5750 /* fall through */
5751
5752 err:
5753 close(fd);
5754 return -1;
5755 }
5756 #endif
5757
5758 /* This function should be async-signal-safe. */
5759 void
5760 rb_close_before_exec(int lowfd, int maxhint, VALUE noclose_fds)
5761 {
5762 int fd, ret;
5763 int max = (int)max_file_descriptor;
5764 #ifdef F_MAXFD
5765 /* F_MAXFD is available since NetBSD 2.0. */
5766 ret = fcntl(0, F_MAXFD); /* async-signal-safe */
5767 if (ret != -1)
5768 maxhint = max = ret;
5769 #elif defined(__linux__)
5770 ret = linux_get_maxfd();
5771 if (maxhint < ret)
5772 maxhint = ret;
5773 /* maxhint = max = ret; if (ret == -1) abort(); // test */
5774 #endif
5775 if (max < maxhint)
5776 max = maxhint;
5777 for (fd = lowfd; fd <= max; fd++) {
5778 if (!NIL_P(noclose_fds) &&
5779 RTEST(rb_hash_lookup(noclose_fds, INT2FIX(fd)))) /* async-signal-safe */
5780 continue;
5781 ret = fcntl(fd, F_GETFD); /* async-signal-safe */
5782 if (ret != -1 && !(ret & FD_CLOEXEC)) {
5783 fcntl(fd, F_SETFD, ret|FD_CLOEXEC); /* async-signal-safe */
5784 }
5785 #define CONTIGUOUS_CLOSED_FDS 20
5786 if (ret != -1) {
5787 if (max < fd + CONTIGUOUS_CLOSED_FDS)
5788 max = fd + CONTIGUOUS_CLOSED_FDS;
5789 }
5790 }
5791 }
5792
5793 static int
5794 popen_exec(void *pp, char *errmsg, size_t errmsg_len)
5795 {
5796 struct popen_arg *p = (struct popen_arg*)pp;
5797
5798 return rb_exec_async_signal_safe(p->eargp, errmsg, errmsg_len);
5799 }
5800 #endif
5801
5802 static VALUE
5803 pipe_open(VALUE execarg_obj, const char *modestr, int fmode, convconfig_t *convconfig)
5804 {
5805 struct rb_execarg *eargp = NIL_P(execarg_obj) ? NULL : rb_execarg_get(execarg_obj);
5806 VALUE prog = eargp ? (eargp->use_shell ? eargp->invoke.sh.shell_script : eargp->invoke.cmd.command_name) : Qfalse ;
5807 rb_pid_t pid = 0;
5808 rb_io_t *fptr;
5809 VALUE port;
5810 rb_io_t *write_fptr;
5811 VALUE write_port;
5812 #if defined(HAVE_FORK)
5813 int status;
5814 char errmsg[80] = { '\0' };
5815 #endif
5816 #if defined(HAVE_FORK) || defined(HAVE_SPAWNV)
5817 struct popen_arg arg;
5818 int e = 0;
5819 #endif
5820 #if defined(HAVE_SPAWNV)
5821 # if defined(HAVE_SPAWNVE)
5822 # define DO_SPAWN(cmd, args, envp) ((args) ? \
5823 spawnve(P_NOWAIT, (cmd), (args), (envp)) : \
5824 spawne(P_NOWAIT, (cmd), (envp)))
5825 # else
5826 # define DO_SPAWN(cmd, args, envp) ((args) ? \
5827 spawnv(P_NOWAIT, (cmd), (args)) : \
5828 spawn(P_NOWAIT, (cmd)))
5829 # endif
5830 # if !defined(HAVE_FORK)
5831 char **args = NULL;
5832 # if defined(HAVE_SPAWNVE)
5833 char **envp = NULL;
5834 # endif
5835 # endif
5836 #endif
5837 #if !defined(HAVE_FORK)
5838 struct rb_execarg sarg, *sargp = &sarg;
5839 #endif
5840 FILE *fp = 0;
5841 int fd = -1;
5842 int write_fd = -1;
5843 #if !defined(HAVE_FORK)
5844 const char *cmd = 0;
5845 #if !defined(HAVE_SPAWNV)
5846 int argc;
5847 VALUE *argv;
5848 #endif
5849
5850 if (prog)
5851 cmd = StringValueCStr(prog);
5852 #endif
5853
5854 #if defined(HAVE_FORK) || defined(HAVE_SPAWNV)
5855 arg.execarg_obj = execarg_obj;
5856 arg.eargp = eargp;
5857 arg.modef = fmode;
5858 arg.pair[0] = arg.pair[1] = -1;
5859 arg.write_pair[0] = arg.write_pair[1] = -1;
5860 # if !defined(HAVE_FORK)
5861 if (eargp && !eargp->use_shell) {
5862 args = ARGVSTR2ARGV(eargp->invoke.cmd.argv_str);
5863 }
5864 # endif
5865 switch (fmode & (FMODE_READABLE|FMODE_WRITABLE)) {
5866 case FMODE_READABLE|FMODE_WRITABLE:
5867 if (rb_pipe(arg.write_pair) < 0)
5868 rb_sys_fail_str(prog);
5869 if (rb_pipe(arg.pair) < 0) {
5870 int e = errno;
5871 close(arg.write_pair[0]);
5872 close(arg.write_pair[1]);
5873 errno = e;
5874 rb_sys_fail_str(prog);
5875 }
5876 if (eargp) {
5877 rb_execarg_addopt(execarg_obj, INT2FIX(0), INT2FIX(arg.write_pair[0]));
5878 rb_execarg_addopt(execarg_obj, INT2FIX(1), INT2FIX(arg.pair[1]));
5879 }
5880 break;
5881 case FMODE_READABLE:
5882 if (rb_pipe(arg.pair) < 0)
5883 rb_sys_fail_str(prog);
5884 if (eargp)
5885 rb_execarg_addopt(execarg_obj, INT2FIX(1), INT2FIX(arg.pair[1]));
5886 break;
5887 case FMODE_WRITABLE:
5888 if (rb_pipe(arg.pair) < 0)
5889 rb_sys_fail_str(prog);
5890 if (eargp)
5891 rb_execarg_addopt(execarg_obj, INT2FIX(0), INT2FIX(arg.pair[0]));
5892 break;
5893 default:
5894 rb_sys_fail_str(prog);
5895 }
5896 if (!NIL_P(execarg_obj)) {
5897 rb_execarg_fixup(execarg_obj);
5898 # if defined(HAVE_FORK)
5899 pid = rb_fork_async_signal_safe(&status, popen_exec, &arg, arg.eargp->redirect_fds, errmsg, sizeof(errmsg));
5900 # else
5901 rb_execarg_run_options(eargp, sargp, NULL, 0);
5902 # if defined(HAVE_SPAWNVE)
5903 if (eargp->envp_str) envp = (char **)RSTRING_PTR(eargp->envp_str);
5904 # endif
5905 while ((pid = DO_SPAWN(cmd, args, envp)) == -1) {
5906 /* exec failed */
5907 switch (e = errno) {
5908 case EAGAIN:
5909 # if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
5910 case EWOULDBLOCK:
5911 # endif
5912 rb_thread_sleep(1);
5913 continue;
5914 }
5915 break;
5916 }
5917 if (eargp)
5918 rb_execarg_run_options(sargp, NULL, NULL, 0);
5919 # endif
5920 }
5921 else {
5922 # if defined(HAVE_FORK)
5923 pid = rb_fork_ruby(&status);
5924 if (pid == 0) { /* child */
5925 rb_thread_atfork();
5926 popen_redirect(&arg);
5927 rb_io_synchronized(RFILE(orig_stdout)->fptr);
5928 rb_io_synchronized(RFILE(orig_stderr)->fptr);
5929 return Qnil;
5930 }
5931 # else
5932 rb_notimplement();
5933 # endif
5934 }
5935
5936 /* parent */
5937 if (pid == -1) {
5938 # if defined(HAVE_FORK)
5939 e = errno;
5940 # endif
5941 close(arg.pair[0]);
5942 close(arg.pair[1]);
5943 if ((fmode & (FMODE_READABLE|FMODE_WRITABLE)) == (FMODE_READABLE|FMODE_WRITABLE)) {
5944 close(arg.write_pair[0]);
5945 close(arg.write_pair[1]);
5946 }
5947 errno = e;
5948 # if defined(HAVE_FORK)
5949 if (errmsg[0])
5950 rb_sys_fail(errmsg);
5951 # endif
5952 rb_sys_fail_str(prog);
5953 }
5954 if ((fmode & FMODE_READABLE) && (fmode & FMODE_WRITABLE)) {
5955 close(arg.pair[1]);
5956 fd = arg.pair[0];
5957 close(arg.write_pair[0]);
5958 write_fd = arg.write_pair[1];
5959 }
5960 else if (fmode & FMODE_READABLE) {
5961 close(arg.pair[1]);
5962 fd = arg.pair[0];
5963 }
5964 else {
5965 close(arg.pair[0]);
5966 fd = arg.pair[1];
5967 }
5968 #else
5969 if (argc) {
5970 prog = rb_ary_join(rb_ary_new4(argc, argv), rb_str_new2(" "));
5971 cmd = StringValueCStr(prog);
5972 }
5973 if (!NIL_P(execarg_obj)) {
5974 rb_execarg_fixup(execarg_obj);
5975 rb_execarg_run_options(eargp, sargp, NULL, 0);
5976 }
5977 fp = popen(cmd, modestr);
5978 if (eargp)
5979 rb_execarg_run_options(sargp, NULL, NULL, 0);
5980 if (!fp) rb_sys_fail_path(prog);
5981 fd = fileno(fp);
5982 #endif
5983
5984 port = io_alloc(rb_cIO);
5985 MakeOpenFile(port, fptr);
5986 fptr->fd = fd;
5987 fptr->stdio_file = fp;
5988 fptr->mode = fmode | FMODE_SYNC|FMODE_DUPLEX;
5989 if (convconfig) {
5990 fptr->encs = *convconfig;
5991 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
5992 if (fptr->encs.ecflags & ECONV_DEFAULT_NEWLINE_DECORATOR) {
5993 fptr->encs.ecflags |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;
5994 }
5995 #endif
5996 }
5997 else {
5998 if (NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {
5999 fptr->encs.ecflags |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;
6000 }
6001 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
6002 if (NEED_NEWLINE_DECORATOR_ON_WRITE(fptr)) {
6003 fptr->encs.ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
6004 }
6005 #endif
6006 }
6007 fptr->pid = pid;
6008
6009 if (0 <= write_fd) {
6010 write_port = io_alloc(rb_cIO);
6011 MakeOpenFile(write_port, write_fptr);
6012 write_fptr->fd = write_fd;
6013 write_fptr->mode = (fmode & ~FMODE_READABLE)| FMODE_SYNC|FMODE_DUPLEX;
6014 fptr->mode &= ~FMODE_WRITABLE;
6015 fptr->tied_io_for_writing = write_port;
6016 rb_ivar_set(port, rb_intern("@tied_io_for_writing"), write_port);
6017 }
6018
6019 #if defined (__CYGWIN__) || !defined(HAVE_FORK)
6020 fptr->finalize = pipe_finalize;
6021 pipe_add_fptr(fptr);
6022 #endif
6023 return port;
6024 }
6025
6026 static int
6027 is_popen_fork(VALUE prog)
6028 {
6029 if (RSTRING_LEN(prog) == 1 && RSTRING_PTR(prog)[0] == '-') {
6030 #if !defined(HAVE_FORK)
6031 rb_raise(rb_eNotImpError,
6032 "fork() function is unimplemented on this machine");
6033 #else
6034 return TRUE;
6035 #endif
6036 }
6037 return FALSE;
6038 }
6039
6040 static VALUE
6041 pipe_open_s(VALUE prog, const char *modestr, int fmode, convconfig_t *convconfig)
6042 {
6043 int argc = 1;
6044 VALUE *argv = &prog;
6045 VALUE execarg_obj = Qnil;
6046
6047 if (!is_popen_fork(prog))
6048 execarg_obj = rb_execarg_new(argc, argv, TRUE);
6049 return pipe_open(execarg_obj, modestr, fmode, convconfig);
6050 }
6051
6052 /*
6053 * call-seq:
6054 * IO.popen([env,] cmd, mode="r" [, opt]) -> io
6055 * IO.popen([env,] cmd, mode="r" [, opt]) {|io| block } -> obj
6056 *
6057 * Runs the specified command as a subprocess; the subprocess's
6058 * standard input and output will be connected to the returned
6059 * <code>IO</code> object.
6060 *
6061 * The PID of the started process can be obtained by IO#pid method.
6062 *
6063 * _cmd_ is a string or an array as follows.
6064 *
6065 * cmd:
6066 * "-" : fork
6067 * commandline : command line string which is passed to a shell
6068 * [env, cmdname, arg1, ..., opts] : command name and zero or more arguments (no shell)
6069 * [env, [cmdname, argv0], arg1, ..., opts] : command name, argv[0] and zero or more arguments (no shell)
6070 * (env and opts are optional.)
6071 *
6072 * If _cmd_ is a +String+ ``<code>-</code>'',
6073 * then a new instance of Ruby is started as the subprocess.
6074 *
6075 * If <i>cmd</i> is an +Array+ of +String+,
6076 * then it will be used as the subprocess's +argv+ bypassing a shell.
6077 * The array can contains a hash at first for environments and
6078 * a hash at last for options similar to <code>spawn</code>.
6079 *
6080 * The default mode for the new file object is ``r'',
6081 * but <i>mode</i> may be set to any of the modes listed in the description for class IO.
6082 * The last argument <i>opt</i> qualifies <i>mode</i>.
6083 *
6084 * # set IO encoding
6085 * IO.popen("nkf -e filename", :external_encoding=>"EUC-JP") {|nkf_io|
6086 * euc_jp_string = nkf_io.read
6087 * }
6088 *
6089 * # merge standard output and standard error using
6090 * # spawn option. See the document of Kernel.spawn.
6091 * IO.popen(["ls", "/", :err=>[:child, :out]]) {|ls_io|
6092 * ls_result_with_error = ls_io.read
6093 * }
6094 *
6095 * # spawn options can be mixed with IO options
6096 * IO.popen(["ls", "/"], :err=>[:child, :out]) {|ls_io|
6097 * ls_result_with_error = ls_io.read
6098 * }
6099 *
6100 * Raises exceptions which <code>IO.pipe</code> and
6101 * <code>Kernel.spawn</code> raise.
6102 *
6103 * If a block is given, Ruby will run the command as a child connected
6104 * to Ruby with a pipe. Ruby's end of the pipe will be passed as a
6105 * parameter to the block.
6106 * At the end of block, Ruby close the pipe and sets <code>$?</code>.
6107 * In this case <code>IO.popen</code> returns
6108 * the value of the block.
6109 *
6110 * If a block is given with a _cmd_ of ``<code>-</code>'',
6111 * the block will be run in two separate processes: once in the parent,
6112 * and once in a child. The parent process will be passed the pipe
6113 * object as a parameter to the block, the child version of the block
6114 * will be passed <code>nil</code>, and the child's standard in and
6115 * standard out will be connected to the parent through the pipe. Not
6116 * available on all platforms.
6117 *
6118 * f = IO.popen("uname")
6119 * p f.readlines
6120 * f.close
6121 * puts "Parent is #{Process.pid}"
6122 * IO.popen("date") { |f| puts f.gets }
6123 * IO.popen("-") {|f| $stderr.puts "#{Process.pid} is here, f is #{f.inspect}"}
6124 * p $?
6125 * IO.popen(%w"sed -e s|^|<foo>| -e s&$&;zot;&", "r+") {|f|
6126 * f.puts "bar"; f.close_write; puts f.gets
6127 * }
6128 *
6129 * <em>produces:</em>
6130 *
6131 * ["Linux\n"]
6132 * Parent is 21346
6133 * Thu Jan 15 22:41:19 JST 2009
6134 * 21346 is here, f is #<IO:fd 3>
6135 * 21352 is here, f is nil
6136 * #<Process::Status: pid 21352 exit 0>
6137 * <foo>bar;zot;
6138 */
6139
6140 static VALUE
6141 rb_io_s_popen(int argc, VALUE *argv, VALUE klass)
6142 {
6143 const char *modestr;
6144 VALUE pname, pmode = Qnil, port, tmp, opt = Qnil, env = Qnil, execarg_obj = Qnil;
6145 int oflags, fmode;
6146 convconfig_t convconfig;
6147
6148 if (argc > 1 && !NIL_P(opt = rb_check_hash_type(argv[argc-1]))) --argc;
6149 if (argc > 1 && !NIL_P(env = rb_check_hash_type(argv[0]))) --argc, ++argv;
6150 switch (argc) {
6151 case 2:
6152 pmode = argv[1];
6153 case 1:
6154 pname = argv[0];
6155 break;
6156 default:
6157 {
6158 int ex = !NIL_P(opt);
6159 rb_error_arity(argc + ex, 1 + ex, 2 + ex);
6160 }
6161 }
6162
6163 tmp = rb_check_array_type(pname);
6164 if (!NIL_P(tmp)) {
6165 long len = RARRAY_LEN(tmp);
6166 #if SIZEOF_LONG > SIZEOF_INT
6167 if (len > INT_MAX) {
6168 rb_raise(rb_eArgError, "too many arguments");
6169 }
6170 #endif
6171 tmp = rb_ary_dup(tmp);
6172 RBASIC_CLEAR_CLASS(tmp);
6173 execarg_obj = rb_execarg_new((int)len, RARRAY_PTR(tmp), FALSE);
6174 rb_ary_clear(tmp);
6175 }
6176 else {
6177 SafeStringValue(pname);
6178 execarg_obj = Qnil;
6179 if (!is_popen_fork(pname))
6180 execarg_obj = rb_execarg_new(1, &pname, TRUE);
6181 }
6182 if (!NIL_P(execarg_obj)) {
6183 if (!NIL_P(opt))
6184 opt = rb_execarg_extract_options(execarg_obj, opt);
6185 if (!NIL_P(env))
6186 rb_execarg_setenv(execarg_obj, env);
6187 }
6188 rb_io_extract_modeenc(&pmode, 0, opt, &oflags, &fmode, &convconfig);
6189 modestr = rb_io_oflags_modestr(oflags);
6190
6191 port = pipe_open(execarg_obj, modestr, fmode, &convconfig);
6192 if (NIL_P(port)) {
6193 /* child */
6194 if (rb_block_given_p()) {
6195 rb_yield(Qnil);
6196 rb_io_flush(rb_stdout);
6197 rb_io_flush(rb_stderr);
6198 _exit(0);
6199 }
6200 return Qnil;
6201 }
6202 RBASIC_SET_CLASS(port, klass);
6203 if (rb_block_given_p()) {
6204 return rb_ensure(rb_yield, port, io_close, port);
6205 }
6206 return port;
6207 }
6208
6209 static void
6210 rb_scan_open_args(int argc, const VALUE *argv,
6211 VALUE *fname_p, int *oflags_p, int *fmode_p,
6212 convconfig_t *convconfig_p, mode_t *perm_p)
6213 {
6214 VALUE opt, fname, vmode, vperm;
6215 int oflags, fmode;
6216 mode_t perm;
6217
6218 argc = rb_scan_args(argc, argv, "12:", &fname, &vmode, &vperm, &opt);
6219 FilePathValue(fname);
6220
6221 rb_io_extract_modeenc(&vmode, &vperm, opt, &oflags, &fmode, convconfig_p);
6222
6223 perm = NIL_P(vperm) ? 0666 : NUM2MODET(vperm);
6224
6225 *fname_p = fname;
6226 *oflags_p = oflags;
6227 *fmode_p = fmode;
6228 *perm_p = perm;
6229 }
6230
6231 static VALUE
6232 rb_open_file(int argc, const VALUE *argv, VALUE io)
6233 {
6234 VALUE fname;
6235 int oflags, fmode;
6236 convconfig_t convconfig;
6237 mode_t perm;
6238
6239 rb_scan_open_args(argc, argv, &fname, &oflags, &fmode, &convconfig, &perm);
6240 rb_file_open_generic(io, fname, oflags, fmode, &convconfig, perm);
6241
6242 return io;
6243 }
6244
6245
6246 /*
6247 * Document-method: File::open
6248 *
6249 * call-seq:
6250 * File.open(filename, mode="r" [, opt]) -> file
6251 * File.open(filename [, mode [, perm]] [, opt]) -> file
6252 * File.open(filename, mode="r" [, opt]) {|file| block } -> obj
6253 * File.open(filename [, mode [, perm]] [, opt]) {|file| block } -> obj
6254 *
6255 * With no associated block, <code>File.open</code> is a synonym for
6256 * File.new. If the optional code block is given, it will
6257 * be passed the opened +file+ as an argument and the File object will
6258 * automatically be closed when the block terminates. The value of the block
6259 * will be returned from <code>File.open</code>.
6260 *
6261 * If a file is being created, its initial permissions may be set using the
6262 * +perm+ parameter. See File.new for further discussion.
6263 *
6264 * See IO.new for a description of the +mode+ and +opt+ parameters.
6265 */
6266
6267 /*
6268 * Document-method: IO::open
6269 *
6270 * call-seq:
6271 * IO.open(fd, mode="r" [, opt]) -> io
6272 * IO.open(fd, mode="r" [, opt]) { |io| block } -> obj
6273 *
6274 * With no associated block, <code>IO.open</code> is a synonym for IO.new. If
6275 * the optional code block is given, it will be passed +io+ as an argument,
6276 * and the IO object will automatically be closed when the block terminates.
6277 * In this instance, IO.open returns the value of the block.
6278 *
6279 * See IO.new for a description of the +fd+, +mode+ and +opt+ parameters.
6280 */
6281
6282 static VALUE
6283 rb_io_s_open(int argc, VALUE *argv, VALUE klass)
6284 {
6285 VALUE io = rb_class_new_instance(argc, argv, klass);
6286
6287 if (rb_block_given_p()) {
6288 return rb_ensure(rb_yield, io, io_close, io);
6289 }
6290
6291 return io;
6292 }
6293
6294 /*
6295 * call-seq:
6296 * IO.sysopen(path, [mode, [perm]]) -> fixnum
6297 *
6298 * Opens the given path, returning the underlying file descriptor as a
6299 * <code>Fixnum</code>.
6300 *
6301 * IO.sysopen("testfile") #=> 3
6302 */
6303
6304 static VALUE
6305 rb_io_s_sysopen(int argc, VALUE *argv)
6306 {
6307 VALUE fname, vmode, vperm;
6308 VALUE intmode;
6309 int oflags, fd;
6310 mode_t perm;
6311
6312 rb_scan_args(argc, argv, "12", &fname, &vmode, &vperm);
6313 FilePathValue(fname);
6314
6315 if (NIL_P(vmode))
6316 oflags = O_RDONLY;
6317 else if (!NIL_P(intmode = rb_check_to_integer(vmode, "to_int")))
6318 oflags = NUM2INT(intmode);
6319 else {
6320 SafeStringValue(vmode);
6321 oflags = rb_io_modestr_oflags(StringValueCStr(vmode));
6322 }
6323 if (NIL_P(vperm)) perm = 0666;
6324 else perm = NUM2MODET(vperm);
6325
6326 RB_GC_GUARD(fname) = rb_str_new4(fname);
6327 fd = rb_sysopen(fname, oflags, perm);
6328 return INT2NUM(fd);
6329 }
6330
6331 static VALUE
6332 check_pipe_command(VALUE filename_or_command)
6333 {
6334 char *s = RSTRING_PTR(filename_or_command);
6335 long l = RSTRING_LEN(filename_or_command);
6336 char *e = s + l;
6337 int chlen;
6338
6339 if (rb_enc_ascget(s, e, &chlen, rb_enc_get(filename_or_command)) == '|') {
6340 VALUE cmd = rb_str_new(s+chlen, l-chlen);
6341 OBJ_INFECT(cmd, filename_or_command);
6342 return cmd;
6343 }
6344 return Qnil;
6345 }
6346
6347 /*
6348 * call-seq:
6349 * open(path [, mode [, perm]] [, opt]) -> io or nil
6350 * open(path [, mode [, perm]] [, opt]) {|io| block } -> obj
6351 *
6352 * Creates an IO object connected to the given stream, file, or subprocess.
6353 *
6354 * If +path+ does not start with a pipe character (<code>|</code>), treat it
6355 * as the name of a file to open using the specified mode (defaulting to
6356 * "r").
6357 *
6358 * The +mode+ is either a string or an integer. If it is an integer, it
6359 * must be bitwise-or of open(2) flags, such as File::RDWR or File::EXCL. If
6360 * it is a string, it is either "fmode", "fmode:ext_enc", or
6361 * "fmode:ext_enc:int_enc".
6362 *
6363 * See the documentation of IO.new for full documentation of the +mode+ string
6364 * directives.
6365 *
6366 * If a file is being created, its initial permissions may be set using the
6367 * +perm+ parameter. See File.new and the open(2) and chmod(2) man pages for
6368 * a description of permissions.
6369 *
6370 * If a block is specified, it will be invoked with the IO object as a
6371 * parameter, and the IO will be automatically closed when the block
6372 * terminates. The call returns the value of the block.
6373 *
6374 * If +path+ starts with a pipe character (<code>"|"</code>), a subprocess is
6375 * created, connected to the caller by a pair of pipes. The returned IO
6376 * object may be used to write to the standard input and read from the
6377 * standard output of this subprocess.
6378 *
6379 * If the command following the pipe is a single minus sign
6380 * (<code>"|-"</code>), Ruby forks, and this subprocess is connected to the
6381 * parent. If the command is not <code>"-"</code>, the subprocess runs the
6382 * command.
6383 *
6384 * When the subprocess is ruby (opened via <code>"|-"</code>), the +open+
6385 * call returns +nil+. If a block is associated with the open call, that
6386 * block will run twice --- once in the parent and once in the child.
6387 *
6388 * The block parameter will be an IO object in the parent and +nil+ in the
6389 * child. The parent's +IO+ object will be connected to the child's $stdin
6390 * and $stdout. The subprocess will be terminated at the end of the block.
6391 *
6392 * === Examples
6393 *
6394 * Reading from "testfile":
6395 *
6396 * open("testfile") do |f|
6397 * print f.gets
6398 * end
6399 *
6400 * Produces:
6401 *
6402 * This is line one
6403 *
6404 * Open a subprocess and read its output:
6405 *
6406 * cmd = open("|date")
6407 * print cmd.gets
6408 * cmd.close
6409 *
6410 * Produces:
6411 *
6412 * Wed Apr 9 08:56:31 CDT 2003
6413 *
6414 * Open a subprocess running the same Ruby program:
6415 *
6416 * f = open("|-", "w+")
6417 * if f == nil
6418 * puts "in Child"
6419 * exit
6420 * else
6421 * puts "Got: #{f.gets}"
6422 * end
6423 *
6424 * Produces:
6425 *
6426 * Got: in Child
6427 *
6428 * Open a subprocess using a block to receive the IO object:
6429 *
6430 * open "|-" do |f|
6431 * if f then
6432 * # parent process
6433 * puts "Got: #{f.gets}"
6434 * else
6435 * # child process
6436 * puts "in Child"
6437 * end
6438 * end
6439 *
6440 * Produces:
6441 *
6442 * Got: in Child
6443 */
6444
6445 static VALUE
6446 rb_f_open(int argc, VALUE *argv)
6447 {
6448 ID to_open = 0;
6449 int redirect = FALSE;
6450
6451 if (argc >= 1) {
6452 CONST_ID(to_open, "to_open");
6453 if (rb_respond_to(argv[0], to_open)) {
6454 redirect = TRUE;
6455 }
6456 else {
6457 VALUE tmp = argv[0];
6458 FilePathValue(tmp);
6459 if (NIL_P(tmp)) {
6460 redirect = TRUE;
6461 }
6462 else {
6463 VALUE cmd = check_pipe_command(tmp);
6464 if (!NIL_P(cmd)) {
6465 argv[0] = cmd;
6466 return rb_io_s_popen(argc, argv, rb_cIO);
6467 }
6468 }
6469 }
6470 }
6471 if (redirect) {
6472 VALUE io = rb_funcall2(argv[0], to_open, argc-1, argv+1);
6473
6474 if (rb_block_given_p()) {
6475 return rb_ensure(rb_yield, io, io_close, io);
6476 }
6477 return io;
6478 }
6479 return rb_io_s_open(argc, argv, rb_cFile);
6480 }
6481
6482 static VALUE
6483 rb_io_open(VALUE filename, VALUE vmode, VALUE vperm, VALUE opt)
6484 {
6485 VALUE cmd;
6486 int oflags, fmode;
6487 convconfig_t convconfig;
6488 mode_t perm;
6489
6490 rb_io_extract_modeenc(&vmode, &vperm, opt, &oflags, &fmode, &convconfig);
6491 perm = NIL_P(vperm) ? 0666 : NUM2MODET(vperm);
6492
6493 if (!NIL_P(cmd = check_pipe_command(filename))) {
6494 return pipe_open_s(cmd, rb_io_oflags_modestr(oflags), fmode, &convconfig);
6495 }
6496 else {
6497 return rb_file_open_generic(io_alloc(rb_cFile), filename,
6498 oflags, fmode, &convconfig, perm);
6499 }
6500 }
6501
6502 static VALUE
6503 rb_io_open_with_args(int argc, const VALUE *argv)
6504 {
6505 VALUE io;
6506
6507 io = io_alloc(rb_cFile);
6508 rb_open_file(argc, argv, io);
6509 return io;
6510 }
6511
6512 static VALUE
6513 io_reopen(VALUE io, VALUE nfile)
6514 {
6515 rb_io_t *fptr, *orig;
6516 int fd, fd2;
6517 off_t pos = 0;
6518
6519 nfile = rb_io_get_io(nfile);
6520 GetOpenFile(io, fptr);
6521 GetOpenFile(nfile, orig);
6522
6523 if (fptr == orig) return io;
6524 if (IS_PREP_STDIO(fptr)) {
6525 if ((fptr->stdio_file == stdin && !(orig->mode & FMODE_READABLE)) ||
6526 (fptr->stdio_file == stdout && !(orig->mode & FMODE_WRITABLE)) ||
6527 (fptr->stdio_file == stderr && !(orig->mode & FMODE_WRITABLE))) {
6528 rb_raise(rb_eArgError,
6529 "%s can't change access mode from \"%s\" to \"%s\"",
6530 PREP_STDIO_NAME(fptr), rb_io_fmode_modestr(fptr->mode),
6531 rb_io_fmode_modestr(orig->mode));
6532 }
6533 }
6534 if (fptr->mode & FMODE_WRITABLE) {
6535 if (io_fflush(fptr) < 0)
6536 rb_sys_fail(0);
6537 }
6538 else {
6539 io_tell(fptr);
6540 }
6541 if (orig->mode & FMODE_READABLE) {
6542 pos = io_tell(orig);
6543 }
6544 if (orig->mode & FMODE_WRITABLE) {
6545 if (io_fflush(orig) < 0)
6546 rb_sys_fail(0);
6547 }
6548
6549 /* copy rb_io_t structure */
6550 fptr->mode = orig->mode | (fptr->mode & FMODE_PREP);
6551 fptr->pid = orig->pid;
6552 fptr->lineno = orig->lineno;
6553 if (RTEST(orig->pathv)) fptr->pathv = orig->pathv;
6554 else if (!IS_PREP_STDIO(fptr)) fptr->pathv = Qnil;
6555 fptr->finalize = orig->finalize;
6556 #if defined (__CYGWIN__) || !defined(HAVE_FORK)
6557 if (fptr->finalize == pipe_finalize)
6558 pipe_add_fptr(fptr);
6559 #endif
6560
6561 fd = fptr->fd;
6562 fd2 = orig->fd;
6563 if (fd != fd2) {
6564 if (IS_PREP_STDIO(fptr) || fd <= 2 || !fptr->stdio_file) {
6565 /* need to keep FILE objects of stdin, stdout and stderr */
6566 if (rb_cloexec_dup2(fd2, fd) < 0)
6567 rb_sys_fail_path(orig->pathv);
6568 rb_update_max_fd(fd);
6569 }
6570 else {
6571 fclose(fptr->stdio_file);
6572 fptr->stdio_file = 0;
6573 fptr->fd = -1;
6574 if (rb_cloexec_dup2(fd2, fd) < 0)
6575 rb_sys_fail_path(orig->pathv);
6576 rb_update_max_fd(fd);
6577 fptr->fd = fd;
6578 }
6579 rb_thread_fd_close(fd);
6580 if ((orig->mode & FMODE_READABLE) && pos >= 0) {
6581 if (io_seek(fptr, pos, SEEK_SET) < 0 && errno) {
6582 rb_sys_fail_path(fptr->pathv);
6583 }
6584 if (io_seek(orig, pos, SEEK_SET) < 0 && errno) {
6585 rb_sys_fail_path(orig->pathv);
6586 }
6587 }
6588 }
6589
6590 if (fptr->mode & FMODE_BINMODE) {
6591 rb_io_binmode(io);
6592 }
6593
6594 RBASIC_SET_CLASS(io, rb_obj_class(nfile));
6595 return io;
6596 }
6597
6598 /*
6599 * call-seq:
6600 * ios.reopen(other_IO) -> ios
6601 * ios.reopen(path, mode_str) -> ios
6602 *
6603 * Reassociates <em>ios</em> with the I/O stream given in
6604 * <i>other_IO</i> or to a new stream opened on <i>path</i>. This may
6605 * dynamically change the actual class of this stream.
6606 *
6607 * f1 = File.new("testfile")
6608 * f2 = File.new("testfile")
6609 * f2.readlines[0] #=> "This is line one\n"
6610 * f2.reopen(f1) #=> #<File:testfile>
6611 * f2.readlines[0] #=> "This is line one\n"
6612 */
6613
6614 static VALUE
6615 rb_io_reopen(int argc, VALUE *argv, VALUE file)
6616 {
6617 VALUE fname, nmode, opt;
6618 int oflags;
6619 rb_io_t *fptr;
6620
6621 if (rb_scan_args(argc, argv, "11:", &fname, &nmode, &opt) == 1) {
6622 VALUE tmp = rb_io_check_io(fname);
6623 if (!NIL_P(tmp)) {
6624 return io_reopen(file, tmp);
6625 }
6626 }
6627
6628 FilePathValue(fname);
6629 rb_io_taint_check(file);
6630 fptr = RFILE(file)->fptr;
6631 if (!fptr) {
6632 fptr = RFILE(file)->fptr = ALLOC(rb_io_t);
6633 MEMZERO(fptr, rb_io_t, 1);
6634 }
6635
6636 if (!NIL_P(nmode) || !NIL_P(opt)) {
6637 int fmode;
6638 convconfig_t convconfig;
6639
6640 rb_io_extract_modeenc(&nmode, 0, opt, &oflags, &fmode, &convconfig);
6641 if (IS_PREP_STDIO(fptr) &&
6642 ((fptr->mode & FMODE_READWRITE) & (fmode & FMODE_READWRITE)) !=
6643 (fptr->mode & FMODE_READWRITE)) {
6644 rb_raise(rb_eArgError,
6645 "%s can't change access mode from \"%s\" to \"%s\"",
6646 PREP_STDIO_NAME(fptr), rb_io_fmode_modestr(fptr->mode),
6647 rb_io_fmode_modestr(fmode));
6648 }
6649 fptr->mode = fmode;
6650 fptr->encs = convconfig;
6651 }
6652 else {
6653 oflags = rb_io_fmode_oflags(fptr->mode);
6654 }
6655
6656 fptr->pathv = rb_str_new_frozen(fname);
6657 if (fptr->fd < 0) {
6658 fptr->fd = rb_sysopen(fptr->pathv, oflags, 0666);
6659 fptr->stdio_file = 0;
6660 return file;
6661 }
6662
6663 if (fptr->mode & FMODE_WRITABLE) {
6664 if (io_fflush(fptr) < 0)
6665 rb_sys_fail(0);
6666 }
6667 fptr->rbuf.off = fptr->rbuf.len = 0;
6668
6669 if (fptr->stdio_file) {
6670 if (freopen(RSTRING_PTR(fptr->pathv), rb_io_oflags_modestr(oflags), fptr->stdio_file) == 0) {
6671 rb_sys_fail_path(fptr->pathv);
6672 }
6673 fptr->fd = fileno(fptr->stdio_file);
6674 rb_fd_fix_cloexec(fptr->fd);
6675 #ifdef USE_SETVBUF
6676 if (setvbuf(fptr->stdio_file, NULL, _IOFBF, 0) != 0)
6677 rb_warn("setvbuf() can't be honoured for %"PRIsVALUE, fptr->pathv);
6678 #endif
6679 if (fptr->stdio_file == stderr) {
6680 if (setvbuf(fptr->stdio_file, NULL, _IONBF, BUFSIZ) != 0)
6681 rb_warn("setvbuf() can't be honoured for %"PRIsVALUE, fptr->pathv);
6682 }
6683 else if (fptr->stdio_file == stdout && isatty(fptr->fd)) {
6684 if (setvbuf(fptr->stdio_file, NULL, _IOLBF, BUFSIZ) != 0)
6685 rb_warn("setvbuf() can't be honoured for %"PRIsVALUE, fptr->pathv);
6686 }
6687 }
6688 else {
6689 int tmpfd = rb_sysopen(fptr->pathv, oflags, 0666);
6690 int err = 0;
6691 if (rb_cloexec_dup2(tmpfd, fptr->fd) < 0)
6692 err = errno;
6693 (void)close(tmpfd);
6694 if (err) {
6695 rb_syserr_fail_path(err, fptr->pathv);
6696 }
6697 }
6698
6699 return file;
6700 }
6701
6702 /* :nodoc: */
6703 static VALUE
6704 rb_io_init_copy(VALUE dest, VALUE io)
6705 {
6706 rb_io_t *fptr, *orig;
6707 int fd;
6708 VALUE write_io;
6709 off_t pos;
6710
6711 io = rb_io_get_io(io);
6712 if (!OBJ_INIT_COPY(dest, io)) return dest;
6713 GetOpenFile(io, orig);
6714 MakeOpenFile(dest, fptr);
6715
6716 rb_io_flush(io);
6717
6718 /* copy rb_io_t structure */
6719 fptr->mode = orig->mode & ~FMODE_PREP;
6720 fptr->encs = orig->encs;
6721 fptr->pid = orig->pid;
6722 fptr->lineno = orig->lineno;
6723 if (!NIL_P(orig->pathv)) fptr->pathv = orig->pathv;
6724 fptr->finalize = orig->finalize;
6725 #if defined (__CYGWIN__) || !defined(HAVE_FORK)
6726 if (fptr->finalize == pipe_finalize)
6727 pipe_add_fptr(fptr);
6728 #endif
6729
6730 fd = ruby_dup(orig->fd);
6731 fptr->fd = fd;
6732 pos = io_tell(orig);
6733 if (0 <= pos)
6734 io_seek(fptr, pos, SEEK_SET);
6735 if (fptr->mode & FMODE_BINMODE) {
6736 rb_io_binmode(dest);
6737 }
6738
6739 write_io = GetWriteIO(io);
6740 if (io != write_io) {
6741 write_io = rb_obj_dup(write_io);
6742 fptr->tied_io_for_writing = write_io;
6743 rb_ivar_set(dest, rb_intern("@tied_io_for_writing"), write_io);
6744 }
6745
6746 return dest;
6747 }
6748
6749 /*
6750 * call-seq:
6751 * ios.printf(format_string [, obj, ...]) -> nil
6752 *
6753 * Formats and writes to <em>ios</em>, converting parameters under
6754 * control of the format string. See <code>Kernel#sprintf</code>
6755 * for details.
6756 */
6757
6758 VALUE
6759 rb_io_printf(int argc, VALUE *argv, VALUE out)
6760 {
6761 rb_io_write(out, rb_f_sprintf(argc, argv));
6762 return Qnil;
6763 }
6764
6765 /*
6766 * call-seq:
6767 * printf(io, string [, obj ... ]) -> nil
6768 * printf(string [, obj ... ]) -> nil
6769 *
6770 * Equivalent to:
6771 * io.write(sprintf(string, obj, ...))
6772 * or
6773 * $stdout.write(sprintf(string, obj, ...))
6774 */
6775
6776 static VALUE
6777 rb_f_printf(int argc, VALUE *argv)
6778 {
6779 VALUE out;
6780
6781 if (argc == 0) return Qnil;
6782 if (RB_TYPE_P(argv[0], T_STRING)) {
6783 out = rb_stdout;
6784 }
6785 else {
6786 out = argv[0];
6787 argv++;
6788 argc--;
6789 }
6790 rb_io_write(out, rb_f_sprintf(argc, argv));
6791
6792 return Qnil;
6793 }
6794
6795 /*
6796 * call-seq:
6797 * ios.print() -> nil
6798 * ios.print(obj, ...) -> nil
6799 *
6800 * Writes the given object(s) to <em>ios</em>. The stream must be
6801 * opened for writing. If the output field separator (<code>$,</code>)
6802 * is not <code>nil</code>, it will be inserted between each object.
6803 * If the output record separator (<code>$\</code>)
6804 * is not <code>nil</code>, it will be appended to the output. If no
6805 * arguments are given, prints <code>$_</code>. Objects that aren't
6806 * strings will be converted by calling their <code>to_s</code> method.
6807 * With no argument, prints the contents of the variable <code>$_</code>.
6808 * Returns <code>nil</code>.
6809 *
6810 * $stdout.print("This is ", 100, " percent.\n")
6811 *
6812 * <em>produces:</em>
6813 *
6814 * This is 100 percent.
6815 */
6816
6817 VALUE
6818 rb_io_print(int argc, VALUE *argv, VALUE out)
6819 {
6820 int i;
6821 VALUE line;
6822
6823 /* if no argument given, print `$_' */
6824 if (argc == 0) {
6825 argc = 1;
6826 line = rb_lastline_get();
6827 argv = &line;
6828 }
6829 for (i=0; i<argc; i++) {
6830 if (!NIL_P(rb_output_fs) && i>0) {
6831 rb_io_write(out, rb_output_fs);
6832 }
6833 rb_io_write(out, argv[i]);
6834 }
6835 if (argc > 0 && !NIL_P(rb_output_rs)) {
6836 rb_io_write(out, rb_output_rs);
6837 }
6838
6839 return Qnil;
6840 }
6841
6842 /*
6843 * call-seq:
6844 * print(obj, ...) -> nil
6845 *
6846 * Prints each object in turn to <code>$stdout</code>. If the output
6847 * field separator (<code>$,</code>) is not +nil+, its
6848 * contents will appear between each field. If the output record
6849 * separator (<code>$\</code>) is not +nil+, it will be
6850 * appended to the output. If no arguments are given, prints
6851 * <code>$_</code>. Objects that aren't strings will be converted by
6852 * calling their <code>to_s</code> method.
6853 *
6854 * print "cat", [1,2,3], 99, "\n"
6855 * $, = ", "
6856 * $\ = "\n"
6857 * print "cat", [1,2,3], 99
6858 *
6859 * <em>produces:</em>
6860 *
6861 * cat12399
6862 * cat, 1, 2, 3, 99
6863 */
6864
6865 static VALUE
6866 rb_f_print(int argc, VALUE *argv)
6867 {
6868 rb_io_print(argc, argv, rb_stdout);
6869 return Qnil;
6870 }
6871
6872 /*
6873 * call-seq:
6874 * ios.putc(obj) -> obj
6875 *
6876 * If <i>obj</i> is <code>Numeric</code>, write the character whose code is
6877 * the least-significant byte of <i>obj</i>, otherwise write the first byte
6878 * of the string representation of <i>obj</i> to <em>ios</em>. Note: This
6879 * method is not safe for use with multi-byte characters as it will truncate
6880 * them.
6881 *
6882 * $stdout.putc "A"
6883 * $stdout.putc 65
6884 *
6885 * <em>produces:</em>
6886 *
6887 * AA
6888 */
6889
6890 static VALUE
6891 rb_io_putc(VALUE io, VALUE ch)
6892 {
6893 VALUE str;
6894 if (RB_TYPE_P(ch, T_STRING)) {
6895 str = rb_str_substr(ch, 0, 1);
6896 }
6897 else {
6898 char c = NUM2CHR(ch);
6899 str = rb_str_new(&c, 1);
6900 }
6901 rb_io_write(io, str);
6902 return ch;
6903 }
6904
6905 /*
6906 * call-seq:
6907 * putc(int) -> int
6908 *
6909 * Equivalent to:
6910 *
6911 * $stdout.putc(int)
6912 *
6913 * Refer to the documentation for IO#putc for important information regarding
6914 * multi-byte characters.
6915 */
6916
6917 static VALUE
6918 rb_f_putc(VALUE recv, VALUE ch)
6919 {
6920 if (recv == rb_stdout) {
6921 return rb_io_putc(recv, ch);
6922 }
6923 return rb_funcall2(rb_stdout, rb_intern("putc"), 1, &ch);
6924 }
6925
6926
6927 static int
6928 str_end_with_asciichar(VALUE str, int c)
6929 {
6930 long len = RSTRING_LEN(str);
6931 const char *ptr = RSTRING_PTR(str);
6932 rb_encoding *enc = rb_enc_from_index(ENCODING_GET(str));
6933 int n;
6934
6935 if (len == 0) return 0;
6936 if ((n = rb_enc_mbminlen(enc)) == 1) {
6937 return ptr[len - 1] == c;
6938 }
6939 return rb_enc_ascget(ptr + ((len - 1) / n) * n, ptr + len, &n, enc) == c;
6940 }
6941
6942 static VALUE
6943 io_puts_ary(VALUE ary, VALUE out, int recur)
6944 {
6945 VALUE tmp;
6946 long i;
6947
6948 if (recur) {
6949 tmp = rb_str_new2("[...]");
6950 rb_io_puts(1, &tmp, out);
6951 return Qtrue;
6952 }
6953 ary = rb_check_array_type(ary);
6954 if (NIL_P(ary)) return Qfalse;
6955 for (i=0; i<RARRAY_LEN(ary); i++) {
6956 tmp = RARRAY_AREF(ary, i);
6957 rb_io_puts(1, &tmp, out);
6958 }
6959 return Qtrue;
6960 }
6961
6962 /*
6963 * call-seq:
6964 * ios.puts(obj, ...) -> nil
6965 *
6966 * Writes the given objects to <em>ios</em> as with
6967 * <code>IO#print</code>. Writes a record separator (typically a
6968 * newline) after any that do not already end with a newline sequence.
6969 * If called with an array argument, writes each element on a new line.
6970 * If called without arguments, outputs a single record separator.
6971 *
6972 * $stdout.puts("this", "is", "a", "test")
6973 *
6974 * <em>produces:</em>
6975 *
6976 * this
6977 * is
6978 * a
6979 * test
6980 */
6981
6982 VALUE
6983 rb_io_puts(int argc, VALUE *argv, VALUE out)
6984 {
6985 int i;
6986 VALUE line;
6987
6988 /* if no argument given, print newline. */
6989 if (argc == 0) {
6990 rb_io_write(out, rb_default_rs);
6991 return Qnil;
6992 }
6993 for (i=0; i<argc; i++) {
6994 if (RB_TYPE_P(argv[i], T_STRING)) {
6995 line = argv[i];
6996 goto string;
6997 }
6998 if (rb_exec_recursive(io_puts_ary, argv[i], out)) {
6999 continue;
7000 }
7001 line = rb_obj_as_string(argv[i]);
7002 string:
7003 rb_io_write(out, line);
7004 if (RSTRING_LEN(line) == 0 ||
7005 !str_end_with_asciichar(line, '\n')) {
7006 rb_io_write(out, rb_default_rs);
7007 }
7008 }
7009
7010 return Qnil;
7011 }
7012
7013 /*
7014 * call-seq:
7015 * puts(obj, ...) -> nil
7016 *
7017 * Equivalent to
7018 *
7019 * $stdout.puts(obj, ...)
7020 */
7021
7022 static VALUE
7023 rb_f_puts(int argc, VALUE *argv, VALUE recv)
7024 {
7025 if (recv == rb_stdout) {
7026 return rb_io_puts(argc, argv, recv);
7027 }
7028 return rb_funcall2(rb_stdout, rb_intern("puts"), argc, argv);
7029 }
7030
7031 void
7032 rb_p(VALUE obj) /* for debug print within C code */
7033 {
7034 VALUE str = rb_obj_as_string(rb_inspect(obj));
7035 if (RB_TYPE_P(rb_stdout, T_FILE) &&
7036 rb_method_basic_definition_p(CLASS_OF(rb_stdout), id_write)) {
7037 io_write(rb_stdout, str, 1);
7038 io_write(rb_stdout, rb_default_rs, 0);
7039 }
7040 else {
7041 rb_io_write(rb_stdout, str);
7042 rb_io_write(rb_stdout, rb_default_rs);
7043 }
7044 }
7045
7046 struct rb_f_p_arg {
7047 int argc;
7048 VALUE *argv;
7049 };
7050
7051 static VALUE
7052 rb_f_p_internal(VALUE arg)
7053 {
7054 struct rb_f_p_arg *arg1 = (struct rb_f_p_arg*)arg;
7055 int argc = arg1->argc;
7056 VALUE *argv = arg1->argv;
7057 int i;
7058 VALUE ret = Qnil;
7059
7060 for (i=0; i<argc; i++) {
7061 rb_p(argv[i]);
7062 }
7063 if (argc == 1) {
7064 ret = argv[0];
7065 }
7066 else if (argc > 1) {
7067 ret = rb_ary_new4(argc, argv);
7068 }
7069 if (RB_TYPE_P(rb_stdout, T_FILE)) {
7070 rb_io_flush(rb_stdout);
7071 }
7072 return ret;
7073 }
7074
7075 /*
7076 * call-seq:
7077 * p(obj) -> obj
7078 * p(obj1, obj2, ...) -> [obj, ...]
7079 * p() -> nil
7080 *
7081 * For each object, directly writes _obj_.+inspect+ followed by a
7082 * newline to the program's standard output.
7083 *
7084 * S = Struct.new(:name, :state)
7085 * s = S['dave', 'TX']
7086 * p s
7087 *
7088 * <em>produces:</em>
7089 *
7090 * #<S name="dave", state="TX">
7091 */
7092
7093 static VALUE
7094 rb_f_p(int argc, VALUE *argv, VALUE self)
7095 {
7096 struct rb_f_p_arg arg;
7097 arg.argc = argc;
7098 arg.argv = argv;
7099
7100 return rb_uninterruptible(rb_f_p_internal, (VALUE)&arg);
7101 }
7102
7103 /*
7104 * call-seq:
7105 * obj.display(port=$>) -> nil
7106 *
7107 * Prints <i>obj</i> on the given port (default <code>$></code>).
7108 * Equivalent to:
7109 *
7110 * def display(port=$>)
7111 * port.write self
7112 * end
7113 *
7114 * For example:
7115 *
7116 * 1.display
7117 * "cat".display
7118 * [ 4, 5, 6 ].display
7119 * puts
7120 *
7121 * <em>produces:</em>
7122 *
7123 * 1cat456
7124 */
7125
7126 static VALUE
7127 rb_obj_display(int argc, VALUE *argv, VALUE self)
7128 {
7129 VALUE out;
7130
7131 if (argc == 0) {
7132 out = rb_stdout;
7133 }
7134 else {
7135 rb_scan_args(argc, argv, "01", &out);
7136 }
7137 rb_io_write(out, self);
7138
7139 return Qnil;
7140 }
7141
7142 void
7143 rb_write_error2(const char *mesg, long len)
7144 {
7145 if (rb_stderr == orig_stderr || RFILE(orig_stderr)->fptr->fd < 0) {
7146 if (fwrite(mesg, sizeof(char), (size_t)len, stderr) < (size_t)len) {
7147 /* failed to write to stderr, what can we do? */
7148 return;
7149 }
7150 }
7151 else {
7152 rb_io_write(rb_stderr, rb_str_new(mesg, len));
7153 }
7154 }
7155
7156 void
7157 rb_write_error(const char *mesg)
7158 {
7159 rb_write_error2(mesg, strlen(mesg));
7160 }
7161
7162 void
7163 rb_write_error_str(VALUE mesg)
7164 {
7165 /* a stopgap measure for the time being */
7166 if (rb_stderr == orig_stderr || RFILE(orig_stderr)->fptr->fd < 0) {
7167 size_t len = (size_t)RSTRING_LEN(mesg);
7168 if (fwrite(RSTRING_PTR(mesg), sizeof(char), len, stderr) < len) {
7169 RB_GC_GUARD(mesg);
7170 return;
7171 }
7172 }
7173 else {
7174 /* may unlock GVL, and */
7175 rb_io_write(rb_stderr, mesg);
7176 }
7177 }
7178
7179 static void
7180 must_respond_to(ID mid, VALUE val, ID id)
7181 {
7182 if (!rb_respond_to(val, mid)) {
7183 rb_raise(rb_eTypeError, "%s must have %s method, %s given",
7184 rb_id2name(id), rb_id2name(mid),
7185 rb_obj_classname(val));
7186 }
7187 }
7188
7189 static void
7190 stdout_setter(VALUE val, ID id, VALUE *variable)
7191 {
7192 must_respond_to(id_write, val, id);
7193 *variable = val;
7194 }
7195
7196 static VALUE
7197 prep_io(int fd, int fmode, VALUE klass, const char *path)
7198 {
7199 rb_io_t *fp;
7200 VALUE io = io_alloc(klass);
7201
7202 MakeOpenFile(io, fp);
7203 fp->fd = fd;
7204 #ifdef __CYGWIN__
7205 if (!isatty(fd)) {
7206 fmode |= FMODE_BINMODE;
7207 setmode(fd, O_BINARY);
7208 }
7209 #endif
7210 fp->mode = fmode;
7211 io_check_tty(fp);
7212 if (path) fp->pathv = rb_obj_freeze(rb_str_new_cstr(path));
7213 rb_update_max_fd(fd);
7214
7215 return io;
7216 }
7217
7218 VALUE
7219 rb_io_fdopen(int fd, int oflags, const char *path)
7220 {
7221 VALUE klass = rb_cIO;
7222
7223 if (path && strcmp(path, "-")) klass = rb_cFile;
7224 return prep_io(fd, rb_io_oflags_fmode(oflags), klass, path);
7225 }
7226
7227 static VALUE
7228 prep_stdio(FILE *f, int fmode, VALUE klass, const char *path)
7229 {
7230 rb_io_t *fptr;
7231 VALUE io = prep_io(fileno(f), fmode|FMODE_PREP|DEFAULT_TEXTMODE, klass, path);
7232
7233 GetOpenFile(io, fptr);
7234 fptr->encs.ecflags |= ECONV_DEFAULT_NEWLINE_DECORATOR;
7235 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
7236 fptr->encs.ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
7237 if (fmode & FMODE_READABLE) {
7238 fptr->encs.ecflags |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;
7239 }
7240 #endif
7241 fptr->stdio_file = f;
7242
7243 return io;
7244 }
7245
7246 FILE *
7247 rb_io_stdio_file(rb_io_t *fptr)
7248 {
7249 if (!fptr->stdio_file) {
7250 int oflags = rb_io_fmode_oflags(fptr->mode);
7251 fptr->stdio_file = rb_fdopen(fptr->fd, rb_io_oflags_modestr(oflags));
7252 }
7253 return fptr->stdio_file;
7254 }
7255
7256 /*
7257 * call-seq:
7258 * IO.new(fd [, mode] [, opt]) -> io
7259 *
7260 * Returns a new IO object (a stream) for the given integer file descriptor
7261 * +fd+ and +mode+ string. +opt+ may be used to specify parts of +mode+ in a
7262 * more readable fashion. See also IO.sysopen and IO.for_fd.
7263 *
7264 * IO.new is called by various File and IO opening methods such as IO::open,
7265 * Kernel#open, and File::open.
7266 *
7267 * === Open Mode
7268 *
7269 * When +mode+ is an integer it must be combination of the modes defined in
7270 * File::Constants (+File::RDONLY+, +File::WRONLY | File::CREAT+). See the
7271 * open(2) man page for more information.
7272 *
7273 * When +mode+ is a string it must be in one of the following forms:
7274 *
7275 * fmode
7276 * fmode ":" ext_enc
7277 * fmode ":" ext_enc ":" int_enc
7278 * fmode ":" "BOM|UTF-*"
7279 *
7280 * +fmode+ is an IO open mode string, +ext_enc+ is the external encoding for
7281 * the IO and +int_enc+ is the internal encoding.
7282 *
7283 * ==== IO Open Mode
7284 *
7285 * Ruby allows the following open modes:
7286 *
7287 * "r" Read-only, starts at beginning of file (default mode).
7288 *
7289 * "r+" Read-write, starts at beginning of file.
7290 *
7291 * "w" Write-only, truncates existing file
7292 * to zero length or creates a new file for writing.
7293 *
7294 * "w+" Read-write, truncates existing file to zero length
7295 * or creates a new file for reading and writing.
7296 *
7297 * "a" Write-only, each write call appends data at end of file.
7298 * Creates a new file for writing if file does not exist.
7299 *
7300 * "a+" Read-write, each write call appends data at end of file.
7301 * Creates a new file for reading and writing if file does
7302 * not exist.
7303 *
7304 * The following modes must be used separately, and along with one or more of
7305 * the modes seen above.
7306 *
7307 * "b" Binary file mode
7308 * Suppresses EOL <-> CRLF conversion on Windows. And
7309 * sets external encoding to ASCII-8BIT unless explicitly
7310 * specified.
7311 *
7312 * "t" Text file mode
7313 *
7314 * When the open mode of original IO is read only, the mode cannot be
7315 * changed to be writable. Similarly, the open mode cannot be changed from
7316 * write only to readable.
7317 *
7318 * When such a change is attempted the error is raised in different locations
7319 * according to the platform.
7320 *
7321 * === IO Encoding
7322 *
7323 * When +ext_enc+ is specified, strings read will be tagged by the encoding
7324 * when reading, and strings output will be converted to the specified
7325 * encoding when writing.
7326 *
7327 * When +ext_enc+ and +int_enc+ are specified read strings will be converted
7328 * from +ext_enc+ to +int_enc+ upon input, and written strings will be
7329 * converted from +int_enc+ to +ext_enc+ upon output. See Encoding for
7330 * further details of transcoding on input and output.
7331 *
7332 * If "BOM|UTF-8", "BOM|UTF-16LE" or "BOM|UTF16-BE" are used, ruby checks for
7333 * a Unicode BOM in the input document to help determine the encoding. For
7334 * UTF-16 encodings the file open mode must be binary. When present, the BOM
7335 * is stripped and the external encoding from the BOM is used. When the BOM
7336 * is missing the given Unicode encoding is used as +ext_enc+. (The BOM-set
7337 * encoding option is case insensitive, so "bom|utf-8" is also valid.)
7338 *
7339 * === Options
7340 *
7341 * +opt+ can be used instead of +mode+ for improved readability. The
7342 * following keys are supported:
7343 *
7344 * :mode ::
7345 * Same as +mode+ parameter
7346 *
7347 * :\external_encoding ::
7348 * External encoding for the IO. "-" is a synonym for the default external
7349 * encoding.
7350 *
7351 * :\internal_encoding ::
7352 * Internal encoding for the IO. "-" is a synonym for the default internal
7353 * encoding.
7354 *
7355 * If the value is nil no conversion occurs.
7356 *
7357 * :encoding ::
7358 * Specifies external and internal encodings as "extern:intern".
7359 *
7360 * :textmode ::
7361 * If the value is truth value, same as "t" in argument +mode+.
7362 *
7363 * :binmode ::
7364 * If the value is truth value, same as "b" in argument +mode+.
7365 *
7366 * :autoclose ::
7367 * If the value is +false+, the +fd+ will be kept open after this IO
7368 * instance gets finalized.
7369 *
7370 * Also, +opt+ can have same keys in String#encode for controlling conversion
7371 * between the external encoding and the internal encoding.
7372 *
7373 * === Example 1
7374 *
7375 * fd = IO.sysopen("/dev/tty", "w")
7376 * a = IO.new(fd,"w")
7377 * $stderr.puts "Hello"
7378 * a.puts "World"
7379 *
7380 * Produces:
7381 *
7382 * Hello
7383 * World
7384 *
7385 * === Example 2
7386 *
7387 * require 'fcntl'
7388 *
7389 * fd = STDERR.fcntl(Fcntl::F_DUPFD)
7390 * io = IO.new(fd, mode: 'w:UTF-16LE', cr_newline: true)
7391 * io.puts "Hello, World!"
7392 *
7393 * fd = STDERR.fcntl(Fcntl::F_DUPFD)
7394 * io = IO.new(fd, mode: 'w', cr_newline: true,
7395 * external_encoding: Encoding::UTF_16LE)
7396 * io.puts "Hello, World!"
7397 *
7398 * Both of above print "Hello, World!" in UTF-16LE to standard error output
7399 * with converting EOL generated by <code>puts</code> to CR.
7400 */
7401
7402 static VALUE
7403 rb_io_initialize(int argc, VALUE *argv, VALUE io)
7404 {
7405 VALUE fnum, vmode;
7406 rb_io_t *fp;
7407 int fd, fmode, oflags = O_RDONLY;
7408 convconfig_t convconfig;
7409 VALUE opt;
7410 #if defined(HAVE_FCNTL) && defined(F_GETFL)
7411 int ofmode;
7412 #else
7413 struct stat st;
7414 #endif
7415
7416
7417 argc = rb_scan_args(argc, argv, "11:", &fnum, &vmode, &opt);
7418 rb_io_extract_modeenc(&vmode, 0, opt, &oflags, &fmode, &convconfig);
7419
7420 fd = NUM2INT(fnum);
7421 if (rb_reserved_fd_p(fd)) {
7422 rb_raise(rb_eArgError, "The given fd is not accessible because RubyVM reserves it");
7423 }
7424 #if defined(HAVE_FCNTL) && defined(F_GETFL)
7425 oflags = fcntl(fd, F_GETFL);
7426 if (oflags == -1) rb_sys_fail(0);
7427 #else
7428 if (fstat(fd, &st) == -1) rb_sys_fail(0);
7429 #endif
7430 rb_update_max_fd(fd);
7431 #if defined(HAVE_FCNTL) && defined(F_GETFL)
7432 ofmode = rb_io_oflags_fmode(oflags);
7433 if (NIL_P(vmode)) {
7434 fmode = ofmode;
7435 }
7436 else if ((~ofmode & fmode) & FMODE_READWRITE) {
7437 VALUE error = INT2FIX(EINVAL);
7438 rb_exc_raise(rb_class_new_instance(1, &error, rb_eSystemCallError));
7439 }
7440 #endif
7441 if (!NIL_P(opt) && rb_hash_aref(opt, sym_autoclose) == Qfalse) {
7442 fmode |= FMODE_PREP;
7443 }
7444 MakeOpenFile(io, fp);
7445 fp->fd = fd;
7446 fp->mode = fmode;
7447 fp->encs = convconfig;
7448 clear_codeconv(fp);
7449 io_check_tty(fp);
7450 if (fileno(stdin) == fd)
7451 fp->stdio_file = stdin;
7452 else if (fileno(stdout) == fd)
7453 fp->stdio_file = stdout;
7454 else if (fileno(stderr) == fd)
7455 fp->stdio_file = stderr;
7456
7457 if (fmode & FMODE_SETENC_BY_BOM) io_set_encoding_by_bom(io);
7458 return io;
7459 }
7460
7461 /*
7462 * call-seq:
7463 * File.new(filename, mode="r" [, opt]) -> file
7464 * File.new(filename [, mode [, perm]] [, opt]) -> file
7465 *
7466 * Opens the file named by +filename+ according to the given +mode+ and
7467 * returns a new File object.
7468 *
7469 * See IO.new for a description of +mode+ and +opt+.
7470 *
7471 * If a file is being created, permission bits may be given in +perm+. These
7472 * mode and permission bits are platform dependent; on Unix systems, see
7473 * open(2) and chmod(2) man pages for details.
7474 *
7475 * === Examples
7476 *
7477 * f = File.new("testfile", "r")
7478 * f = File.new("newfile", "w+")
7479 * f = File.new("newfile", File::CREAT|File::TRUNC|File::RDWR, 0644)
7480 */
7481
7482 static VALUE
7483 rb_file_initialize(int argc, VALUE *argv, VALUE io)
7484 {
7485 if (RFILE(io)->fptr) {
7486 rb_raise(rb_eRuntimeError, "reinitializing File");
7487 }
7488 if (0 < argc && argc < 3) {
7489 VALUE fd = rb_check_convert_type(argv[0], T_FIXNUM, "Fixnum", "to_int");
7490
7491 if (!NIL_P(fd)) {
7492 argv[0] = fd;
7493 return rb_io_initialize(argc, argv, io);
7494 }
7495 }
7496 rb_open_file(argc, argv, io);
7497
7498 return io;
7499 }
7500
7501 /* :nodoc: */
7502 static VALUE
7503 rb_io_s_new(int argc, VALUE *argv, VALUE klass)
7504 {
7505 if (rb_block_given_p()) {
7506 const char *cname = rb_class2name(klass);
7507
7508 rb_warn("%s::new() does not take block; use %s::open() instead",
7509 cname, cname);
7510 }
7511 return rb_class_new_instance(argc, argv, klass);
7512 }
7513
7514
7515 /*
7516 * call-seq:
7517 * IO.for_fd(fd, mode [, opt]) -> io
7518 *
7519 * Synonym for <code>IO.new</code>.
7520 *
7521 */
7522
7523 static VALUE
7524 rb_io_s_for_fd(int argc, VALUE *argv, VALUE klass)
7525 {
7526 VALUE io = rb_obj_alloc(klass);
7527 rb_io_initialize(argc, argv, io);
7528 return io;
7529 }
7530
7531 /*
7532 * call-seq:
7533 * ios.autoclose? -> true or false
7534 *
7535 * Returns +true+ if the underlying file descriptor of _ios_ will be
7536 * closed automatically at its finalization, otherwise +false+.
7537 */
7538
7539 static VALUE
7540 rb_io_autoclose_p(VALUE io)
7541 {
7542 rb_io_t *fptr = RFILE(io)->fptr;
7543 rb_io_check_closed(fptr);
7544 return (fptr->mode & FMODE_PREP) ? Qfalse : Qtrue;
7545 }
7546
7547 /*
7548 * call-seq:
7549 * io.autoclose = bool -> true or false
7550 *
7551 * Sets auto-close flag.
7552 *
7553 * f = open("/dev/null")
7554 * IO.for_fd(f.fileno)
7555 * # ...
7556 * f.gets # may cause IOError
7557 *
7558 * f = open("/dev/null")
7559 * IO.for_fd(f.fileno).autoclose = true
7560 * # ...
7561 * f.gets # won't cause IOError
7562 */
7563
7564 static VALUE
7565 rb_io_set_autoclose(VALUE io, VALUE autoclose)
7566 {
7567 rb_io_t *fptr;
7568 GetOpenFile(io, fptr);
7569 if (!RTEST(autoclose))
7570 fptr->mode |= FMODE_PREP;
7571 else
7572 fptr->mode &= ~FMODE_PREP;
7573 return io;
7574 }
7575
7576 static void
7577 argf_mark(void *ptr)
7578 {
7579 struct argf *p = ptr;
7580 rb_gc_mark(p->filename);
7581 rb_gc_mark(p->current_file);
7582 rb_gc_mark(p->argv);
7583 rb_gc_mark(p->encs.ecopts);
7584 }
7585
7586 static void
7587 argf_free(void *ptr)
7588 {
7589 struct argf *p = ptr;
7590 xfree(p->inplace);
7591 xfree(p);
7592 }
7593
7594 static size_t
7595 argf_memsize(const void *ptr)
7596 {
7597 const struct argf *p = ptr;
7598 size_t size = sizeof(*p);
7599 if (!ptr) return 0;
7600 if (p->inplace) size += strlen(p->inplace) + 1;
7601 return size;
7602 }
7603
7604 static const rb_data_type_t argf_type = {
7605 "ARGF",
7606 {argf_mark, argf_free, argf_memsize},
7607 NULL, NULL, RUBY_TYPED_FREE_IMMEDIATELY
7608 };
7609
7610 static inline void
7611 argf_init(struct argf *p, VALUE v)
7612 {
7613 p->filename = Qnil;
7614 p->current_file = Qnil;
7615 p->lineno = 0;
7616 p->argv = v;
7617 }
7618
7619 static VALUE
7620 argf_alloc(VALUE klass)
7621 {
7622 struct argf *p;
7623 VALUE argf = TypedData_Make_Struct(klass, struct argf, &argf_type, p);
7624
7625 argf_init(p, Qnil);
7626 return argf;
7627 }
7628
7629 #undef rb_argv
7630
7631 /* :nodoc: */
7632 static VALUE
7633 argf_initialize(VALUE argf, VALUE argv)
7634 {
7635 memset(&ARGF, 0, sizeof(ARGF));
7636 argf_init(&ARGF, argv);
7637
7638 return argf;
7639 }
7640
7641 /* :nodoc: */
7642 static VALUE
7643 argf_initialize_copy(VALUE argf, VALUE orig)
7644 {
7645 if (!OBJ_INIT_COPY(argf, orig)) return argf;
7646 ARGF = argf_of(orig);
7647 ARGF.argv = rb_obj_dup(ARGF.argv);
7648 if (ARGF.inplace) {
7649 const char *inplace = ARGF.inplace;
7650 ARGF.inplace = 0;
7651 ARGF.inplace = ruby_strdup(inplace);
7652 }
7653 return argf;
7654 }
7655
7656 /*
7657 * call-seq:
7658 * ARGF.lineno = integer -> integer
7659 *
7660 * Sets the line number of +ARGF+ as a whole to the given +Integer+.
7661 *
7662 * +ARGF+ sets the line number automatically as you read data, so normally
7663 * you will not need to set it explicitly. To access the current line number
7664 * use +ARGF.lineno+.
7665 *
7666 * For example:
7667 *
7668 * ARGF.lineno #=> 0
7669 * ARGF.readline #=> "This is line 1\n"
7670 * ARGF.lineno #=> 1
7671 * ARGF.lineno = 0 #=> 0
7672 * ARGF.lineno #=> 0
7673 */
7674 static VALUE
7675 argf_set_lineno(VALUE argf, VALUE val)
7676 {
7677 ARGF.lineno = NUM2INT(val);
7678 ARGF.last_lineno = ARGF.lineno;
7679 return Qnil;
7680 }
7681
7682 /*
7683 * call-seq:
7684 * ARGF.lineno -> integer
7685 *
7686 * Returns the current line number of ARGF as a whole. This value
7687 * can be set manually with +ARGF.lineno=+.
7688 *
7689 * For example:
7690 *
7691 * ARGF.lineno #=> 0
7692 * ARGF.readline #=> "This is line 1\n"
7693 * ARGF.lineno #=> 1
7694 */
7695 static VALUE
7696 argf_lineno(VALUE argf)
7697 {
7698 return INT2FIX(ARGF.lineno);
7699 }
7700
7701 static VALUE
7702 argf_forward(int argc, VALUE *argv, VALUE argf)
7703 {
7704 return rb_funcall3(ARGF.current_file, rb_frame_this_func(), argc, argv);
7705 }
7706
7707 #define next_argv() argf_next_argv(argf)
7708 #define ARGF_GENERIC_INPUT_P() \
7709 (ARGF.current_file == rb_stdin && !RB_TYPE_P(ARGF.current_file, T_FILE))
7710 #define ARGF_FORWARD(argc, argv) do {\
7711 if (ARGF_GENERIC_INPUT_P())\
7712 return argf_forward((argc), (argv), argf);\
7713 } while (0)
7714 #define NEXT_ARGF_FORWARD(argc, argv) do {\
7715 if (!next_argv()) return Qnil;\
7716 ARGF_FORWARD((argc), (argv));\
7717 } while (0)
7718
7719 static void
7720 argf_close(VALUE argf)
7721 {
7722 VALUE file = ARGF.current_file;
7723 if (file == rb_stdin) return;
7724 if (RB_TYPE_P(file, T_FILE)) {
7725 rb_io_set_write_io(file, Qnil);
7726 }
7727 rb_funcall3(file, rb_intern("close"), 0, 0);
7728 ARGF.init_p = -1;
7729 }
7730
7731 static int
7732 argf_next_argv(VALUE argf)
7733 {
7734 char *fn;
7735 rb_io_t *fptr;
7736 int stdout_binmode = 0;
7737 int fmode;
7738
7739 if (RB_TYPE_P(rb_stdout, T_FILE)) {
7740 GetOpenFile(rb_stdout, fptr);
7741 if (fptr->mode & FMODE_BINMODE)
7742 stdout_binmode = 1;
7743 }
7744
7745 if (ARGF.init_p == 0) {
7746 if (!NIL_P(ARGF.argv) && RARRAY_LEN(ARGF.argv) > 0) {
7747 ARGF.next_p = 1;
7748 }
7749 else {
7750 ARGF.next_p = -1;
7751 }
7752 ARGF.init_p = 1;
7753 }
7754 else {
7755 if (NIL_P(ARGF.argv)) {
7756 ARGF.next_p = -1;
7757 }
7758 else if (ARGF.next_p == -1 && RARRAY_LEN(ARGF.argv) > 0) {
7759 ARGF.next_p = 1;
7760 }
7761 }
7762
7763 if (ARGF.next_p == 1) {
7764 retry:
7765 if (RARRAY_LEN(ARGF.argv) > 0) {
7766 ARGF.filename = rb_ary_shift(ARGF.argv);
7767 fn = StringValueCStr(ARGF.filename);
7768 if (strlen(fn) == 1 && fn[0] == '-') {
7769 ARGF.current_file = rb_stdin;
7770 if (ARGF.inplace) {
7771 rb_warn("Can't do inplace edit for stdio; skipping");
7772 goto retry;
7773 }
7774 }
7775 else {
7776 VALUE write_io = Qnil;
7777 int fr = rb_sysopen(ARGF.filename, O_RDONLY, 0);
7778
7779 if (ARGF.inplace) {
7780 struct stat st;
7781 #ifndef NO_SAFE_RENAME
7782 struct stat st2;
7783 #endif
7784 VALUE str;
7785 int fw;
7786
7787 if (RB_TYPE_P(rb_stdout, T_FILE) && rb_stdout != orig_stdout) {
7788 rb_io_close(rb_stdout);
7789 }
7790 fstat(fr, &st);
7791 if (*ARGF.inplace) {
7792 str = rb_str_new2(fn);
7793 rb_str_cat2(str, ARGF.inplace);
7794 #ifdef NO_SAFE_RENAME
7795 (void)close(fr);
7796 (void)unlink(RSTRING_PTR(str));
7797 if (rename(fn, RSTRING_PTR(str)) < 0) {
7798 rb_warn("Can't rename %s to %s: %s, skipping file",
7799 fn, RSTRING_PTR(str), strerror(errno));
7800 goto retry;
7801 }
7802 fr = rb_sysopen(str, O_RDONLY, 0);
7803 #else
7804 if (rename(fn, RSTRING_PTR(str)) < 0) {
7805 rb_warn("Can't rename %s to %s: %s, skipping file",
7806 fn, RSTRING_PTR(str), strerror(errno));
7807 close(fr);
7808 goto retry;
7809 }
7810 #endif
7811 }
7812 else {
7813 #ifdef NO_SAFE_RENAME
7814 rb_fatal("Can't do inplace edit without backup");
7815 #else
7816 if (unlink(fn) < 0) {
7817 rb_warn("Can't remove %s: %s, skipping file",
7818 fn, strerror(errno));
7819 close(fr);
7820 goto retry;
7821 }
7822 #endif
7823 }
7824 fw = rb_sysopen(ARGF.filename, O_WRONLY|O_CREAT|O_TRUNC, 0666);
7825 #ifndef NO_SAFE_RENAME
7826 fstat(fw, &st2);
7827 #ifdef HAVE_FCHMOD
7828 fchmod(fw, st.st_mode);
7829 #else
7830 chmod(fn, st.st_mode);
7831 #endif
7832 if (st.st_uid!=st2.st_uid || st.st_gid!=st2.st_gid) {
7833 int err;
7834 #ifdef HAVE_FCHOWN
7835 err = fchown(fw, st.st_uid, st.st_gid);
7836 #else
7837 err = chown(fn, st.st_uid, st.st_gid);
7838 #endif
7839 if (err && getuid() == 0 && st2.st_uid == 0) {
7840 const char *wkfn = RSTRING_PTR(ARGF.filename);
7841 rb_warn("Can't set owner/group of %s to same as %s: %s, skipping file",
7842 wkfn, fn, strerror(errno));
7843 (void)close(fr);
7844 (void)close(fw);
7845 (void)unlink(wkfn);
7846 goto retry;
7847 }
7848 }
7849 #endif
7850 write_io = prep_io(fw, FMODE_WRITABLE, rb_cFile, fn);
7851 rb_stdout = write_io;
7852 if (stdout_binmode) rb_io_binmode(rb_stdout);
7853 }
7854 fmode = FMODE_READABLE;
7855 if (!ARGF.binmode) {
7856 fmode |= DEFAULT_TEXTMODE;
7857 }
7858 ARGF.current_file = prep_io(fr, fmode, rb_cFile, fn);
7859 if (!NIL_P(write_io)) {
7860 rb_io_set_write_io(ARGF.current_file, write_io);
7861 }
7862 }
7863 if (ARGF.binmode) rb_io_ascii8bit_binmode(ARGF.current_file);
7864 GetOpenFile(ARGF.current_file, fptr);
7865 if (ARGF.encs.enc) {
7866 fptr->encs = ARGF.encs;
7867 clear_codeconv(fptr);
7868 }
7869 else {
7870 fptr->encs.ecflags &= ~ECONV_NEWLINE_DECORATOR_MASK;
7871 if (!ARGF.binmode) {
7872 fptr->encs.ecflags |= ECONV_DEFAULT_NEWLINE_DECORATOR;
7873 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
7874 fptr->encs.ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
7875 #endif
7876 }
7877 }
7878 ARGF.next_p = 0;
7879 }
7880 else {
7881 ARGF.next_p = 1;
7882 return FALSE;
7883 }
7884 }
7885 else if (ARGF.next_p == -1) {
7886 ARGF.current_file = rb_stdin;
7887 ARGF.filename = rb_str_new2("-");
7888 if (ARGF.inplace) {
7889 rb_warn("Can't do inplace edit for stdio");
7890 rb_stdout = orig_stdout;
7891 }
7892 }
7893 if (ARGF.init_p == -1) ARGF.init_p = 1;
7894 return TRUE;
7895 }
7896
7897 static VALUE
7898 argf_getline(int argc, VALUE *argv, VALUE argf)
7899 {
7900 VALUE line;
7901 long lineno = ARGF.lineno;
7902
7903 retry:
7904 if (!next_argv()) return Qnil;
7905 if (ARGF_GENERIC_INPUT_P()) {
7906 line = rb_funcall3(ARGF.current_file, idGets, argc, argv);
7907 }
7908 else {
7909 if (argc == 0 && rb_rs == rb_default_rs) {
7910 line = rb_io_gets(ARGF.current_file);
7911 }
7912 else {
7913 line = rb_io_getline(argc, argv, ARGF.current_file);
7914 }
7915 if (NIL_P(line) && ARGF.next_p != -1) {
7916 argf_close(argf);
7917 ARGF.next_p = 1;
7918 goto retry;
7919 }
7920 }
7921 if (!NIL_P(line)) {
7922 ARGF.lineno = ++lineno;
7923 ARGF.last_lineno = ARGF.lineno;
7924 }
7925 return line;
7926 }
7927
7928 static VALUE
7929 argf_lineno_getter(ID id, VALUE *var)
7930 {
7931 VALUE argf = *var;
7932 return INT2FIX(ARGF.last_lineno);
7933 }
7934
7935 static void
7936 argf_lineno_setter(VALUE val, ID id, VALUE *var)
7937 {
7938 VALUE argf = *var;
7939 int n = NUM2INT(val);
7940 ARGF.last_lineno = ARGF.lineno = n;
7941 }
7942
7943 static VALUE argf_gets(int, VALUE *, VALUE);
7944
7945 /*
7946 * call-seq:
7947 * gets(sep=$/) -> string or nil
7948 * gets(limit) -> string or nil
7949 * gets(sep,limit) -> string or nil
7950 *
7951 * Returns (and assigns to <code>$_</code>) the next line from the list
7952 * of files in +ARGV+ (or <code>$*</code>), or from standard input if
7953 * no files are present on the command line. Returns +nil+ at end of
7954 * file. The optional argument specifies the record separator. The
7955 * separator is included with the contents of each record. A separator
7956 * of +nil+ reads the entire contents, and a zero-length separator
7957 * reads the input one paragraph at a time, where paragraphs are
7958 * divided by two consecutive newlines. If the first argument is an
7959 * integer, or optional second argument is given, the returning string
7960 * would not be longer than the given value in bytes. If multiple
7961 * filenames are present in +ARGV+, +gets(nil)+ will read the contents
7962 * one file at a time.
7963 *
7964 * ARGV << "testfile"
7965 * print while gets
7966 *
7967 * <em>produces:</em>
7968 *
7969 * This is line one
7970 * This is line two
7971 * This is line three
7972 * And so on...
7973 *
7974 * The style of programming using <code>$_</code> as an implicit
7975 * parameter is gradually losing favor in the Ruby community.
7976 */
7977
7978 static VALUE
7979 rb_f_gets(int argc, VALUE *argv, VALUE recv)
7980 {
7981 if (recv == argf) {
7982 return argf_gets(argc, argv, argf);
7983 }
7984 return rb_funcall2(argf, idGets, argc, argv);
7985 }
7986
7987 /*
7988 * call-seq:
7989 * ARGF.gets(sep=$/) -> string or nil
7990 * ARGF.gets(limit) -> string or nil
7991 * ARGF.gets(sep, limit) -> string or nil
7992 *
7993 * Returns the next line from the current file in +ARGF+.
7994 *
7995 * By default lines are assumed to be separated by +$/+; to use a different
7996 * character as a separator, supply it as a +String+ for the _sep_ argument.
7997 *
7998 * The optional _limit_ argument specifies how many characters of each line
7999 * to return. By default all characters are returned.
8000 *
8001 */
8002 static VALUE
8003 argf_gets(int argc, VALUE *argv, VALUE argf)
8004 {
8005 VALUE line;
8006
8007 line = argf_getline(argc, argv, argf);
8008 rb_lastline_set(line);
8009
8010 return line;
8011 }
8012
8013 VALUE
8014 rb_gets(void)
8015 {
8016 VALUE line;
8017
8018 if (rb_rs != rb_default_rs) {
8019 return rb_f_gets(0, 0, argf);
8020 }
8021
8022 retry:
8023 if (!next_argv()) return Qnil;
8024 line = rb_io_gets(ARGF.current_file);
8025 if (NIL_P(line) && ARGF.next_p != -1) {
8026 rb_io_close(ARGF.current_file);
8027 ARGF.next_p = 1;
8028 goto retry;
8029 }
8030 rb_lastline_set(line);
8031 if (!NIL_P(line)) {
8032 ARGF.lineno++;
8033 ARGF.last_lineno = ARGF.lineno;
8034 }
8035
8036 return line;
8037 }
8038
8039 static VALUE argf_readline(int, VALUE *, VALUE);
8040
8041 /*
8042 * call-seq:
8043 * readline(sep=$/) -> string
8044 * readline(limit) -> string
8045 * readline(sep, limit) -> string
8046 *
8047 * Equivalent to <code>Kernel::gets</code>, except
8048 * +readline+ raises +EOFError+ at end of file.
8049 */
8050
8051 static VALUE
8052 rb_f_readline(int argc, VALUE *argv, VALUE recv)
8053 {
8054 if (recv == argf) {
8055 return argf_readline(argc, argv, argf);
8056 }
8057 return rb_funcall2(argf, rb_intern("readline"), argc, argv);
8058 }
8059
8060
8061 /*
8062 * call-seq:
8063 * ARGF.readline(sep=$/) -> string
8064 * ARGF.readline(limit) -> string
8065 * ARGF.readline(sep, limit) -> string
8066 *
8067 * Returns the next line from the current file in +ARGF+.
8068 *
8069 * By default lines are assumed to be separated by +$/+; to use a different
8070 * character as a separator, supply it as a +String+ for the _sep_ argument.
8071 *
8072 * The optional _limit_ argument specifies how many characters of each line
8073 * to return. By default all characters are returned.
8074 *
8075 * An +EOFError+ is raised at the end of the file.
8076 */
8077 static VALUE
8078 argf_readline(int argc, VALUE *argv, VALUE argf)
8079 {
8080 VALUE line;
8081
8082 if (!next_argv()) rb_eof_error();
8083 ARGF_FORWARD(argc, argv);
8084 line = argf_gets(argc, argv, argf);
8085 if (NIL_P(line)) {
8086 rb_eof_error();
8087 }
8088
8089 return line;
8090 }
8091
8092 static VALUE argf_readlines(int, VALUE *, VALUE);
8093
8094 /*
8095 * call-seq:
8096 * readlines(sep=$/) -> array
8097 * readlines(limit) -> array
8098 * readlines(sep,limit) -> array
8099 *
8100 * Returns an array containing the lines returned by calling
8101 * <code>Kernel.gets(<i>sep</i>)</code> until the end of file.
8102 */
8103
8104 static VALUE
8105 rb_f_readlines(int argc, VALUE *argv, VALUE recv)
8106 {
8107 if (recv == argf) {
8108 return argf_readlines(argc, argv, argf);
8109 }
8110 return rb_funcall2(argf, rb_intern("readlines"), argc, argv);
8111 }
8112
8113 /*
8114 * call-seq:
8115 * ARGF.readlines(sep=$/) -> array
8116 * ARGF.readlines(limit) -> array
8117 * ARGF.readlines(sep, limit) -> array
8118 *
8119 * ARGF.to_a(sep=$/) -> array
8120 * ARGF.to_a(limit) -> array
8121 * ARGF.to_a(sep, limit) -> array
8122 *
8123 * Reads +ARGF+'s current file in its entirety, returning an +Array+ of its
8124 * lines, one line per element. Lines are assumed to be separated by _sep_.
8125 *
8126 * lines = ARGF.readlines
8127 * lines[0] #=> "This is line one\n"
8128 */
8129 static VALUE
8130 argf_readlines(int argc, VALUE *argv, VALUE argf)
8131 {
8132 long lineno = ARGF.lineno;
8133 VALUE lines, ary;
8134
8135 ary = rb_ary_new();
8136 while (next_argv()) {
8137 if (ARGF_GENERIC_INPUT_P()) {
8138 lines = rb_funcall3(ARGF.current_file, rb_intern("readlines"), argc, argv);
8139 }
8140 else {
8141 lines = rb_io_readlines(argc, argv, ARGF.current_file);
8142 argf_close(argf);
8143 }
8144 ARGF.next_p = 1;
8145 rb_ary_concat(ary, lines);
8146 ARGF.lineno = lineno + RARRAY_LEN(ary);
8147 ARGF.last_lineno = ARGF.lineno;
8148 }
8149 ARGF.init_p = 0;
8150 return ary;
8151 }
8152
8153 /*
8154 * call-seq:
8155 * `cmd` -> string
8156 *
8157 * Returns the standard output of running _cmd_ in a subshell.
8158 * The built-in syntax <code>%x{...}</code> uses
8159 * this method. Sets <code>$?</code> to the process status.
8160 *
8161 * `date` #=> "Wed Apr 9 08:56:30 CDT 2003\n"
8162 * `ls testdir`.split[1] #=> "main.rb"
8163 * `echo oops && exit 99` #=> "oops\n"
8164 * $?.exitstatus #=> 99
8165 */
8166
8167 static VALUE
8168 rb_f_backquote(VALUE obj, VALUE str)
8169 {
8170 volatile VALUE port;
8171 VALUE result;
8172 rb_io_t *fptr;
8173
8174 SafeStringValue(str);
8175 rb_last_status_clear();
8176 port = pipe_open_s(str, "r", FMODE_READABLE|DEFAULT_TEXTMODE, NULL);
8177 if (NIL_P(port)) return rb_str_new(0,0);
8178
8179 GetOpenFile(port, fptr);
8180 result = read_all(fptr, remain_size(fptr), Qnil);
8181 rb_io_close(port);
8182
8183 return result;
8184 }
8185
8186 #ifdef HAVE_SYS_SELECT_H
8187 #include <sys/select.h>
8188 #endif
8189
8190 static VALUE
8191 select_internal(VALUE read, VALUE write, VALUE except, struct timeval *tp, rb_fdset_t *fds)
8192 {
8193 VALUE res, list;
8194 rb_fdset_t *rp, *wp, *ep;
8195 rb_io_t *fptr;
8196 long i;
8197 int max = 0, n;
8198 int pending = 0;
8199 struct timeval timerec;
8200
8201 if (!NIL_P(read)) {
8202 Check_Type(read, T_ARRAY);
8203 for (i=0; i<RARRAY_LEN(read); i++) {
8204 GetOpenFile(rb_io_get_io(RARRAY_AREF(read, i)), fptr);
8205 rb_fd_set(fptr->fd, &fds[0]);
8206 if (READ_DATA_PENDING(fptr) || READ_CHAR_PENDING(fptr)) { /* check for buffered data */
8207 pending++;
8208 rb_fd_set(fptr->fd, &fds[3]);
8209 }
8210 if (max < fptr->fd) max = fptr->fd;
8211 }
8212 if (pending) { /* no blocking if there's buffered data */
8213 timerec.tv_sec = timerec.tv_usec = 0;
8214 tp = &timerec;
8215 }
8216 rp = &fds[0];
8217 }
8218 else
8219 rp = 0;
8220
8221 if (!NIL_P(write)) {
8222 Check_Type(write, T_ARRAY);
8223 for (i=0; i<RARRAY_LEN(write); i++) {
8224 VALUE write_io = GetWriteIO(rb_io_get_io(RARRAY_AREF(write, i)));
8225 GetOpenFile(write_io, fptr);
8226 rb_fd_set(fptr->fd, &fds[1]);
8227 if (max < fptr->fd) max = fptr->fd;
8228 }
8229 wp = &fds[1];
8230 }
8231 else
8232 wp = 0;
8233
8234 if (!NIL_P(except)) {
8235 Check_Type(except, T_ARRAY);
8236 for (i=0; i<RARRAY_LEN(except); i++) {
8237 VALUE io = rb_io_get_io(RARRAY_AREF(except, i));
8238 VALUE write_io = GetWriteIO(io);
8239 GetOpenFile(io, fptr);
8240 rb_fd_set(fptr->fd, &fds[2]);
8241 if (max < fptr->fd) max = fptr->fd;
8242 if (io != write_io) {
8243 GetOpenFile(write_io, fptr);
8244 rb_fd_set(fptr->fd, &fds[2]);
8245 if (max < fptr->fd) max = fptr->fd;
8246 }
8247 }
8248 ep = &fds[2];
8249 }
8250 else {
8251 ep = 0;
8252 }
8253
8254 max++;
8255
8256 n = rb_thread_fd_select(max, rp, wp, ep, tp);
8257 if (n < 0) {
8258 rb_sys_fail(0);
8259 }
8260 if (!pending && n == 0) return Qnil; /* returns nil on timeout */
8261
8262 res = rb_ary_new2(3);
8263 rb_ary_push(res, rp?rb_ary_new():rb_ary_new2(0));
8264 rb_ary_push(res, wp?rb_ary_new():rb_ary_new2(0));
8265 rb_ary_push(res, ep?rb_ary_new():rb_ary_new2(0));
8266
8267 if (rp) {
8268 list = RARRAY_AREF(res, 0);
8269 for (i=0; i< RARRAY_LEN(read); i++) {
8270 VALUE obj = rb_ary_entry(read, i);
8271 VALUE io = rb_io_get_io(obj);
8272 GetOpenFile(io, fptr);
8273 if (rb_fd_isset(fptr->fd, &fds[0]) ||
8274 rb_fd_isset(fptr->fd, &fds[3])) {
8275 rb_ary_push(list, obj);
8276 }
8277 }
8278 }
8279
8280 if (wp) {
8281 list = RARRAY_AREF(res, 1);
8282 for (i=0; i< RARRAY_LEN(write); i++) {
8283 VALUE obj = rb_ary_entry(write, i);
8284 VALUE io = rb_io_get_io(obj);
8285 VALUE write_io = GetWriteIO(io);
8286 GetOpenFile(write_io, fptr);
8287 if (rb_fd_isset(fptr->fd, &fds[1])) {
8288 rb_ary_push(list, obj);
8289 }
8290 }
8291 }
8292
8293 if (ep) {
8294 list = RARRAY_AREF(res, 2);
8295 for (i=0; i< RARRAY_LEN(except); i++) {
8296 VALUE obj = rb_ary_entry(except, i);
8297 VALUE io = rb_io_get_io(obj);
8298 VALUE write_io = GetWriteIO(io);
8299 GetOpenFile(io, fptr);
8300 if (rb_fd_isset(fptr->fd, &fds[2])) {
8301 rb_ary_push(list, obj);
8302 }
8303 else if (io != write_io) {
8304 GetOpenFile(write_io, fptr);
8305 if (rb_fd_isset(fptr->fd, &fds[2])) {
8306 rb_ary_push(list, obj);
8307 }
8308 }
8309 }
8310 }
8311
8312 return res; /* returns an empty array on interrupt */
8313 }
8314
8315 struct select_args {
8316 VALUE read, write, except;
8317 struct timeval *timeout;
8318 rb_fdset_t fdsets[4];
8319 };
8320
8321 static VALUE
8322 select_call(VALUE arg)
8323 {
8324 struct select_args *p = (struct select_args *)arg;
8325
8326 return select_internal(p->read, p->write, p->except, p->timeout, p->fdsets);
8327 }
8328
8329 static VALUE
8330 select_end(VALUE arg)
8331 {
8332 struct select_args *p = (struct select_args *)arg;
8333 int i;
8334
8335 for (i = 0; i < numberof(p->fdsets); ++i)
8336 rb_fd_term(&p->fdsets[i]);
8337 return Qnil;
8338 }
8339
8340 static VALUE sym_normal, sym_sequential, sym_random,
8341 sym_willneed, sym_dontneed, sym_noreuse;
8342
8343 #ifdef HAVE_POSIX_FADVISE
8344 struct io_advise_struct {
8345 int fd;
8346 off_t offset;
8347 off_t len;
8348 int advice;
8349 };
8350
8351 static VALUE
8352 io_advise_internal(void *arg)
8353 {
8354 struct io_advise_struct *ptr = arg;
8355 return posix_fadvise(ptr->fd, ptr->offset, ptr->len, ptr->advice);
8356 }
8357
8358 static VALUE
8359 io_advise_sym_to_const(VALUE sym)
8360 {
8361 #ifdef POSIX_FADV_NORMAL
8362 if (sym == sym_normal)
8363 return INT2NUM(POSIX_FADV_NORMAL);
8364 #endif
8365
8366 #ifdef POSIX_FADV_RANDOM
8367 if (sym == sym_random)
8368 return INT2NUM(POSIX_FADV_RANDOM);
8369 #endif
8370
8371 #ifdef POSIX_FADV_SEQUENTIAL
8372 if (sym == sym_sequential)
8373 return INT2NUM(POSIX_FADV_SEQUENTIAL);
8374 #endif
8375
8376 #ifdef POSIX_FADV_WILLNEED
8377 if (sym == sym_willneed)
8378 return INT2NUM(POSIX_FADV_WILLNEED);
8379 #endif
8380
8381 #ifdef POSIX_FADV_DONTNEED
8382 if (sym == sym_dontneed)
8383 return INT2NUM(POSIX_FADV_DONTNEED);
8384 #endif
8385
8386 #ifdef POSIX_FADV_NOREUSE
8387 if (sym == sym_noreuse)
8388 return INT2NUM(POSIX_FADV_NOREUSE);
8389 #endif
8390
8391 return Qnil;
8392 }
8393
8394 static VALUE
8395 do_io_advise(rb_io_t *fptr, VALUE advice, off_t offset, off_t len)
8396 {
8397 int rv;
8398 struct io_advise_struct ias;
8399 VALUE num_adv;
8400
8401 num_adv = io_advise_sym_to_const(advice);
8402
8403 /*
8404 * The platform doesn't support this hint. We don't raise exception, instead
8405 * silently ignore it. Because IO::advise is only hint.
8406 */
8407 if (NIL_P(num_adv))
8408 return Qnil;
8409
8410 ias.fd = fptr->fd;
8411 ias.advice = NUM2INT(num_adv);
8412 ias.offset = offset;
8413 ias.len = len;
8414
8415 rv = (int)rb_thread_io_blocking_region(io_advise_internal, &ias, fptr->fd);
8416 if (rv) {
8417 /* posix_fadvise(2) doesn't set errno. On success it returns 0; otherwise
8418 it returns the error code. */
8419 rb_syserr_fail_str(rv, fptr->pathv);
8420 }
8421
8422 return Qnil;
8423 }
8424
8425 #endif /* HAVE_POSIX_FADVISE */
8426
8427 static void
8428 advice_arg_check(VALUE advice)
8429 {
8430 if (!SYMBOL_P(advice))
8431 rb_raise(rb_eTypeError, "advice must be a Symbol");
8432
8433 if (advice != sym_normal &&
8434 advice != sym_sequential &&
8435 advice != sym_random &&
8436 advice != sym_willneed &&
8437 advice != sym_dontneed &&
8438 advice != sym_noreuse) {
8439 VALUE symname = rb_inspect(advice);
8440 rb_raise(rb_eNotImpError, "Unsupported advice: %s",
8441 StringValuePtr(symname));
8442 }
8443 }
8444
8445 /*
8446 * call-seq:
8447 * ios.advise(advice, offset=0, len=0) -> nil
8448 *
8449 * Announce an intention to access data from the current file in a
8450 * specific pattern. On platforms that do not support the
8451 * <em>posix_fadvise(2)</em> system call, this method is a no-op.
8452 *
8453 * _advice_ is one of the following symbols:
8454 *
8455 * :normal:: No advice to give; the default assumption for an open file.
8456 * :sequential:: The data will be accessed sequentially
8457 * with lower offsets read before higher ones.
8458 * :random:: The data will be accessed in random order.
8459 * :willneed:: The data will be accessed in the near future.
8460 * :dontneed:: The data will not be accessed in the near future.
8461 * :noreuse:: The data will only be accessed once.
8462 *
8463 * The semantics of a piece of advice are platform-dependent. See
8464 * <em>man 2 posix_fadvise</em> for details.
8465 *
8466 * "data" means the region of the current file that begins at
8467 * _offset_ and extends for _len_ bytes. If _len_ is 0, the region
8468 * ends at the last byte of the file. By default, both _offset_ and
8469 * _len_ are 0, meaning that the advice applies to the entire file.
8470 *
8471 * If an error occurs, one of the following exceptions will be raised:
8472 *
8473 * <code>IOError</code>:: The <code>IO</code> stream is closed.
8474 * <code>Errno::EBADF</code>::
8475 * The file descriptor of the current file is invalid.
8476 * <code>Errno::EINVAL</code>:: An invalid value for _advice_ was given.
8477 * <code>Errno::ESPIPE</code>::
8478 * The file descriptor of the current file refers to a FIFO or
8479 * pipe. (Linux raises <code>Errno::EINVAL</code> in this case).
8480 * <code>TypeError</code>::
8481 * Either _advice_ was not a Symbol, or one of the
8482 * other arguments was not an <code>Integer</code>.
8483 * <code>RangeError</code>:: One of the arguments given was too big/small.
8484 *
8485 * This list is not exhaustive; other Errno:: exceptions are also possible.
8486 */
8487 static VALUE
8488 rb_io_advise(int argc, VALUE *argv, VALUE io)
8489 {
8490 VALUE advice, offset, len;
8491 off_t off, l;
8492 rb_io_t *fptr;
8493
8494 rb_scan_args(argc, argv, "12", &advice, &offset, &len);
8495 advice_arg_check(advice);
8496
8497 io = GetWriteIO(io);
8498 GetOpenFile(io, fptr);
8499
8500 off = NIL_P(offset) ? 0 : NUM2OFFT(offset);
8501 l = NIL_P(len) ? 0 : NUM2OFFT(len);
8502
8503 #ifdef HAVE_POSIX_FADVISE
8504 return do_io_advise(fptr, advice, off, l);
8505 #else
8506 ((void)off, (void)l); /* Ignore all hint */
8507 return Qnil;
8508 #endif
8509 }
8510
8511 /*
8512 * call-seq:
8513 * IO.select(read_array
8514 * [, write_array
8515 * [, error_array
8516 * [, timeout]]]) -> array or nil
8517 *
8518 * Calls select(2) system call.
8519 * It monitors given arrays of <code>IO</code> objects, waits one or more
8520 * of <code>IO</code> objects ready for reading, are ready for writing,
8521 * and have pending exceptions respectively, and returns an array that
8522 * contains arrays of those IO objects. It will return <code>nil</code>
8523 * if optional <i>timeout</i> value is given and no <code>IO</code> object
8524 * is ready in <i>timeout</i> seconds.
8525 *
8526 * <code>IO.select</code> peeks the buffer of <code>IO</code> objects for testing readability.
8527 * If the <code>IO</code> buffer is not empty,
8528 * <code>IO.select</code> immediately notify readability.
8529 * This "peek" is only happen for <code>IO</code> objects.
8530 * It is not happen for IO-like objects such as OpenSSL::SSL::SSLSocket.
8531 *
8532 * The best way to use <code>IO.select</code> is invoking it
8533 * after nonblocking methods such as <code>read_nonblock</code>, <code>write_nonblock</code>, etc.
8534 * The methods raises an exception which is extended by
8535 * <code>IO::WaitReadable</code> or <code>IO::WaitWritable</code>.
8536 * The modules notify how the caller should wait with <code>IO.select</code>.
8537 * If <code>IO::WaitReadable</code> is raised, the caller should wait for reading.
8538 * If <code>IO::WaitWritable</code> is raised, the caller should wait for writing.
8539 *
8540 * So, blocking read (<code>readpartial</code>) can be emulated using
8541 * <code>read_nonblock</code> and <code>IO.select</code> as follows:
8542 *
8543 * begin
8544 * result = io_like.read_nonblock(maxlen)
8545 * rescue IO::WaitReadable
8546 * IO.select([io_like])
8547 * retry
8548 * rescue IO::WaitWritable
8549 * IO.select(nil, [io_like])
8550 * retry
8551 * end
8552 *
8553 * Especially, the combination of nonblocking methods and
8554 * <code>IO.select</code> is preferred for <code>IO</code> like
8555 * objects such as <code>OpenSSL::SSL::SSLSocket</code>.
8556 * It has <code>to_io</code> method to return underlying <code>IO</code> object.
8557 * <code>IO.select</code> calls <code>to_io</code> to obtain the file descriptor to wait.
8558 *
8559 * This means that readability notified by <code>IO.select</code> doesn't mean
8560 * readability from <code>OpenSSL::SSL::SSLSocket</code> object.
8561 *
8562 * Most possible situation is <code>OpenSSL::SSL::SSLSocket</code> buffers some data.
8563 * <code>IO.select</code> doesn't see the buffer.
8564 * So <code>IO.select</code> can block when <code>OpenSSL::SSL::SSLSocket#readpartial</code> doesn't block.
8565 *
8566 * However several more complicated situation exists.
8567 *
8568 * SSL is a protocol which is sequence of records.
8569 * The record consists multiple bytes.
8570 * So, the remote side of SSL sends a partial record,
8571 * <code>IO.select</code> notifies readability but
8572 * <code>OpenSSL::SSL::SSLSocket</code> cannot decrypt a byte and
8573 * <code>OpenSSL::SSL::SSLSocket#readpartial</code> will blocks.
8574 *
8575 * Also, the remote side can request SSL renegotiation which forces
8576 * the local SSL engine writes some data.
8577 * This means <code>OpenSSL::SSL::SSLSocket#readpartial</code> may
8578 * invoke <code>write</code> system call and it can block.
8579 * In such situation, <code>OpenSSL::SSL::SSLSocket#read_nonblock</code>
8580 * raises IO::WaitWritable instead of blocking.
8581 * So, the caller should wait for ready for writability as above example.
8582 *
8583 * The combination of nonblocking methods and <code>IO.select</code> is
8584 * also useful for streams such as tty, pipe socket socket when
8585 * multiple process read form a stream.
8586 *
8587 * Finally, Linux kernel developers doesn't guarantee that
8588 * readability of select(2) means readability of following read(2) even
8589 * for single process.
8590 * See select(2) manual on GNU/Linux system.
8591 *
8592 * Invoking <code>IO.select</code> before <code>IO#readpartial</code> works well in usual.
8593 * However it is not the best way to use <code>IO.select</code>.
8594 *
8595 * The writability notified by select(2) doesn't show
8596 * how many bytes writable.
8597 * <code>IO#write</code> method blocks until given whole string is written.
8598 * So, <code>IO#write(two or more bytes)</code> can block after writability is notified by <code>IO.select</code>.
8599 * <code>IO#write_nonblock</code> is required to avoid the blocking.
8600 *
8601 * Blocking write (<code>write</code>) can be emulated using
8602 * <code>write_nonblock</code> and <code>IO.select</code> as follows:
8603 * IO::WaitReadable should also be rescued for SSL renegotiation in <code>OpenSSL::SSL::SSLSocket</code>.
8604 *
8605 * while 0 < string.bytesize
8606 * begin
8607 * written = io_like.write_nonblock(string)
8608 * rescue IO::WaitReadable
8609 * IO.select([io_like])
8610 * retry
8611 * rescue IO::WaitWritable
8612 * IO.select(nil, [io_like])
8613 * retry
8614 * end
8615 * string = string.byteslice(written..-1)
8616 * end
8617 *
8618 * === Parameters
8619 * read_array:: an array of <code>IO</code> objects that wait until ready for read
8620 * write_array:: an array of <code>IO</code> objects that wait until ready for write
8621 * error_array:: an array of <code>IO</code> objects that wait for exceptions
8622 * timeout:: a numeric value in second
8623 *
8624 * === Example
8625 *
8626 * rp, wp = IO.pipe
8627 * mesg = "ping "
8628 * 100.times {
8629 * # IO.select follows IO#read. Not the best way to use IO.select.
8630 * rs, ws, = IO.select([rp], [wp])
8631 * if r = rs[0]
8632 * ret = r.read(5)
8633 * print ret
8634 * case ret
8635 * when /ping/
8636 * mesg = "pong\n"
8637 * when /pong/
8638 * mesg = "ping "
8639 * end
8640 * end
8641 * if w = ws[0]
8642 * w.write(mesg)
8643 * end
8644 * }
8645 *
8646 * <em>produces:</em>
8647 *
8648 * ping pong
8649 * ping pong
8650 * ping pong
8651 * (snipped)
8652 * ping
8653 */
8654
8655 static VALUE
8656 rb_f_select(int argc, VALUE *argv, VALUE obj)
8657 {
8658 VALUE timeout;
8659 struct select_args args;
8660 struct timeval timerec;
8661 int i;
8662
8663 rb_scan_args(argc, argv, "13", &args.read, &args.write, &args.except, &timeout);
8664 if (NIL_P(timeout)) {
8665 args.timeout = 0;
8666 }
8667 else {
8668 timerec = rb_time_interval(timeout);
8669 args.timeout = &timerec;
8670 }
8671
8672 for (i = 0; i < numberof(args.fdsets); ++i)
8673 rb_fd_init(&args.fdsets[i]);
8674
8675 return rb_ensure(select_call, (VALUE)&args, select_end, (VALUE)&args);
8676 }
8677
8678 #if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
8679 typedef unsigned long ioctl_req_t;
8680 # define NUM2IOCTLREQ(num) NUM2ULONG(num)
8681 #else
8682 typedef int ioctl_req_t;
8683 # define NUM2IOCTLREQ(num) NUM2INT(num)
8684 #endif
8685
8686 struct ioctl_arg {
8687 int fd;
8688 ioctl_req_t cmd;
8689 long narg;
8690 };
8691
8692 static VALUE
8693 nogvl_ioctl(void *ptr)
8694 {
8695 struct ioctl_arg *arg = ptr;
8696
8697 return (VALUE)ioctl(arg->fd, arg->cmd, arg->narg);
8698 }
8699
8700 static int
8701 do_ioctl(int fd, ioctl_req_t cmd, long narg)
8702 {
8703 int retval;
8704 struct ioctl_arg arg;
8705
8706 arg.fd = fd;
8707 arg.cmd = cmd;
8708 arg.narg = narg;
8709
8710 retval = (int)rb_thread_io_blocking_region(nogvl_ioctl, &arg, fd);
8711
8712 return retval;
8713 }
8714
8715 #define DEFULT_IOCTL_NARG_LEN (256)
8716
8717 #if defined(__linux__) && defined(_IOC_SIZE)
8718 static long
8719 linux_iocparm_len(ioctl_req_t cmd)
8720 {
8721 long len;
8722
8723 if ((cmd & 0xFFFF0000) == 0) {
8724 /* legacy and unstructured ioctl number. */
8725 return DEFULT_IOCTL_NARG_LEN;
8726 }
8727
8728 len = _IOC_SIZE(cmd);
8729
8730 /* paranoia check for silly drivers which don't keep ioctl convention */
8731 if (len < DEFULT_IOCTL_NARG_LEN)
8732 len = DEFULT_IOCTL_NARG_LEN;
8733
8734 return len;
8735 }
8736 #endif
8737
8738 static long
8739 ioctl_narg_len(ioctl_req_t cmd)
8740 {
8741 long len;
8742
8743 #ifdef IOCPARM_MASK
8744 #ifndef IOCPARM_LEN
8745 #define IOCPARM_LEN(x) (((x) >> 16) & IOCPARM_MASK)
8746 #endif
8747 #endif
8748 #ifdef IOCPARM_LEN
8749 len = IOCPARM_LEN(cmd); /* on BSDish systems we're safe */
8750 #elif defined(__linux__) && defined(_IOC_SIZE)
8751 len = linux_iocparm_len(cmd);
8752 #else
8753 /* otherwise guess at what's safe */
8754 len = DEFULT_IOCTL_NARG_LEN;
8755 #endif
8756
8757 return len;
8758 }
8759
8760 #ifdef HAVE_FCNTL
8761 #ifdef __linux__
8762 typedef long fcntl_arg_t;
8763 #else
8764 /* posix */
8765 typedef int fcntl_arg_t;
8766 #endif
8767
8768 static long
8769 fcntl_narg_len(int cmd)
8770 {
8771 long len;
8772
8773 switch (cmd) {
8774 #ifdef F_DUPFD
8775 case F_DUPFD:
8776 len = sizeof(fcntl_arg_t);
8777 break;
8778 #endif
8779 #ifdef F_DUP2FD /* bsd specific */
8780 case F_DUP2FD:
8781 len = sizeof(int);
8782 break;
8783 #endif
8784 #ifdef F_DUPFD_CLOEXEC /* linux specific */
8785 case F_DUPFD_CLOEXEC:
8786 len = sizeof(fcntl_arg_t);
8787 break;
8788 #endif
8789 #ifdef F_GETFD
8790 case F_GETFD:
8791 len = 1;
8792 break;
8793 #endif
8794 #ifdef F_SETFD
8795 case F_SETFD:
8796 len = sizeof(fcntl_arg_t);
8797 break;
8798 #endif
8799 #ifdef F_GETFL
8800 case F_GETFL:
8801 len = 1;
8802 break;
8803 #endif
8804 #ifdef F_SETFL
8805 case F_SETFL:
8806 len = sizeof(fcntl_arg_t);
8807 break;
8808 #endif
8809 #ifdef F_GETOWN
8810 case F_GETOWN:
8811 len = 1;
8812 break;
8813 #endif
8814 #ifdef F_SETOWN
8815 case F_SETOWN:
8816 len = sizeof(fcntl_arg_t);
8817 break;
8818 #endif
8819 #ifdef F_GETOWN_EX /* linux specific */
8820 case F_GETOWN_EX:
8821 len = sizeof(struct f_owner_ex);
8822 break;
8823 #endif
8824 #ifdef F_SETOWN_EX /* linux specific */
8825 case F_SETOWN_EX:
8826 len = sizeof(struct f_owner_ex);
8827 break;
8828 #endif
8829 #ifdef F_GETLK
8830 case F_GETLK:
8831 len = sizeof(struct flock);
8832 break;
8833 #endif
8834 #ifdef F_SETLK
8835 case F_SETLK:
8836 len = sizeof(struct flock);
8837 break;
8838 #endif
8839 #ifdef F_SETLKW
8840 case F_SETLKW:
8841 len = sizeof(struct flock);
8842 break;
8843 #endif
8844 #ifdef F_READAHEAD /* bsd specific */
8845 case F_READAHEAD:
8846 len = sizeof(int);
8847 break;
8848 #endif
8849 #ifdef F_RDAHEAD /* Darwin specific */
8850 case F_RDAHEAD:
8851 len = sizeof(int);
8852 break;
8853 #endif
8854 #ifdef F_GETSIG /* linux specific */
8855 case F_GETSIG:
8856 len = 1;
8857 break;
8858 #endif
8859 #ifdef F_SETSIG /* linux specific */
8860 case F_SETSIG:
8861 len = sizeof(fcntl_arg_t);
8862 break;
8863 #endif
8864 #ifdef F_GETLEASE /* linux specific */
8865 case F_GETLEASE:
8866 len = 1;
8867 break;
8868 #endif
8869 #ifdef F_SETLEASE /* linux specific */
8870 case F_SETLEASE:
8871 len = sizeof(fcntl_arg_t);
8872 break;
8873 #endif
8874 #ifdef F_NOTIFY /* linux specific */
8875 case F_NOTIFY:
8876 len = sizeof(fcntl_arg_t);
8877 break;
8878 #endif
8879
8880 default:
8881 len = 256;
8882 break;
8883 }
8884
8885 return len;
8886 }
8887 #else /* HAVE_FCNTL */
8888 static long
8889 fcntl_narg_len(int cmd)
8890 {
8891 return 0;
8892 }
8893 #endif /* HAVE_FCNTL */
8894
8895 static long
8896 setup_narg(ioctl_req_t cmd, VALUE *argp, int io_p)
8897 {
8898 long narg = 0;
8899 VALUE arg = *argp;
8900
8901 if (NIL_P(arg) || arg == Qfalse) {
8902 narg = 0;
8903 }
8904 else if (FIXNUM_P(arg)) {
8905 narg = FIX2LONG(arg);
8906 }
8907 else if (arg == Qtrue) {
8908 narg = 1;
8909 }
8910 else {
8911 VALUE tmp = rb_check_string_type(arg);
8912
8913 if (NIL_P(tmp)) {
8914 narg = NUM2LONG(arg);
8915 }
8916 else {
8917 long len;
8918
8919 *argp = arg = tmp;
8920 if (io_p)
8921 len = ioctl_narg_len(cmd);
8922 else
8923 len = fcntl_narg_len((int)cmd);
8924 rb_str_modify(arg);
8925
8926 /* expand for data + sentinel. */
8927 if (RSTRING_LEN(arg) < len+1) {
8928 rb_str_resize(arg, len+1);
8929 }
8930 /* a little sanity check here */
8931 RSTRING_PTR(arg)[RSTRING_LEN(arg) - 1] = 17;
8932 narg = (long)(SIGNED_VALUE)RSTRING_PTR(arg);
8933 }
8934 }
8935
8936 return narg;
8937 }
8938
8939 static VALUE
8940 rb_ioctl(VALUE io, VALUE req, VALUE arg)
8941 {
8942 ioctl_req_t cmd = NUM2IOCTLREQ(req);
8943 rb_io_t *fptr;
8944 long narg;
8945 int retval;
8946
8947 rb_secure(2);
8948
8949 narg = setup_narg(cmd, &arg, 1);
8950 GetOpenFile(io, fptr);
8951 retval = do_ioctl(fptr->fd, cmd, narg);
8952 if (retval < 0) rb_sys_fail_path(fptr->pathv);
8953 if (RB_TYPE_P(arg, T_STRING)) {
8954 if (RSTRING_PTR(arg)[RSTRING_LEN(arg)-1] != 17)
8955 rb_raise(rb_eArgError, "return value overflowed string");
8956 RSTRING_PTR(arg)[RSTRING_LEN(arg)-1] = '\0';
8957 }
8958
8959 return INT2NUM(retval);
8960 }
8961
8962 /*
8963 * call-seq:
8964 * ios.ioctl(integer_cmd, arg) -> integer
8965 *
8966 * Provides a mechanism for issuing low-level commands to control or
8967 * query I/O devices. Arguments and results are platform dependent. If
8968 * <i>arg</i> is a number, its value is passed directly. If it is a
8969 * string, it is interpreted as a binary sequence of bytes. On Unix
8970 * platforms, see <code>ioctl(2)</code> for details. Not implemented on
8971 * all platforms.
8972 */
8973
8974 static VALUE
8975 rb_io_ioctl(int argc, VALUE *argv, VALUE io)
8976 {
8977 VALUE req, arg;
8978
8979 rb_scan_args(argc, argv, "11", &req, &arg);
8980 return rb_ioctl(io, req, arg);
8981 }
8982
8983 #ifdef HAVE_FCNTL
8984 struct fcntl_arg {
8985 int fd;
8986 int cmd;
8987 long narg;
8988 };
8989
8990 static VALUE
8991 nogvl_fcntl(void *ptr)
8992 {
8993 struct fcntl_arg *arg = ptr;
8994
8995 #if defined(F_DUPFD)
8996 if (arg->cmd == F_DUPFD)
8997 return (VALUE)rb_cloexec_fcntl_dupfd(arg->fd, (int)arg->narg);
8998 #endif
8999 return (VALUE)fcntl(arg->fd, arg->cmd, arg->narg);
9000 }
9001
9002 static int
9003 do_fcntl(int fd, int cmd, long narg)
9004 {
9005 int retval;
9006 struct fcntl_arg arg;
9007
9008 arg.fd = fd;
9009 arg.cmd = cmd;
9010 arg.narg = narg;
9011
9012 retval = (int)rb_thread_io_blocking_region(nogvl_fcntl, &arg, fd);
9013 #if defined(F_DUPFD)
9014 if (retval != -1 && cmd == F_DUPFD) {
9015 rb_update_max_fd(retval);
9016 }
9017 #endif
9018
9019 return retval;
9020 }
9021
9022 static VALUE
9023 rb_fcntl(VALUE io, VALUE req, VALUE arg)
9024 {
9025 int cmd = NUM2INT(req);
9026 rb_io_t *fptr;
9027 long narg;
9028 int retval;
9029
9030 rb_secure(2);
9031
9032 narg = setup_narg(cmd, &arg, 0);
9033 GetOpenFile(io, fptr);
9034 retval = do_fcntl(fptr->fd, cmd, narg);
9035 if (retval < 0) rb_sys_fail_path(fptr->pathv);
9036 if (RB_TYPE_P(arg, T_STRING)) {
9037 if (RSTRING_PTR(arg)[RSTRING_LEN(arg)-1] != 17)
9038 rb_raise(rb_eArgError, "return value overflowed string");
9039 RSTRING_PTR(arg)[RSTRING_LEN(arg)-1] = '\0';
9040 }
9041
9042 if (cmd == F_SETFL) {
9043 if (narg & O_NONBLOCK) {
9044 fptr->mode |= FMODE_WSPLIT_INITIALIZED;
9045 fptr->mode &= ~FMODE_WSPLIT;
9046 }
9047 else {
9048 fptr->mode &= ~(FMODE_WSPLIT_INITIALIZED|FMODE_WSPLIT);
9049 }
9050 }
9051
9052 return INT2NUM(retval);
9053 }
9054
9055 /*
9056 * call-seq:
9057 * ios.fcntl(integer_cmd, arg) -> integer
9058 *
9059 * Provides a mechanism for issuing low-level commands to control or
9060 * query file-oriented I/O streams. Arguments and results are platform
9061 * dependent. If <i>arg</i> is a number, its value is passed
9062 * directly. If it is a string, it is interpreted as a binary sequence
9063 * of bytes (<code>Array#pack</code> might be a useful way to build this
9064 * string). On Unix platforms, see <code>fcntl(2)</code> for details.
9065 * Not implemented on all platforms.
9066 */
9067
9068 static VALUE
9069 rb_io_fcntl(int argc, VALUE *argv, VALUE io)
9070 {
9071 VALUE req, arg;
9072
9073 rb_scan_args(argc, argv, "11", &req, &arg);
9074 return rb_fcntl(io, req, arg);
9075 }
9076 #else
9077 #define rb_io_fcntl rb_f_notimplement
9078 #endif
9079
9080 #if defined(HAVE_SYSCALL) || defined(HAVE___SYSCALL)
9081 /*
9082 * call-seq:
9083 * syscall(num [, args...]) -> integer
9084 *
9085 * Calls the operating system function identified by _num_ and
9086 * returns the result of the function or raises SystemCallError if
9087 * it failed.
9088 *
9089 * Arguments for the function can follow _num_. They must be either
9090 * +String+ objects or +Integer+ objects. A +String+ object is passed
9091 * as a pointer to the byte sequence. An +Integer+ object is passed
9092 * as an integer whose bit size is same as a pointer.
9093 * Up to nine parameters may be passed (14 on the Atari-ST).
9094 *
9095 * The function identified by _num_ is system
9096 * dependent. On some Unix systems, the numbers may be obtained from a
9097 * header file called <code>syscall.h</code>.
9098 *
9099 * syscall 4, 1, "hello\n", 6 # '4' is write(2) on our box
9100 *
9101 * <em>produces:</em>
9102 *
9103 * hello
9104 *
9105 *
9106 * Calling +syscall+ on a platform which does not have any way to
9107 * an arbitrary system function just fails with NotImplementedError.
9108 *
9109 * Note::
9110 * +syscall+ is essentially unsafe and unportable. Feel free to shoot your foot.
9111 * DL (Fiddle) library is preferred for safer and a bit more portable programming.
9112 */
9113
9114 static VALUE
9115 rb_f_syscall(int argc, VALUE *argv)
9116 {
9117 #ifdef atarist
9118 VALUE arg[13]; /* yes, we really need that many ! */
9119 #else
9120 VALUE arg[8];
9121 #endif
9122 #if SIZEOF_VOIDP == 8 && defined(HAVE___SYSCALL) && SIZEOF_INT != 8 /* mainly *BSD */
9123 # define SYSCALL __syscall
9124 # define NUM2SYSCALLID(x) NUM2LONG(x)
9125 # define RETVAL2NUM(x) LONG2NUM(x)
9126 # if SIZEOF_LONG == 8
9127 long num, retval = -1;
9128 # elif SIZEOF_LONG_LONG == 8
9129 long long num, retval = -1;
9130 # else
9131 # error ---->> it is asserted that __syscall takes the first argument and returns retval in 64bit signed integer. <<----
9132 # endif
9133 #elif defined(__linux__)
9134 # define SYSCALL syscall
9135 # define NUM2SYSCALLID(x) NUM2LONG(x)
9136 # define RETVAL2NUM(x) LONG2NUM(x)
9137 /*
9138 * Linux man page says, syscall(2) function prototype is below.
9139 *
9140 * int syscall(int number, ...);
9141 *
9142 * But, it's incorrect. Actual one takes and returned long. (see unistd.h)
9143 */
9144 long num, retval = -1;
9145 #else
9146 # define SYSCALL syscall
9147 # define NUM2SYSCALLID(x) NUM2INT(x)
9148 # define RETVAL2NUM(x) INT2NUM(x)
9149 int num, retval = -1;
9150 #endif
9151 int i;
9152
9153 if (RTEST(ruby_verbose)) {
9154 rb_warning("We plan to remove a syscall function at future release. DL(Fiddle) provides safer alternative.");
9155 }
9156
9157 rb_secure(2);
9158 if (argc == 0)
9159 rb_raise(rb_eArgError, "too few arguments for syscall");
9160 if (argc > numberof(arg))
9161 rb_raise(rb_eArgError, "too many arguments for syscall");
9162 num = NUM2SYSCALLID(argv[0]); ++argv;
9163 for (i = argc - 1; i--; ) {
9164 VALUE v = rb_check_string_type(argv[i]);
9165
9166 if (!NIL_P(v)) {
9167 SafeStringValue(v);
9168 rb_str_modify(v);
9169 arg[i] = (VALUE)StringValueCStr(v);
9170 }
9171 else {
9172 arg[i] = (VALUE)NUM2LONG(argv[i]);
9173 }
9174 }
9175
9176 switch (argc) {
9177 case 1:
9178 retval = SYSCALL(num);
9179 break;
9180 case 2:
9181 retval = SYSCALL(num, arg[0]);
9182 break;
9183 case 3:
9184 retval = SYSCALL(num, arg[0],arg[1]);
9185 break;
9186 case 4:
9187 retval = SYSCALL(num, arg[0],arg[1],arg[2]);
9188 break;
9189 case 5:
9190 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3]);
9191 break;
9192 case 6:
9193 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4]);
9194 break;
9195 case 7:
9196 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5]);
9197 break;
9198 case 8:
9199 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6]);
9200 break;
9201 #ifdef atarist
9202 case 9:
9203 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
9204 arg[7]);
9205 break;
9206 case 10:
9207 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
9208 arg[7], arg[8]);
9209 break;
9210 case 11:
9211 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
9212 arg[7], arg[8], arg[9]);
9213 break;
9214 case 12:
9215 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
9216 arg[7], arg[8], arg[9], arg[10]);
9217 break;
9218 case 13:
9219 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
9220 arg[7], arg[8], arg[9], arg[10], arg[11]);
9221 break;
9222 case 14:
9223 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
9224 arg[7], arg[8], arg[9], arg[10], arg[11], arg[12]);
9225 break;
9226 #endif
9227 }
9228
9229 if (retval == -1)
9230 rb_sys_fail(0);
9231 return RETVAL2NUM(retval);
9232 #undef SYSCALL
9233 #undef NUM2SYSCALLID
9234 #undef RETVAL2NUM
9235 }
9236 #else
9237 #define rb_f_syscall rb_f_notimplement
9238 #endif
9239
9240 static VALUE
9241 io_new_instance(VALUE args)
9242 {
9243 return rb_class_new_instance(2, (VALUE*)args+1, *(VALUE*)args);
9244 }
9245
9246 static rb_encoding *
9247 find_encoding(VALUE v)
9248 {
9249 rb_encoding *enc = rb_find_encoding(v);
9250 if (!enc) unsupported_encoding(StringValueCStr(v));
9251 return enc;
9252 }
9253
9254 static void
9255 io_encoding_set(rb_io_t *fptr, VALUE v1, VALUE v2, VALUE opt)
9256 {
9257 rb_encoding *enc, *enc2;
9258 int ecflags = fptr->encs.ecflags;
9259 VALUE ecopts, tmp;
9260
9261 if (!NIL_P(v2)) {
9262 enc2 = find_encoding(v1);
9263 tmp = rb_check_string_type(v2);
9264 if (!NIL_P(tmp)) {
9265 if (RSTRING_LEN(tmp) == 1 && RSTRING_PTR(tmp)[0] == '-') {
9266 /* Special case - "-" => no transcoding */
9267 enc = enc2;
9268 enc2 = NULL;
9269 }
9270 else
9271 enc = find_encoding(v2);
9272 if (enc == enc2) {
9273 /* Special case - "-" => no transcoding */
9274 enc2 = NULL;
9275 }
9276 }
9277 else {
9278 enc = find_encoding(v2);
9279 if (enc == enc2) {
9280 /* Special case - "-" => no transcoding */
9281 enc2 = NULL;
9282 }
9283 }
9284 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
9285 ecflags = rb_econv_prepare_options(opt, &ecopts, ecflags);
9286 }
9287 else {
9288 if (NIL_P(v1)) {
9289 /* Set to default encodings */
9290 rb_io_ext_int_to_encs(NULL, NULL, &enc, &enc2, 0);
9291 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
9292 ecopts = Qnil;
9293 }
9294 else {
9295 tmp = rb_check_string_type(v1);
9296 if (!NIL_P(tmp) && rb_enc_asciicompat(rb_enc_get(tmp))) {
9297 parse_mode_enc(RSTRING_PTR(tmp), &enc, &enc2, NULL);
9298 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
9299 ecflags = rb_econv_prepare_options(opt, &ecopts, ecflags);
9300 }
9301 else {
9302 rb_io_ext_int_to_encs(find_encoding(v1), NULL, &enc, &enc2, 0);
9303 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
9304 ecopts = Qnil;
9305 }
9306 }
9307 }
9308 validate_enc_binmode(&fptr->mode, ecflags, enc, enc2);
9309 fptr->encs.enc = enc;
9310 fptr->encs.enc2 = enc2;
9311 fptr->encs.ecflags = ecflags;
9312 fptr->encs.ecopts = ecopts;
9313 clear_codeconv(fptr);
9314
9315 }
9316
9317 static VALUE
9318 pipe_pair_close(VALUE rw)
9319 {
9320 VALUE *rwp = (VALUE *)rw;
9321 return rb_ensure(io_close, rwp[0], io_close, rwp[1]);
9322 }
9323
9324 /*
9325 * call-seq:
9326 * IO.pipe -> [read_io, write_io]
9327 * IO.pipe(ext_enc) -> [read_io, write_io]
9328 * IO.pipe("ext_enc:int_enc" [, opt]) -> [read_io, write_io]
9329 * IO.pipe(ext_enc, int_enc [, opt]) -> [read_io, write_io]
9330 *
9331 * IO.pipe(...) {|read_io, write_io| ... }
9332 *
9333 * Creates a pair of pipe endpoints (connected to each other) and
9334 * returns them as a two-element array of <code>IO</code> objects:
9335 * <code>[</code> <i>read_io</i>, <i>write_io</i> <code>]</code>.
9336 *
9337 * If a block is given, the block is called and
9338 * returns the value of the block.
9339 * <i>read_io</i> and <i>write_io</i> are sent to the block as arguments.
9340 * If read_io and write_io are not closed when the block exits, they are closed.
9341 * i.e. closing read_io and/or write_io doesn't cause an error.
9342 *
9343 * Not available on all platforms.
9344 *
9345 * If an encoding (encoding name or encoding object) is specified as an optional argument,
9346 * read string from pipe is tagged with the encoding specified.
9347 * If the argument is a colon separated two encoding names "A:B",
9348 * the read string is converted from encoding A (external encoding)
9349 * to encoding B (internal encoding), then tagged with B.
9350 * If two optional arguments are specified, those must be
9351 * encoding objects or encoding names,
9352 * and the first one is the external encoding,
9353 * and the second one is the internal encoding.
9354 * If the external encoding and the internal encoding is specified,
9355 * optional hash argument specify the conversion option.
9356 *
9357 * In the example below, the two processes close the ends of the pipe
9358 * that they are not using. This is not just a cosmetic nicety. The
9359 * read end of a pipe will not generate an end of file condition if
9360 * there are any writers with the pipe still open. In the case of the
9361 * parent process, the <code>rd.read</code> will never return if it
9362 * does not first issue a <code>wr.close</code>.
9363 *
9364 * rd, wr = IO.pipe
9365 *
9366 * if fork
9367 * wr.close
9368 * puts "Parent got: <#{rd.read}>"
9369 * rd.close
9370 * Process.wait
9371 * else
9372 * rd.close
9373 * puts "Sending message to parent"
9374 * wr.write "Hi Dad"
9375 * wr.close
9376 * end
9377 *
9378 * <em>produces:</em>
9379 *
9380 * Sending message to parent
9381 * Parent got: <Hi Dad>
9382 */
9383
9384 static VALUE
9385 rb_io_s_pipe(int argc, VALUE *argv, VALUE klass)
9386 {
9387 int pipes[2], state;
9388 VALUE r, w, args[3], v1, v2;
9389 VALUE opt;
9390 rb_io_t *fptr, *fptr2;
9391 int fmode = 0;
9392 VALUE ret;
9393
9394 argc = rb_scan_args(argc, argv, "02:", &v1, &v2, &opt);
9395 if (rb_pipe(pipes) == -1)
9396 rb_sys_fail(0);
9397
9398 args[0] = klass;
9399 args[1] = INT2NUM(pipes[0]);
9400 args[2] = INT2FIX(O_RDONLY);
9401 r = rb_protect(io_new_instance, (VALUE)args, &state);
9402 if (state) {
9403 close(pipes[0]);
9404 close(pipes[1]);
9405 rb_jump_tag(state);
9406 }
9407 GetOpenFile(r, fptr);
9408 io_encoding_set(fptr, v1, v2, opt);
9409 args[1] = INT2NUM(pipes[1]);
9410 args[2] = INT2FIX(O_WRONLY);
9411 w = rb_protect(io_new_instance, (VALUE)args, &state);
9412 if (state) {
9413 close(pipes[1]);
9414 if (!NIL_P(r)) rb_io_close(r);
9415 rb_jump_tag(state);
9416 }
9417 GetOpenFile(w, fptr2);
9418 rb_io_synchronized(fptr2);
9419
9420 extract_binmode(opt, &fmode);
9421 #if DEFAULT_TEXTMODE
9422 if ((fptr->mode & FMODE_TEXTMODE) && (fmode & FMODE_BINMODE)) {
9423 fptr->mode &= ~FMODE_TEXTMODE;
9424 setmode(fptr->fd, O_BINARY);
9425 }
9426 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
9427 if (fptr->encs.ecflags & ECONV_DEFAULT_NEWLINE_DECORATOR) {
9428 fptr->encs.ecflags |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;
9429 }
9430 #endif
9431 #endif
9432 fptr->mode |= fmode;
9433 #if DEFAULT_TEXTMODE
9434 if ((fptr2->mode & FMODE_TEXTMODE) && (fmode & FMODE_BINMODE)) {
9435 fptr2->mode &= ~FMODE_TEXTMODE;
9436 setmode(fptr2->fd, O_BINARY);
9437 }
9438 #endif
9439 fptr2->mode |= fmode;
9440
9441 ret = rb_assoc_new(r, w);
9442 if (rb_block_given_p()) {
9443 VALUE rw[2];
9444 rw[0] = r;
9445 rw[1] = w;
9446 return rb_ensure(rb_yield, ret, pipe_pair_close, (VALUE)rw);
9447 }
9448 return ret;
9449 }
9450
9451 struct foreach_arg {
9452 int argc;
9453 VALUE *argv;
9454 VALUE io;
9455 };
9456
9457 static void
9458 open_key_args(int argc, VALUE *argv, VALUE opt, struct foreach_arg *arg)
9459 {
9460 VALUE path, v;
9461
9462 path = *argv++;
9463 argc--;
9464 FilePathValue(path);
9465 arg->io = 0;
9466 arg->argc = argc;
9467 arg->argv = argv;
9468 if (NIL_P(opt)) {
9469 arg->io = rb_io_open(path, INT2NUM(O_RDONLY), INT2FIX(0666), Qnil);
9470 return;
9471 }
9472 v = rb_hash_aref(opt, sym_open_args);
9473 if (!NIL_P(v)) {
9474 VALUE args;
9475 long n;
9476
9477 v = rb_convert_type(v, T_ARRAY, "Array", "to_ary");
9478 n = RARRAY_LEN(v) + 1;
9479 #if SIZEOF_LONG > SIZEOF_INT
9480 if (n > INT_MAX) {
9481 rb_raise(rb_eArgError, "too many arguments");
9482 }
9483 #endif
9484 args = rb_ary_tmp_new(n);
9485 rb_ary_push(args, path);
9486 rb_ary_concat(args, v);
9487 arg->io = rb_io_open_with_args((int)n, RARRAY_CONST_PTR(args));
9488 rb_ary_clear(args); /* prevent from GC */
9489 return;
9490 }
9491 arg->io = rb_io_open(path, Qnil, Qnil, opt);
9492 }
9493
9494 static VALUE
9495 io_s_foreach(struct foreach_arg *arg)
9496 {
9497 VALUE str;
9498
9499 while (!NIL_P(str = rb_io_gets_m(arg->argc, arg->argv, arg->io))) {
9500 rb_yield(str);
9501 }
9502 return Qnil;
9503 }
9504
9505 /*
9506 * call-seq:
9507 * IO.foreach(name, sep=$/ [, open_args]) {|line| block } -> nil
9508 * IO.foreach(name, limit [, open_args]) {|line| block } -> nil
9509 * IO.foreach(name, sep, limit [, open_args]) {|line| block } -> nil
9510 * IO.foreach(...) -> an_enumerator
9511 *
9512 * Executes the block for every line in the named I/O port, where lines
9513 * are separated by <em>sep</em>.
9514 *
9515 * If no block is given, an enumerator is returned instead.
9516 *
9517 * IO.foreach("testfile") {|x| print "GOT ", x }
9518 *
9519 * <em>produces:</em>
9520 *
9521 * GOT This is line one
9522 * GOT This is line two
9523 * GOT This is line three
9524 * GOT And so on...
9525 *
9526 * If the last argument is a hash, it's the keyword argument to open.
9527 * See <code>IO.read</code> for detail.
9528 *
9529 */
9530
9531 static VALUE
9532 rb_io_s_foreach(int argc, VALUE *argv, VALUE self)
9533 {
9534 VALUE opt;
9535 int orig_argc = argc;
9536 struct foreach_arg arg;
9537
9538 argc = rb_scan_args(argc, argv, "13:", NULL, NULL, NULL, NULL, &opt);
9539 RETURN_ENUMERATOR(self, orig_argc, argv);
9540 open_key_args(argc, argv, opt, &arg);
9541 if (NIL_P(arg.io)) return Qnil;
9542 return rb_ensure(io_s_foreach, (VALUE)&arg, rb_io_close, arg.io);
9543 }
9544
9545 static VALUE
9546 io_s_readlines(struct foreach_arg *arg)
9547 {
9548 return rb_io_readlines(arg->argc, arg->argv, arg->io);
9549 }
9550
9551 /*
9552 * call-seq:
9553 * IO.readlines(name, sep=$/ [, open_args]) -> array
9554 * IO.readlines(name, limit [, open_args]) -> array
9555 * IO.readlines(name, sep, limit [, open_args]) -> array
9556 *
9557 * Reads the entire file specified by <i>name</i> as individual
9558 * lines, and returns those lines in an array. Lines are separated by
9559 * <i>sep</i>.
9560 *
9561 * a = IO.readlines("testfile")
9562 * a[0] #=> "This is line one\n"
9563 *
9564 * If the last argument is a hash, it's the keyword argument to open.
9565 * See <code>IO.read</code> for detail.
9566 *
9567 */
9568
9569 static VALUE
9570 rb_io_s_readlines(int argc, VALUE *argv, VALUE io)
9571 {
9572 VALUE opt;
9573 struct foreach_arg arg;
9574
9575 argc = rb_scan_args(argc, argv, "13:", NULL, NULL, NULL, NULL, &opt);
9576 open_key_args(argc, argv, opt, &arg);
9577 if (NIL_P(arg.io)) return Qnil;
9578 return rb_ensure(io_s_readlines, (VALUE)&arg, rb_io_close, arg.io);
9579 }
9580
9581 static VALUE
9582 io_s_read(struct foreach_arg *arg)
9583 {
9584 return io_read(arg->argc, arg->argv, arg->io);
9585 }
9586
9587 struct seek_arg {
9588 VALUE io;
9589 VALUE offset;
9590 int mode;
9591 };
9592
9593 static VALUE
9594 seek_before_access(VALUE argp)
9595 {
9596 struct seek_arg *arg = (struct seek_arg *)argp;
9597 rb_io_binmode(arg->io);
9598 return rb_io_seek(arg->io, arg->offset, arg->mode);
9599 }
9600
9601 /*
9602 * call-seq:
9603 * IO.read(name, [length [, offset]] ) -> string
9604 * IO.read(name, [length [, offset]], open_args) -> string
9605 *
9606 * Opens the file, optionally seeks to the given +offset+, then returns
9607 * +length+ bytes (defaulting to the rest of the file). <code>read</code>
9608 * ensures the file is closed before returning.
9609 *
9610 * If the last argument is a hash, it specifies option for internal
9611 * open(). The key would be the following. open_args: is exclusive
9612 * to others.
9613 *
9614 * encoding::
9615 * string or encoding
9616 *
9617 * specifies encoding of the read string. +encoding+ will be ignored
9618 * if length is specified.
9619 *
9620 * mode::
9621 * string
9622 *
9623 * specifies mode argument for open(). It should start with "r"
9624 * otherwise it will cause an error.
9625 *
9626 * open_args:: array of strings
9627 *
9628 * specifies arguments for open() as an array.
9629 *
9630 * Examples:
9631 *
9632 * IO.read("testfile") #=> "This is line one\nThis is line two\nThis is line three\nAnd so on...\n"
9633 * IO.read("testfile", 20) #=> "This is line one\nThi"
9634 * IO.read("testfile", 20, 10) #=> "ne one\nThis is line "
9635 */
9636
9637 static VALUE
9638 rb_io_s_read(int argc, VALUE *argv, VALUE io)
9639 {
9640 VALUE opt, offset;
9641 struct foreach_arg arg;
9642
9643 argc = rb_scan_args(argc, argv, "13:", NULL, NULL, &offset, NULL, &opt);
9644 open_key_args(argc, argv, opt, &arg);
9645 if (NIL_P(arg.io)) return Qnil;
9646 if (!NIL_P(offset)) {
9647 struct seek_arg sarg;
9648 int state = 0;
9649 sarg.io = arg.io;
9650 sarg.offset = offset;
9651 sarg.mode = SEEK_SET;
9652 rb_protect(seek_before_access, (VALUE)&sarg, &state);
9653 if (state) {
9654 rb_io_close(arg.io);
9655 rb_jump_tag(state);
9656 }
9657 if (arg.argc == 2) arg.argc = 1;
9658 }
9659 return rb_ensure(io_s_read, (VALUE)&arg, rb_io_close, arg.io);
9660 }
9661
9662 /*
9663 * call-seq:
9664 * IO.binread(name, [length [, offset]] ) -> string
9665 *
9666 * Opens the file, optionally seeks to the given <i>offset</i>, then returns
9667 * <i>length</i> bytes (defaulting to the rest of the file).
9668 * <code>binread</code> ensures the file is closed before returning.
9669 * The open mode would be "rb:ASCII-8BIT".
9670 *
9671 * IO.binread("testfile") #=> "This is line one\nThis is line two\nThis is line three\nAnd so on...\n"
9672 * IO.binread("testfile", 20) #=> "This is line one\nThi"
9673 * IO.binread("testfile", 20, 10) #=> "ne one\nThis is line "
9674 */
9675
9676 static VALUE
9677 rb_io_s_binread(int argc, VALUE *argv, VALUE io)
9678 {
9679 VALUE offset;
9680 struct foreach_arg arg;
9681
9682 rb_scan_args(argc, argv, "12", NULL, NULL, &offset);
9683 FilePathValue(argv[0]);
9684 arg.io = rb_io_open(argv[0], rb_str_new_cstr("rb:ASCII-8BIT"), Qnil, Qnil);
9685 if (NIL_P(arg.io)) return Qnil;
9686 arg.argv = argv+1;
9687 arg.argc = (argc > 1) ? 1 : 0;
9688 if (!NIL_P(offset)) {
9689 rb_io_seek(arg.io, offset, SEEK_SET);
9690 }
9691 return rb_ensure(io_s_read, (VALUE)&arg, rb_io_close, arg.io);
9692 }
9693
9694 static VALUE
9695 io_s_write0(struct write_arg *arg)
9696 {
9697 return io_write(arg->io,arg->str,arg->nosync);
9698 }
9699
9700 static VALUE
9701 io_s_write(int argc, VALUE *argv, int binary)
9702 {
9703 VALUE string, offset, opt;
9704 struct foreach_arg arg;
9705 struct write_arg warg;
9706
9707 rb_scan_args(argc, argv, "21:", NULL, &string, &offset, &opt);
9708
9709 if (NIL_P(opt)) opt = rb_hash_new();
9710 else opt = rb_hash_dup(opt);
9711
9712
9713 if (NIL_P(rb_hash_aref(opt,sym_mode))) {
9714 int mode = O_WRONLY|O_CREAT;
9715 #ifdef O_BINARY
9716 if (binary) mode |= O_BINARY;
9717 #endif
9718 if (NIL_P(offset)) mode |= O_TRUNC;
9719 rb_hash_aset(opt,sym_mode,INT2NUM(mode));
9720 }
9721 open_key_args(argc,argv,opt,&arg);
9722
9723 #ifndef O_BINARY
9724 if (binary) rb_io_binmode_m(arg.io);
9725 #endif
9726
9727 if (NIL_P(arg.io)) return Qnil;
9728 if (!NIL_P(offset)) {
9729 struct seek_arg sarg;
9730 int state = 0;
9731 sarg.io = arg.io;
9732 sarg.offset = offset;
9733 sarg.mode = SEEK_SET;
9734 rb_protect(seek_before_access, (VALUE)&sarg, &state);
9735 if (state) {
9736 rb_io_close(arg.io);
9737 rb_jump_tag(state);
9738 }
9739 }
9740
9741 warg.io = arg.io;
9742 warg.str = string;
9743 warg.nosync = 0;
9744
9745 return rb_ensure(io_s_write0, (VALUE)&warg, rb_io_close, arg.io);
9746 }
9747
9748 /*
9749 * call-seq:
9750 * IO.write(name, string, [offset] ) => fixnum
9751 * IO.write(name, string, [offset], open_args ) => fixnum
9752 *
9753 * Opens the file, optionally seeks to the given <i>offset</i>, writes
9754 * <i>string</i>, then returns the length written.
9755 * <code>write</code> ensures the file is closed before returning.
9756 * If <i>offset</i> is not given, the file is truncated. Otherwise,
9757 * it is not truncated.
9758 *
9759 * If the last argument is a hash, it specifies option for internal
9760 * open(). The key would be the following. open_args: is exclusive
9761 * to others.
9762 *
9763 * encoding: string or encoding
9764 *
9765 * specifies encoding of the read string. encoding will be ignored
9766 * if length is specified.
9767 *
9768 * mode: string
9769 *
9770 * specifies mode argument for open(). it should start with "w" or "a" or "r+"
9771 * otherwise it would cause error.
9772 *
9773 * perm: fixnum
9774 *
9775 * specifies perm argument for open().
9776 *
9777 * open_args: array
9778 *
9779 * specifies arguments for open() as an array.
9780 *
9781 * IO.write("testfile", "0123456789", 20) # => 10
9782 * # File could contain: "This is line one\nThi0123456789two\nThis is line three\nAnd so on...\n"
9783 * IO.write("testfile", "0123456789") #=> 10
9784 * # File would now read: "0123456789"
9785 */
9786
9787 static VALUE
9788 rb_io_s_write(int argc, VALUE *argv, VALUE io)
9789 {
9790 return io_s_write(argc, argv, 0);
9791 }
9792
9793 /*
9794 * call-seq:
9795 * IO.binwrite(name, string, [offset] ) => fixnum
9796 * IO.binwrite(name, string, [offset], open_args ) => fixnum
9797 *
9798 * Same as <code>IO.write</code> except opening the file in binary mode
9799 * and ASCII-8BIT encoding ("wb:ASCII-8BIT").
9800 *
9801 */
9802
9803 static VALUE
9804 rb_io_s_binwrite(int argc, VALUE *argv, VALUE io)
9805 {
9806 return io_s_write(argc, argv, 1);
9807 }
9808
9809 struct copy_stream_struct {
9810 VALUE src;
9811 VALUE dst;
9812 off_t copy_length; /* (off_t)-1 if not specified */
9813 off_t src_offset; /* (off_t)-1 if not specified */
9814
9815 int src_fd;
9816 int dst_fd;
9817 int close_src;
9818 int close_dst;
9819 off_t total;
9820 const char *syserr;
9821 int error_no;
9822 const char *notimp;
9823 rb_fdset_t fds;
9824 VALUE th;
9825 };
9826
9827 static void *
9828 exec_interrupts(void *arg)
9829 {
9830 VALUE th = (VALUE)arg;
9831 rb_thread_execute_interrupts(th);
9832 return NULL;
9833 }
9834
9835 /*
9836 * returns TRUE if the preceding system call was interrupted
9837 * so we can continue. If the thread was interrupted, we
9838 * reacquire the GVL to execute interrupts before continuing.
9839 */
9840 static int
9841 maygvl_copy_stream_continue_p(int has_gvl, struct copy_stream_struct *stp)
9842 {
9843 switch (errno) {
9844 case EINTR:
9845 #if defined(ERESTART)
9846 case ERESTART:
9847 #endif
9848 if (rb_thread_interrupted(stp->th)) {
9849 if (has_gvl)
9850 rb_thread_execute_interrupts(stp->th);
9851 else
9852 rb_thread_call_with_gvl(exec_interrupts, (void *)stp->th);
9853 }
9854 return TRUE;
9855 }
9856 return FALSE;
9857 }
9858
9859 static int
9860 maygvl_select(int has_gvl, int n, rb_fdset_t *rfds, rb_fdset_t *wfds, rb_fdset_t *efds, struct timeval *timeout)
9861 {
9862 if (has_gvl)
9863 return rb_thread_fd_select(n, rfds, wfds, efds, timeout);
9864 else
9865 return rb_fd_select(n, rfds, wfds, efds, timeout);
9866 }
9867
9868 static int
9869 maygvl_copy_stream_wait_read(int has_gvl, struct copy_stream_struct *stp)
9870 {
9871 int ret;
9872
9873 do {
9874 rb_fd_zero(&stp->fds);
9875 rb_fd_set(stp->src_fd, &stp->fds);
9876 ret = maygvl_select(has_gvl, rb_fd_max(&stp->fds), &stp->fds, NULL, NULL, NULL);
9877 } while (ret == -1 && maygvl_copy_stream_continue_p(has_gvl, stp));
9878
9879 if (ret == -1) {
9880 stp->syserr = "select";
9881 stp->error_no = errno;
9882 return -1;
9883 }
9884 return 0;
9885 }
9886
9887 static int
9888 nogvl_copy_stream_wait_write(struct copy_stream_struct *stp)
9889 {
9890 int ret;
9891
9892 do {
9893 rb_fd_zero(&stp->fds);
9894 rb_fd_set(stp->dst_fd, &stp->fds);
9895 ret = rb_fd_select(rb_fd_max(&stp->fds), NULL, &stp->fds, NULL, NULL);
9896 } while (ret == -1 && maygvl_copy_stream_continue_p(0, stp));
9897
9898 if (ret == -1) {
9899 stp->syserr = "select";
9900 stp->error_no = errno;
9901 return -1;
9902 }
9903 return 0;
9904 }
9905
9906 #ifdef HAVE_SENDFILE
9907
9908 # ifdef __linux__
9909 # define USE_SENDFILE
9910
9911 # ifdef HAVE_SYS_SENDFILE_H
9912 # include <sys/sendfile.h>
9913 # endif
9914
9915 static ssize_t
9916 simple_sendfile(int out_fd, int in_fd, off_t *offset, off_t count)
9917 {
9918 return sendfile(out_fd, in_fd, offset, (size_t)count);
9919 }
9920
9921 # elif 0 /* defined(__FreeBSD__) || defined(__DragonFly__) */ || defined(__APPLE__)
9922 /* This runs on FreeBSD8.1 r30210, but sendfiles blocks its execution
9923 * without cpuset -l 0.
9924 */
9925 # define USE_SENDFILE
9926
9927 # ifdef HAVE_SYS_UIO_H
9928 # include <sys/uio.h>
9929 # endif
9930
9931 static ssize_t
9932 simple_sendfile(int out_fd, int in_fd, off_t *offset, off_t count)
9933 {
9934 int r;
9935 off_t pos = offset ? *offset : lseek(in_fd, 0, SEEK_CUR);
9936 off_t sbytes;
9937 # ifdef __APPLE__
9938 r = sendfile(in_fd, out_fd, pos, &count, NULL, 0);
9939 sbytes = count;
9940 # else
9941 r = sendfile(in_fd, out_fd, pos, (size_t)count, NULL, &sbytes, 0);
9942 # endif
9943 if (r != 0 && sbytes == 0) return -1;
9944 if (offset) {
9945 *offset += sbytes;
9946 }
9947 else {
9948 lseek(in_fd, sbytes, SEEK_CUR);
9949 }
9950 return (ssize_t)sbytes;
9951 }
9952
9953 # endif
9954
9955 #endif
9956
9957 #ifdef USE_SENDFILE
9958 static int
9959 nogvl_copy_stream_sendfile(struct copy_stream_struct *stp)
9960 {
9961 struct stat src_stat, dst_stat;
9962 ssize_t ss;
9963 int ret;
9964
9965 off_t copy_length;
9966 off_t src_offset;
9967 int use_pread;
9968
9969 ret = fstat(stp->src_fd, &src_stat);
9970 if (ret == -1) {
9971 stp->syserr = "fstat";
9972 stp->error_no = errno;
9973 return -1;
9974 }
9975 if (!S_ISREG(src_stat.st_mode))
9976 return 0;
9977
9978 ret = fstat(stp->dst_fd, &dst_stat);
9979 if (ret == -1) {
9980 stp->syserr = "fstat";
9981 stp->error_no = errno;
9982 return -1;
9983 }
9984 if ((dst_stat.st_mode & S_IFMT) != S_IFSOCK)
9985 return 0;
9986
9987 src_offset = stp->src_offset;
9988 use_pread = src_offset != (off_t)-1;
9989
9990 copy_length = stp->copy_length;
9991 if (copy_length == (off_t)-1) {
9992 if (use_pread)
9993 copy_length = src_stat.st_size - src_offset;
9994 else {
9995 off_t cur;
9996 errno = 0;
9997 cur = lseek(stp->src_fd, 0, SEEK_CUR);
9998 if (cur == (off_t)-1 && errno) {
9999 stp->syserr = "lseek";
10000 stp->error_no = errno;
10001 return -1;
10002 }
10003 copy_length = src_stat.st_size - cur;
10004 }
10005 }
10006
10007 retry_sendfile:
10008 # if SIZEOF_OFF_T > SIZEOF_SIZE_T
10009 /* we are limited by the 32-bit ssize_t return value on 32-bit */
10010 ss = (copy_length > (off_t)SSIZE_MAX) ? SSIZE_MAX : (ssize_t)copy_length;
10011 # else
10012 ss = (ssize_t)copy_length;
10013 # endif
10014 if (use_pread) {
10015 ss = simple_sendfile(stp->dst_fd, stp->src_fd, &src_offset, ss);
10016 }
10017 else {
10018 ss = simple_sendfile(stp->dst_fd, stp->src_fd, NULL, ss);
10019 }
10020 if (0 < ss) {
10021 stp->total += ss;
10022 copy_length -= ss;
10023 if (0 < copy_length) {
10024 goto retry_sendfile;
10025 }
10026 }
10027 if (ss == -1) {
10028 if (maygvl_copy_stream_continue_p(0, stp))
10029 goto retry_sendfile;
10030 switch (errno) {
10031 case EINVAL:
10032 #ifdef ENOSYS
10033 case ENOSYS:
10034 #endif
10035 return 0;
10036 case EAGAIN:
10037 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
10038 case EWOULDBLOCK:
10039 #endif
10040 #ifndef __linux__
10041 /*
10042 * Linux requires stp->src_fd to be a mmap-able (regular) file,
10043 * select() reports regular files to always be "ready", so
10044 * there is no need to select() on it.
10045 * Other OSes may have the same limitation for sendfile() which
10046 * allow us to bypass maygvl_copy_stream_wait_read()...
10047 */
10048 if (maygvl_copy_stream_wait_read(0, stp) == -1)
10049 return -1;
10050 #endif
10051 if (nogvl_copy_stream_wait_write(stp) == -1)
10052 return -1;
10053 goto retry_sendfile;
10054 }
10055 stp->syserr = "sendfile";
10056 stp->error_no = errno;
10057 return -1;
10058 }
10059 return 1;
10060 }
10061 #endif
10062
10063 static ssize_t
10064 maygvl_read(int has_gvl, int fd, void *buf, size_t count)
10065 {
10066 if (has_gvl)
10067 return rb_read_internal(fd, buf, count);
10068 else
10069 return read(fd, buf, count);
10070 }
10071
10072 static ssize_t
10073 maygvl_copy_stream_read(int has_gvl, struct copy_stream_struct *stp, char *buf, size_t len, off_t offset)
10074 {
10075 ssize_t ss;
10076 retry_read:
10077 if (offset == (off_t)-1) {
10078 ss = maygvl_read(has_gvl, stp->src_fd, buf, len);
10079 }
10080 else {
10081 #ifdef HAVE_PREAD
10082 ss = pread(stp->src_fd, buf, len, offset);
10083 #else
10084 stp->notimp = "pread";
10085 return -1;
10086 #endif
10087 }
10088 if (ss == 0) {
10089 return 0;
10090 }
10091 if (ss == -1) {
10092 if (maygvl_copy_stream_continue_p(has_gvl, stp))
10093 goto retry_read;
10094 switch (errno) {
10095 case EAGAIN:
10096 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
10097 case EWOULDBLOCK:
10098 #endif
10099 if (maygvl_copy_stream_wait_read(has_gvl, stp) == -1)
10100 return -1;
10101 goto retry_read;
10102 #ifdef ENOSYS
10103 case ENOSYS:
10104 #endif
10105 stp->notimp = "pread";
10106 return -1;
10107 }
10108 stp->syserr = offset == (off_t)-1 ? "read" : "pread";
10109 stp->error_no = errno;
10110 return -1;
10111 }
10112 return ss;
10113 }
10114
10115 static int
10116 nogvl_copy_stream_write(struct copy_stream_struct *stp, char *buf, size_t len)
10117 {
10118 ssize_t ss;
10119 int off = 0;
10120 while (len) {
10121 ss = write(stp->dst_fd, buf+off, len);
10122 if (ss == -1) {
10123 if (maygvl_copy_stream_continue_p(0, stp))
10124 continue;
10125 if (errno == EAGAIN || errno == EWOULDBLOCK) {
10126 if (nogvl_copy_stream_wait_write(stp) == -1)
10127 return -1;
10128 continue;
10129 }
10130 stp->syserr = "write";
10131 stp->error_no = errno;
10132 return -1;
10133 }
10134 off += (int)ss;
10135 len -= (int)ss;
10136 stp->total += ss;
10137 }
10138 return 0;
10139 }
10140
10141 static void
10142 nogvl_copy_stream_read_write(struct copy_stream_struct *stp)
10143 {
10144 char buf[1024*16];
10145 size_t len;
10146 ssize_t ss;
10147 int ret;
10148 off_t copy_length;
10149 int use_eof;
10150 off_t src_offset;
10151 int use_pread;
10152
10153 copy_length = stp->copy_length;
10154 use_eof = copy_length == (off_t)-1;
10155 src_offset = stp->src_offset;
10156 use_pread = src_offset != (off_t)-1;
10157
10158 if (use_pread && stp->close_src) {
10159 off_t r;
10160 errno = 0;
10161 r = lseek(stp->src_fd, src_offset, SEEK_SET);
10162 if (r == (off_t)-1 && errno) {
10163 stp->syserr = "lseek";
10164 stp->error_no = errno;
10165 return;
10166 }
10167 src_offset = (off_t)-1;
10168 use_pread = 0;
10169 }
10170
10171 while (use_eof || 0 < copy_length) {
10172 if (!use_eof && copy_length < (off_t)sizeof(buf)) {
10173 len = (size_t)copy_length;
10174 }
10175 else {
10176 len = sizeof(buf);
10177 }
10178 if (use_pread) {
10179 ss = maygvl_copy_stream_read(0, stp, buf, len, src_offset);
10180 if (0 < ss)
10181 src_offset += ss;
10182 }
10183 else {
10184 ss = maygvl_copy_stream_read(0, stp, buf, len, (off_t)-1);
10185 }
10186 if (ss <= 0) /* EOF or error */
10187 return;
10188
10189 ret = nogvl_copy_stream_write(stp, buf, ss);
10190 if (ret < 0)
10191 return;
10192
10193 if (!use_eof)
10194 copy_length -= ss;
10195 }
10196 }
10197
10198 static void *
10199 nogvl_copy_stream_func(void *arg)
10200 {
10201 struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
10202 #ifdef USE_SENDFILE
10203 int ret;
10204 #endif
10205
10206 #ifdef USE_SENDFILE
10207 ret = nogvl_copy_stream_sendfile(stp);
10208 if (ret != 0)
10209 goto finish; /* error or success */
10210 #endif
10211
10212 nogvl_copy_stream_read_write(stp);
10213
10214 #ifdef USE_SENDFILE
10215 finish:
10216 #endif
10217 return 0;
10218 }
10219
10220 static VALUE
10221 copy_stream_fallback_body(VALUE arg)
10222 {
10223 struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
10224 const int buflen = 16*1024;
10225 VALUE n;
10226 VALUE buf = rb_str_buf_new(buflen);
10227 off_t rest = stp->copy_length;
10228 off_t off = stp->src_offset;
10229 ID read_method = id_readpartial;
10230
10231 if (stp->src_fd == -1) {
10232 if (!rb_respond_to(stp->src, read_method)) {
10233 read_method = id_read;
10234 }
10235 }
10236
10237 while (1) {
10238 long numwrote;
10239 long l;
10240 if (stp->copy_length == (off_t)-1) {
10241 l = buflen;
10242 }
10243 else {
10244 if (rest == 0)
10245 break;
10246 l = buflen < rest ? buflen : (long)rest;
10247 }
10248 if (stp->src_fd == -1) {
10249 VALUE rc = rb_funcall(stp->src, read_method, 2, INT2FIX(l), buf);
10250
10251 if (read_method == id_read && NIL_P(rc))
10252 break;
10253 }
10254 else {
10255 ssize_t ss;
10256 rb_str_resize(buf, buflen);
10257 ss = maygvl_copy_stream_read(1, stp, RSTRING_PTR(buf), l, off);
10258 if (ss == -1)
10259 return Qnil;
10260 if (ss == 0)
10261 rb_eof_error();
10262 rb_str_resize(buf, ss);
10263 if (off != (off_t)-1)
10264 off += ss;
10265 }
10266 n = rb_io_write(stp->dst, buf);
10267 numwrote = NUM2LONG(n);
10268 stp->total += numwrote;
10269 rest -= numwrote;
10270 if (read_method == id_read && RSTRING_LEN(buf) == 0) {
10271 break;
10272 }
10273 }
10274
10275 return Qnil;
10276 }
10277
10278 static VALUE
10279 copy_stream_fallback(struct copy_stream_struct *stp)
10280 {
10281 if (stp->src_fd == -1 && stp->src_offset != (off_t)-1) {
10282 rb_raise(rb_eArgError, "cannot specify src_offset for non-IO");
10283 }
10284 rb_rescue2(copy_stream_fallback_body, (VALUE)stp,
10285 (VALUE (*) (ANYARGS))0, (VALUE)0,
10286 rb_eEOFError, (VALUE)0);
10287 return Qnil;
10288 }
10289
10290 static VALUE
10291 copy_stream_body(VALUE arg)
10292 {
10293 struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
10294 VALUE src_io = stp->src, dst_io = stp->dst;
10295 rb_io_t *src_fptr = 0, *dst_fptr = 0;
10296 int src_fd, dst_fd;
10297 const int common_oflags = 0
10298 #ifdef O_NOCTTY
10299 | O_NOCTTY
10300 #endif
10301 ;
10302
10303 stp->th = rb_thread_current();
10304
10305 stp->total = 0;
10306
10307 if (src_io == argf ||
10308 !(RB_TYPE_P(src_io, T_FILE) ||
10309 RB_TYPE_P(src_io, T_STRING) ||
10310 rb_respond_to(src_io, rb_intern("to_path")))) {
10311 src_fd = -1;
10312 }
10313 else {
10314 if (!RB_TYPE_P(src_io, T_FILE)) {
10315 VALUE args[2];
10316 FilePathValue(src_io);
10317 args[0] = src_io;
10318 args[1] = INT2NUM(O_RDONLY|common_oflags);
10319 src_io = rb_class_new_instance(2, args, rb_cFile);
10320 stp->src = src_io;
10321 stp->close_src = 1;
10322 }
10323 GetOpenFile(src_io, src_fptr);
10324 rb_io_check_byte_readable(src_fptr);
10325 src_fd = src_fptr->fd;
10326 }
10327 stp->src_fd = src_fd;
10328
10329 if (dst_io == argf ||
10330 !(RB_TYPE_P(dst_io, T_FILE) ||
10331 RB_TYPE_P(dst_io, T_STRING) ||
10332 rb_respond_to(dst_io, rb_intern("to_path")))) {
10333 dst_fd = -1;
10334 }
10335 else {
10336 if (!RB_TYPE_P(dst_io, T_FILE)) {
10337 VALUE args[3];
10338 FilePathValue(dst_io);
10339 args[0] = dst_io;
10340 args[1] = INT2NUM(O_WRONLY|O_CREAT|O_TRUNC|common_oflags);
10341 args[2] = INT2FIX(0666);
10342 dst_io = rb_class_new_instance(3, args, rb_cFile);
10343 stp->dst = dst_io;
10344 stp->close_dst = 1;
10345 }
10346 else {
10347 dst_io = GetWriteIO(dst_io);
10348 stp->dst = dst_io;
10349 }
10350 GetOpenFile(dst_io, dst_fptr);
10351 rb_io_check_writable(dst_fptr);
10352 dst_fd = dst_fptr->fd;
10353 }
10354 stp->dst_fd = dst_fd;
10355
10356 #ifdef O_BINARY
10357 if (src_fptr)
10358 SET_BINARY_MODE_WITH_SEEK_CUR(src_fptr);
10359 #endif
10360 if (dst_fptr)
10361 io_ascii8bit_binmode(dst_fptr);
10362
10363 if (stp->src_offset == (off_t)-1 && src_fptr && src_fptr->rbuf.len) {
10364 size_t len = src_fptr->rbuf.len;
10365 VALUE str;
10366 if (stp->copy_length != (off_t)-1 && stp->copy_length < (off_t)len) {
10367 len = (size_t)stp->copy_length;
10368 }
10369 str = rb_str_buf_new(len);
10370 rb_str_resize(str,len);
10371 read_buffered_data(RSTRING_PTR(str), len, src_fptr);
10372 if (dst_fptr) { /* IO or filename */
10373 if (io_binwrite(str, RSTRING_PTR(str), RSTRING_LEN(str), dst_fptr, 0) < 0)
10374 rb_sys_fail(0);
10375 }
10376 else /* others such as StringIO */
10377 rb_io_write(dst_io, str);
10378 stp->total += len;
10379 if (stp->copy_length != (off_t)-1)
10380 stp->copy_length -= len;
10381 }
10382
10383 if (dst_fptr && io_fflush(dst_fptr) < 0) {
10384 rb_raise(rb_eIOError, "flush failed");
10385 }
10386
10387 if (stp->copy_length == 0)
10388 return Qnil;
10389
10390 if (src_fd == -1 || dst_fd == -1) {
10391 return copy_stream_fallback(stp);
10392 }
10393
10394 rb_fd_set(src_fd, &stp->fds);
10395 rb_fd_set(dst_fd, &stp->fds);
10396
10397 rb_thread_call_without_gvl(nogvl_copy_stream_func, (void*)stp, RUBY_UBF_IO, 0);
10398 return Qnil;
10399 }
10400
10401 static VALUE
10402 copy_stream_finalize(VALUE arg)
10403 {
10404 struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
10405 if (stp->close_src) {
10406 rb_io_close_m(stp->src);
10407 }
10408 if (stp->close_dst) {
10409 rb_io_close_m(stp->dst);
10410 }
10411 rb_fd_term(&stp->fds);
10412 if (stp->syserr) {
10413 errno = stp->error_no;
10414 rb_sys_fail(stp->syserr);
10415 }
10416 if (stp->notimp) {
10417 rb_raise(rb_eNotImpError, "%s() not implemented", stp->notimp);
10418 }
10419 return Qnil;
10420 }
10421
10422 /*
10423 * call-seq:
10424 * IO.copy_stream(src, dst)
10425 * IO.copy_stream(src, dst, copy_length)
10426 * IO.copy_stream(src, dst, copy_length, src_offset)
10427 *
10428 * IO.copy_stream copies <i>src</i> to <i>dst</i>.
10429 * <i>src</i> and <i>dst</i> is either a filename or an IO.
10430 *
10431 * This method returns the number of bytes copied.
10432 *
10433 * If optional arguments are not given,
10434 * the start position of the copy is
10435 * the beginning of the filename or
10436 * the current file offset of the IO.
10437 * The end position of the copy is the end of file.
10438 *
10439 * If <i>copy_length</i> is given,
10440 * No more than <i>copy_length</i> bytes are copied.
10441 *
10442 * If <i>src_offset</i> is given,
10443 * it specifies the start position of the copy.
10444 *
10445 * When <i>src_offset</i> is specified and
10446 * <i>src</i> is an IO,
10447 * IO.copy_stream doesn't move the current file offset.
10448 *
10449 */
10450 static VALUE
10451 rb_io_s_copy_stream(int argc, VALUE *argv, VALUE io)
10452 {
10453 VALUE src, dst, length, src_offset;
10454 struct copy_stream_struct st;
10455
10456 MEMZERO(&st, struct copy_stream_struct, 1);
10457
10458 rb_scan_args(argc, argv, "22", &src, &dst, &length, &src_offset);
10459
10460 st.src = src;
10461 st.dst = dst;
10462
10463 if (NIL_P(length))
10464 st.copy_length = (off_t)-1;
10465 else
10466 st.copy_length = NUM2OFFT(length);
10467
10468 if (NIL_P(src_offset))
10469 st.src_offset = (off_t)-1;
10470 else
10471 st.src_offset = NUM2OFFT(src_offset);
10472
10473 rb_fd_init(&st.fds);
10474 rb_ensure(copy_stream_body, (VALUE)&st, copy_stream_finalize, (VALUE)&st);
10475
10476 return OFFT2NUM(st.total);
10477 }
10478
10479 /*
10480 * call-seq:
10481 * io.external_encoding -> encoding
10482 *
10483 * Returns the Encoding object that represents the encoding of the file.
10484 * If io is write mode and no encoding is specified, returns <code>nil</code>.
10485 */
10486
10487 static VALUE
10488 rb_io_external_encoding(VALUE io)
10489 {
10490 rb_io_t *fptr;
10491
10492 GetOpenFile(io, fptr);
10493 if (fptr->encs.enc2) {
10494 return rb_enc_from_encoding(fptr->encs.enc2);
10495 }
10496 if (fptr->mode & FMODE_WRITABLE) {
10497 if (fptr->encs.enc)
10498 return rb_enc_from_encoding(fptr->encs.enc);
10499 return Qnil;
10500 }
10501 return rb_enc_from_encoding(io_read_encoding(fptr));
10502 }
10503
10504 /*
10505 * call-seq:
10506 * io.internal_encoding -> encoding
10507 *
10508 * Returns the Encoding of the internal string if conversion is
10509 * specified. Otherwise returns nil.
10510 */
10511
10512 static VALUE
10513 rb_io_internal_encoding(VALUE io)
10514 {
10515 rb_io_t *fptr;
10516
10517 GetOpenFile(io, fptr);
10518 if (!fptr->encs.enc2) return Qnil;
10519 return rb_enc_from_encoding(io_read_encoding(fptr));
10520 }
10521
10522 /*
10523 * call-seq:
10524 * io.set_encoding(ext_enc) -> io
10525 * io.set_encoding("ext_enc:int_enc") -> io
10526 * io.set_encoding(ext_enc, int_enc) -> io
10527 * io.set_encoding("ext_enc:int_enc", opt) -> io
10528 * io.set_encoding(ext_enc, int_enc, opt) -> io
10529 *
10530 * If single argument is specified, read string from io is tagged
10531 * with the encoding specified. If encoding is a colon separated two
10532 * encoding names "A:B", the read string is converted from encoding A
10533 * (external encoding) to encoding B (internal encoding), then tagged
10534 * with B. If two arguments are specified, those must be encoding
10535 * objects or encoding names, and the first one is the external encoding, and the
10536 * second one is the internal encoding.
10537 * If the external encoding and the internal encoding is specified,
10538 * optional hash argument specify the conversion option.
10539 */
10540
10541 static VALUE
10542 rb_io_set_encoding(int argc, VALUE *argv, VALUE io)
10543 {
10544 rb_io_t *fptr;
10545 VALUE v1, v2, opt;
10546
10547 if (!RB_TYPE_P(io, T_FILE)) {
10548 return rb_funcall2(io, id_set_encoding, argc, argv);
10549 }
10550
10551 argc = rb_scan_args(argc, argv, "11:", &v1, &v2, &opt);
10552 GetOpenFile(io, fptr);
10553 io_encoding_set(fptr, v1, v2, opt);
10554 return io;
10555 }
10556
10557 void
10558 rb_stdio_set_default_encoding(void)
10559 {
10560 extern VALUE rb_stdin, rb_stdout, rb_stderr;
10561 VALUE val = Qnil;
10562
10563 rb_io_set_encoding(1, &val, rb_stdin);
10564 rb_io_set_encoding(1, &val, rb_stdout);
10565 rb_io_set_encoding(1, &val, rb_stderr);
10566 }
10567
10568 /*
10569 * call-seq:
10570 * ARGF.external_encoding -> encoding
10571 *
10572 * Returns the external encoding for files read from +ARGF+ as an +Encoding+
10573 * object. The external encoding is the encoding of the text as stored in a
10574 * file. Contrast with +ARGF.internal_encoding+, which is the encoding used
10575 * to represent this text within Ruby.
10576 *
10577 * To set the external encoding use +ARGF.set_encoding+.
10578 *
10579 * For example:
10580 *
10581 * ARGF.external_encoding #=> #<Encoding:UTF-8>
10582 *
10583 */
10584 static VALUE
10585 argf_external_encoding(VALUE argf)
10586 {
10587 if (!RTEST(ARGF.current_file)) {
10588 return rb_enc_from_encoding(rb_default_external_encoding());
10589 }
10590 return rb_io_external_encoding(rb_io_check_io(ARGF.current_file));
10591 }
10592
10593 /*
10594 * call-seq:
10595 * ARGF.internal_encoding -> encoding
10596 *
10597 * Returns the internal encoding for strings read from +ARGF+ as an
10598 * +Encoding+ object.
10599 *
10600 * If +ARGF.set_encoding+ has been called with two encoding names, the second
10601 * is returned. Otherwise, if +Encoding.default_external+ has been set, that
10602 * value is returned. Failing that, if a default external encoding was
10603 * specified on the command-line, that value is used. If the encoding is
10604 * unknown, nil is returned.
10605 */
10606 static VALUE
10607 argf_internal_encoding(VALUE argf)
10608 {
10609 if (!RTEST(ARGF.current_file)) {
10610 return rb_enc_from_encoding(rb_default_external_encoding());
10611 }
10612 return rb_io_internal_encoding(rb_io_check_io(ARGF.current_file));
10613 }
10614
10615 /*
10616 * call-seq:
10617 * ARGF.set_encoding(ext_enc) -> ARGF
10618 * ARGF.set_encoding("ext_enc:int_enc") -> ARGF
10619 * ARGF.set_encoding(ext_enc, int_enc) -> ARGF
10620 * ARGF.set_encoding("ext_enc:int_enc", opt) -> ARGF
10621 * ARGF.set_encoding(ext_enc, int_enc, opt) -> ARGF
10622 *
10623 * If single argument is specified, strings read from ARGF are tagged with
10624 * the encoding specified.
10625 *
10626 * If two encoding names separated by a colon are given, e.g. "ascii:utf-8",
10627 * the read string is converted from the first encoding (external encoding)
10628 * to the second encoding (internal encoding), then tagged with the second
10629 * encoding.
10630 *
10631 * If two arguments are specified, they must be encoding objects or encoding
10632 * names. Again, the first specifies the external encoding; the second
10633 * specifies the internal encoding.
10634 *
10635 * If the external encoding and the internal encoding are specified, the
10636 * optional +Hash+ argument can be used to adjust the conversion process. The
10637 * structure of this hash is explained in the +String#encode+ documentation.
10638 *
10639 * For example:
10640 *
10641 * ARGF.set_encoding('ascii') # Tag the input as US-ASCII text
10642 * ARGF.set_encoding(Encoding::UTF_8) # Tag the input as UTF-8 text
10643 * ARGF.set_encoding('utf-8','ascii') # Transcode the input from US-ASCII
10644 * # to UTF-8.
10645 */
10646 static VALUE
10647 argf_set_encoding(int argc, VALUE *argv, VALUE argf)
10648 {
10649 rb_io_t *fptr;
10650
10651 if (!next_argv()) {
10652 rb_raise(rb_eArgError, "no stream to set encoding");
10653 }
10654 rb_io_set_encoding(argc, argv, ARGF.current_file);
10655 GetOpenFile(ARGF.current_file, fptr);
10656 ARGF.encs = fptr->encs;
10657 return argf;
10658 }
10659
10660 /*
10661 * call-seq:
10662 * ARGF.tell -> Integer
10663 * ARGF.pos -> Integer
10664 *
10665 * Returns the current offset (in bytes) of the current file in +ARGF+.
10666 *
10667 * ARGF.pos #=> 0
10668 * ARGF.gets #=> "This is line one\n"
10669 * ARGF.pos #=> 17
10670 *
10671 */
10672 static VALUE
10673 argf_tell(VALUE argf)
10674 {
10675 if (!next_argv()) {
10676 rb_raise(rb_eArgError, "no stream to tell");
10677 }
10678 ARGF_FORWARD(0, 0);
10679 return rb_io_tell(ARGF.current_file);
10680 }
10681
10682 /*
10683 * call-seq:
10684 * ARGF.seek(amount, whence=IO::SEEK_SET) -> 0
10685 *
10686 * Seeks to offset _amount_ (an +Integer+) in the +ARGF+ stream according to
10687 * the value of _whence_. See +IO#seek+ for further details.
10688 */
10689 static VALUE
10690 argf_seek_m(int argc, VALUE *argv, VALUE argf)
10691 {
10692 if (!next_argv()) {
10693 rb_raise(rb_eArgError, "no stream to seek");
10694 }
10695 ARGF_FORWARD(argc, argv);
10696 return rb_io_seek_m(argc, argv, ARGF.current_file);
10697 }
10698
10699 /*
10700 * call-seq:
10701 * ARGF.pos = position -> Integer
10702 *
10703 * Seeks to the position given by _position_ (in bytes) in +ARGF+.
10704 *
10705 * For example:
10706 *
10707 * ARGF.pos = 17
10708 * ARGF.gets #=> "This is line two\n"
10709 */
10710 static VALUE
10711 argf_set_pos(VALUE argf, VALUE offset)
10712 {
10713 if (!next_argv()) {
10714 rb_raise(rb_eArgError, "no stream to set position");
10715 }
10716 ARGF_FORWARD(1, &offset);
10717 return rb_io_set_pos(ARGF.current_file, offset);
10718 }
10719
10720 /*
10721 * call-seq:
10722 * ARGF.rewind -> 0
10723 *
10724 * Positions the current file to the beginning of input, resetting
10725 * +ARGF.lineno+ to zero.
10726 *
10727 * ARGF.readline #=> "This is line one\n"
10728 * ARGF.rewind #=> 0
10729 * ARGF.lineno #=> 0
10730 * ARGF.readline #=> "This is line one\n"
10731 */
10732 static VALUE
10733 argf_rewind(VALUE argf)
10734 {
10735 if (!next_argv()) {
10736 rb_raise(rb_eArgError, "no stream to rewind");
10737 }
10738 ARGF_FORWARD(0, 0);
10739 return rb_io_rewind(ARGF.current_file);
10740 }
10741
10742 /*
10743 * call-seq:
10744 * ARGF.fileno -> fixnum
10745 * ARGF.to_i -> fixnum
10746 *
10747 * Returns an integer representing the numeric file descriptor for
10748 * the current file. Raises an +ArgumentError+ if there isn't a current file.
10749 *
10750 * ARGF.fileno #=> 3
10751 */
10752 static VALUE
10753 argf_fileno(VALUE argf)
10754 {
10755 if (!next_argv()) {
10756 rb_raise(rb_eArgError, "no stream");
10757 }
10758 ARGF_FORWARD(0, 0);
10759 return rb_io_fileno(ARGF.current_file);
10760 }
10761
10762 /*
10763 * call-seq:
10764 * ARGF.to_io -> IO
10765 *
10766 * Returns an +IO+ object representing the current file. This will be a
10767 * +File+ object unless the current file is a stream such as STDIN.
10768 *
10769 * For example:
10770 *
10771 * ARGF.to_io #=> #<File:glark.txt>
10772 * ARGF.to_io #=> #<IO:<STDIN>>
10773 */
10774 static VALUE
10775 argf_to_io(VALUE argf)
10776 {
10777 next_argv();
10778 ARGF_FORWARD(0, 0);
10779 return ARGF.current_file;
10780 }
10781
10782 /*
10783 * call-seq:
10784 * ARGF.eof? -> true or false
10785 * ARGF.eof -> true or false
10786 *
10787 * Returns true if the current file in +ARGF+ is at end of file, i.e. it has
10788 * no data to read. The stream must be opened for reading or an +IOError+
10789 * will be raised.
10790 *
10791 * $ echo "eof" | ruby argf.rb
10792 *
10793 * ARGF.eof? #=> false
10794 * 3.times { ARGF.readchar }
10795 * ARGF.eof? #=> false
10796 * ARGF.readchar #=> "\n"
10797 * ARGF.eof? #=> true
10798 */
10799
10800 static VALUE
10801 argf_eof(VALUE argf)
10802 {
10803 next_argv();
10804 if (RTEST(ARGF.current_file)) {
10805 if (ARGF.init_p == 0) return Qtrue;
10806 next_argv();
10807 ARGF_FORWARD(0, 0);
10808 if (rb_io_eof(ARGF.current_file)) {
10809 return Qtrue;
10810 }
10811 }
10812 return Qfalse;
10813 }
10814
10815 /*
10816 * call-seq:
10817 * ARGF.read([length [, outbuf]]) -> string, outbuf, or nil
10818 *
10819 * Reads _length_ bytes from ARGF. The files named on the command line
10820 * are concatenated and treated as a single file by this method, so when
10821 * called without arguments the contents of this pseudo file are returned in
10822 * their entirety.
10823 *
10824 * _length_ must be a non-negative integer or nil. If it is a positive
10825 * integer, +read+ tries to read at most _length_ bytes. It returns nil
10826 * if an EOF was encountered before anything could be read. Fewer than
10827 * _length_ bytes may be returned if an EOF is encountered during the read.
10828 *
10829 * If _length_ is omitted or is _nil_, it reads until EOF. A String is
10830 * returned even if EOF is encountered before any data is read.
10831 *
10832 * If _length_ is zero, it returns _""_.
10833 *
10834 * If the optional _outbuf_ argument is present, it must reference a String,
10835 * which will receive the data.
10836 * The <i>outbuf</i> will contain only the received data after the method call
10837 * even if it is not empty at the beginning.
10838 *
10839 * For example:
10840 *
10841 * $ echo "small" > small.txt
10842 * $ echo "large" > large.txt
10843 * $ ./glark.rb small.txt large.txt
10844 *
10845 * ARGF.read #=> "small\nlarge"
10846 * ARGF.read(200) #=> "small\nlarge"
10847 * ARGF.read(2) #=> "sm"
10848 * ARGF.read(0) #=> ""
10849 *
10850 * Note that this method behaves like fread() function in C. If you need the
10851 * behavior like read(2) system call, consider +ARGF.readpartial+.
10852 */
10853
10854 static VALUE
10855 argf_read(int argc, VALUE *argv, VALUE argf)
10856 {
10857 VALUE tmp, str, length;
10858 long len = 0;
10859
10860 rb_scan_args(argc, argv, "02", &length, &str);
10861 if (!NIL_P(length)) {
10862 len = NUM2LONG(argv[0]);
10863 }
10864 if (!NIL_P(str)) {
10865 StringValue(str);
10866 rb_str_resize(str,0);
10867 argv[1] = Qnil;
10868 }
10869
10870 retry:
10871 if (!next_argv()) {
10872 return str;
10873 }
10874 if (ARGF_GENERIC_INPUT_P()) {
10875 tmp = argf_forward(argc, argv, argf);
10876 }
10877 else {
10878 tmp = io_read(argc, argv, ARGF.current_file);
10879 }
10880 if (NIL_P(str)) str = tmp;
10881 else if (!NIL_P(tmp)) rb_str_append(str, tmp);
10882 if (NIL_P(tmp) || NIL_P(length)) {
10883 if (ARGF.next_p != -1) {
10884 argf_close(argf);
10885 ARGF.next_p = 1;
10886 goto retry;
10887 }
10888 }
10889 else if (argc >= 1) {
10890 if (RSTRING_LEN(str) < len) {
10891 len -= RSTRING_LEN(str);
10892 argv[0] = INT2NUM(len);
10893 goto retry;
10894 }
10895 }
10896 return str;
10897 }
10898
10899 struct argf_call_arg {
10900 int argc;
10901 VALUE *argv;
10902 VALUE argf;
10903 };
10904
10905 static VALUE
10906 argf_forward_call(VALUE arg)
10907 {
10908 struct argf_call_arg *p = (struct argf_call_arg *)arg;
10909 argf_forward(p->argc, p->argv, p->argf);
10910 return Qnil;
10911 }
10912
10913 static VALUE argf_getpartial(int argc, VALUE *argv, VALUE argf, int nonblock);
10914
10915 /*
10916 * call-seq:
10917 * ARGF.readpartial(maxlen) -> string
10918 * ARGF.readpartial(maxlen, outbuf) -> outbuf
10919 *
10920 * Reads at most _maxlen_ bytes from the ARGF stream.
10921 *
10922 * If the optional _outbuf_ argument is present,
10923 * it must reference a String, which will receive the data.
10924 * The <i>outbuf</i> will contain only the received data after the method call
10925 * even if it is not empty at the beginning.
10926 *
10927 * It raises <code>EOFError</code> on end of ARGF stream.
10928 * Since ARGF stream is a concatenation of multiple files,
10929 * internally EOF is occur for each file.
10930 * ARGF.readpartial returns empty strings for EOFs except the last one and
10931 * raises <code>EOFError</code> for the last one.
10932 *
10933 */
10934
10935 static VALUE
10936 argf_readpartial(int argc, VALUE *argv, VALUE argf)
10937 {
10938 return argf_getpartial(argc, argv, argf, 0);
10939 }
10940
10941 /*
10942 * call-seq:
10943 * ARGF.read_nonblock(maxlen) -> string
10944 * ARGF.read_nonblock(maxlen, outbuf) -> outbuf
10945 *
10946 * Reads at most _maxlen_ bytes from the ARGF stream in non-blocking mode.
10947 */
10948
10949 static VALUE
10950 argf_read_nonblock(int argc, VALUE *argv, VALUE argf)
10951 {
10952 return argf_getpartial(argc, argv, argf, 1);
10953 }
10954
10955 static VALUE
10956 argf_getpartial(int argc, VALUE *argv, VALUE argf, int nonblock)
10957 {
10958 VALUE tmp, str, length;
10959
10960 rb_scan_args(argc, argv, "11", &length, &str);
10961 if (!NIL_P(str)) {
10962 StringValue(str);
10963 argv[1] = str;
10964 }
10965
10966 if (!next_argv()) {
10967 rb_str_resize(str, 0);
10968 rb_eof_error();
10969 }
10970 if (ARGF_GENERIC_INPUT_P()) {
10971 struct argf_call_arg arg;
10972 arg.argc = argc;
10973 arg.argv = argv;
10974 arg.argf = argf;
10975 tmp = rb_rescue2(argf_forward_call, (VALUE)&arg,
10976 RUBY_METHOD_FUNC(0), Qnil, rb_eEOFError, (VALUE)0);
10977 }
10978 else {
10979 tmp = io_getpartial(argc, argv, ARGF.current_file, nonblock, 0);
10980 }
10981 if (NIL_P(tmp)) {
10982 if (ARGF.next_p == -1) {
10983 rb_eof_error();
10984 }
10985 argf_close(argf);
10986 ARGF.next_p = 1;
10987 if (RARRAY_LEN(ARGF.argv) == 0)
10988 rb_eof_error();
10989 if (NIL_P(str))
10990 str = rb_str_new(NULL, 0);
10991 return str;
10992 }
10993 return tmp;
10994 }
10995
10996 /*
10997 * call-seq:
10998 * ARGF.getc -> String or nil
10999 *
11000 * Reads the next character from +ARGF+ and returns it as a +String+. Returns
11001 * +nil+ at the end of the stream.
11002 *
11003 * +ARGF+ treats the files named on the command line as a single file created
11004 * by concatenating their contents. After returning the last character of the
11005 * first file, it returns the first character of the second file, and so on.
11006 *
11007 * For example:
11008 *
11009 * $ echo "foo" > file
11010 * $ ruby argf.rb file
11011 *
11012 * ARGF.getc #=> "f"
11013 * ARGF.getc #=> "o"
11014 * ARGF.getc #=> "o"
11015 * ARGF.getc #=> "\n"
11016 * ARGF.getc #=> nil
11017 * ARGF.getc #=> nil
11018 */
11019 static VALUE
11020 argf_getc(VALUE argf)
11021 {
11022 VALUE ch;
11023
11024 retry:
11025 if (!next_argv()) return Qnil;
11026 if (ARGF_GENERIC_INPUT_P()) {
11027 ch = rb_funcall3(ARGF.current_file, rb_intern("getc"), 0, 0);
11028 }
11029 else {
11030 ch = rb_io_getc(ARGF.current_file);
11031 }
11032 if (NIL_P(ch) && ARGF.next_p != -1) {
11033 argf_close(argf);
11034 ARGF.next_p = 1;
11035 goto retry;
11036 }
11037
11038 return ch;
11039 }
11040
11041 /*
11042 * call-seq:
11043 * ARGF.getbyte -> Fixnum or nil
11044 *
11045 * Gets the next 8-bit byte (0..255) from +ARGF+. Returns +nil+ if called at
11046 * the end of the stream.
11047 *
11048 * For example:
11049 *
11050 * $ echo "foo" > file
11051 * $ ruby argf.rb file
11052 *
11053 * ARGF.getbyte #=> 102
11054 * ARGF.getbyte #=> 111
11055 * ARGF.getbyte #=> 111
11056 * ARGF.getbyte #=> 10
11057 * ARGF.getbyte #=> nil
11058 */
11059 static VALUE
11060 argf_getbyte(VALUE argf)
11061 {
11062 VALUE ch;
11063
11064 retry:
11065 if (!next_argv()) return Qnil;
11066 if (!RB_TYPE_P(ARGF.current_file, T_FILE)) {
11067 ch = rb_funcall3(ARGF.current_file, rb_intern("getbyte"), 0, 0);
11068 }
11069 else {
11070 ch = rb_io_getbyte(ARGF.current_file);
11071 }
11072 if (NIL_P(ch) && ARGF.next_p != -1) {
11073 argf_close(argf);
11074 ARGF.next_p = 1;
11075 goto retry;
11076 }
11077
11078 return ch;
11079 }
11080
11081 /*
11082 * call-seq:
11083 * ARGF.readchar -> String or nil
11084 *
11085 * Reads the next character from +ARGF+ and returns it as a +String+. Raises
11086 * an +EOFError+ after the last character of the last file has been read.
11087 *
11088 * For example:
11089 *
11090 * $ echo "foo" > file
11091 * $ ruby argf.rb file
11092 *
11093 * ARGF.readchar #=> "f"
11094 * ARGF.readchar #=> "o"
11095 * ARGF.readchar #=> "o"
11096 * ARGF.readchar #=> "\n"
11097 * ARGF.readchar #=> end of file reached (EOFError)
11098 */
11099 static VALUE
11100 argf_readchar(VALUE argf)
11101 {
11102 VALUE ch;
11103
11104 retry:
11105 if (!next_argv()) rb_eof_error();
11106 if (!RB_TYPE_P(ARGF.current_file, T_FILE)) {
11107 ch = rb_funcall3(ARGF.current_file, rb_intern("getc"), 0, 0);
11108 }
11109 else {
11110 ch = rb_io_getc(ARGF.current_file);
11111 }
11112 if (NIL_P(ch) && ARGF.next_p != -1) {
11113 argf_close(argf);
11114 ARGF.next_p = 1;
11115 goto retry;
11116 }
11117
11118 return ch;
11119 }
11120
11121 /*
11122 * call-seq:
11123 * ARGF.readbyte -> Fixnum
11124 *
11125 * Reads the next 8-bit byte from ARGF and returns it as a +Fixnum+. Raises
11126 * an +EOFError+ after the last byte of the last file has been read.
11127 *
11128 * For example:
11129 *
11130 * $ echo "foo" > file
11131 * $ ruby argf.rb file
11132 *
11133 * ARGF.readbyte #=> 102
11134 * ARGF.readbyte #=> 111
11135 * ARGF.readbyte #=> 111
11136 * ARGF.readbyte #=> 10
11137 * ARGF.readbyte #=> end of file reached (EOFError)
11138 */
11139 static VALUE
11140 argf_readbyte(VALUE argf)
11141 {
11142 VALUE c;
11143
11144 NEXT_ARGF_FORWARD(0, 0);
11145 c = argf_getbyte(argf);
11146 if (NIL_P(c)) {
11147 rb_eof_error();
11148 }
11149 return c;
11150 }
11151
11152 #define FOREACH_ARGF() while (next_argv())
11153
11154 static VALUE
11155 argf_block_call_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, argf))
11156 {
11157 const VALUE current = ARGF.current_file;
11158 rb_yield_values2(argc, argv);
11159 if (ARGF.init_p == -1 || current != ARGF.current_file) {
11160 rb_iter_break_value(Qundef);
11161 }
11162 return Qnil;
11163 }
11164
11165 static void
11166 argf_block_call(ID mid, int argc, VALUE *argv, VALUE argf)
11167 {
11168 VALUE ret = rb_block_call(ARGF.current_file, mid, argc, argv, argf_block_call_i, argf);
11169 if (ret != Qundef) ARGF.next_p = 1;
11170 }
11171
11172 /*
11173 * call-seq:
11174 * ARGF.each(sep=$/) {|line| block } -> ARGF
11175 * ARGF.each(sep=$/,limit) {|line| block } -> ARGF
11176 * ARGF.each(...) -> an_enumerator
11177 *
11178 * ARGF.each_line(sep=$/) {|line| block } -> ARGF
11179 * ARGF.each_line(sep=$/,limit) {|line| block } -> ARGF
11180 * ARGF.each_line(...) -> an_enumerator
11181 *
11182 * Returns an enumerator which iterates over each line (separated by _sep_,
11183 * which defaults to your platform's newline character) of each file in
11184 * +ARGV+. If a block is supplied, each line in turn will be yielded to the
11185 * block, otherwise an enumerator is returned.
11186 * The optional _limit_ argument is a +Fixnum+ specifying the maximum
11187 * length of each line; longer lines will be split according to this limit.
11188 *
11189 * This method allows you to treat the files supplied on the command line as
11190 * a single file consisting of the concatenation of each named file. After
11191 * the last line of the first file has been returned, the first line of the
11192 * second file is returned. The +ARGF.filename+ and +ARGF.lineno+ methods can
11193 * be used to determine the filename and line number, respectively, of the
11194 * current line.
11195 *
11196 * For example, the following code prints out each line of each named file
11197 * prefixed with its line number, displaying the filename once per file:
11198 *
11199 * ARGF.lines do |line|
11200 * puts ARGF.filename if ARGF.lineno == 1
11201 * puts "#{ARGF.lineno}: #{line}"
11202 * end
11203 */
11204 static VALUE
11205 argf_each_line(int argc, VALUE *argv, VALUE argf)
11206 {
11207 RETURN_ENUMERATOR(argf, argc, argv);
11208 FOREACH_ARGF() {
11209 argf_block_call(rb_intern("each_line"), argc, argv, argf);
11210 }
11211 return argf;
11212 }
11213
11214 /*
11215 * This is a deprecated alias for <code>each_line</code>.
11216 */
11217
11218 static VALUE
11219 argf_lines(int argc, VALUE *argv, VALUE argf)
11220 {
11221 rb_warn("ARGF#lines is deprecated; use #each_line instead");
11222 if (!rb_block_given_p())
11223 return rb_enumeratorize(argf, ID2SYM(rb_intern("each_line")), argc, argv);
11224 return argf_each_line(argc, argv, argf);
11225 }
11226
11227 /*
11228 * call-seq:
11229 * ARGF.bytes {|byte| block } -> ARGF
11230 * ARGF.bytes -> an_enumerator
11231 *
11232 * ARGF.each_byte {|byte| block } -> ARGF
11233 * ARGF.each_byte -> an_enumerator
11234 *
11235 * Iterates over each byte of each file in +ARGV+.
11236 * A byte is returned as a +Fixnum+ in the range 0..255.
11237 *
11238 * This method allows you to treat the files supplied on the command line as
11239 * a single file consisting of the concatenation of each named file. After
11240 * the last byte of the first file has been returned, the first byte of the
11241 * second file is returned. The +ARGF.filename+ method can be used to
11242 * determine the filename of the current byte.
11243 *
11244 * If no block is given, an enumerator is returned instead.
11245 *
11246 * For example:
11247 *
11248 * ARGF.bytes.to_a #=> [35, 32, ... 95, 10]
11249 *
11250 */
11251 static VALUE
11252 argf_each_byte(VALUE argf)
11253 {
11254 RETURN_ENUMERATOR(argf, 0, 0);
11255 FOREACH_ARGF() {
11256 argf_block_call(rb_intern("each_byte"), 0, 0, argf);
11257 }
11258 return argf;
11259 }
11260
11261 /*
11262 * This is a deprecated alias for <code>each_byte</code>.
11263 */
11264
11265 static VALUE
11266 argf_bytes(VALUE argf)
11267 {
11268 rb_warn("ARGF#bytes is deprecated; use #each_byte instead");
11269 if (!rb_block_given_p())
11270 return rb_enumeratorize(argf, ID2SYM(rb_intern("each_byte")), 0, 0);
11271 return argf_each_byte(argf);
11272 }
11273
11274 /*
11275 * call-seq:
11276 * ARGF.each_char {|char| block } -> ARGF
11277 * ARGF.each_char -> an_enumerator
11278 *
11279 * Iterates over each character of each file in +ARGF+.
11280 *
11281 * This method allows you to treat the files supplied on the command line as
11282 * a single file consisting of the concatenation of each named file. After
11283 * the last character of the first file has been returned, the first
11284 * character of the second file is returned. The +ARGF.filename+ method can
11285 * be used to determine the name of the file in which the current character
11286 * appears.
11287 *
11288 * If no block is given, an enumerator is returned instead.
11289 */
11290 static VALUE
11291 argf_each_char(VALUE argf)
11292 {
11293 RETURN_ENUMERATOR(argf, 0, 0);
11294 FOREACH_ARGF() {
11295 argf_block_call(rb_intern("each_char"), 0, 0, argf);
11296 }
11297 return argf;
11298 }
11299
11300 /*
11301 * This is a deprecated alias for <code>each_char</code>.
11302 */
11303
11304 static VALUE
11305 argf_chars(VALUE argf)
11306 {
11307 rb_warn("ARGF#chars is deprecated; use #each_char instead");
11308 if (!rb_block_given_p())
11309 return rb_enumeratorize(argf, ID2SYM(rb_intern("each_char")), 0, 0);
11310 return argf_each_char(argf);
11311 }
11312
11313 /*
11314 * call-seq:
11315 * ARGF.each_codepoint {|codepoint| block } -> ARGF
11316 * ARGF.each_codepoint -> an_enumerator
11317 *
11318 * Iterates over each codepoint of each file in +ARGF+.
11319 *
11320 * This method allows you to treat the files supplied on the command line as
11321 * a single file consisting of the concatenation of each named file. After
11322 * the last codepoint of the first file has been returned, the first
11323 * codepoint of the second file is returned. The +ARGF.filename+ method can
11324 * be used to determine the name of the file in which the current codepoint
11325 * appears.
11326 *
11327 * If no block is given, an enumerator is returned instead.
11328 */
11329 static VALUE
11330 argf_each_codepoint(VALUE argf)
11331 {
11332 RETURN_ENUMERATOR(argf, 0, 0);
11333 FOREACH_ARGF() {
11334 argf_block_call(rb_intern("each_codepoint"), 0, 0, argf);
11335 }
11336 return argf;
11337 }
11338
11339 /*
11340 * This is a deprecated alias for <code>each_codepoint</code>.
11341 */
11342
11343 static VALUE
11344 argf_codepoints(VALUE argf)
11345 {
11346 rb_warn("ARGF#codepoints is deprecated; use #each_codepoint instead");
11347 if (!rb_block_given_p())
11348 return rb_enumeratorize(argf, ID2SYM(rb_intern("each_codepoint")), 0, 0);
11349 return argf_each_codepoint(argf);
11350 }
11351
11352 /*
11353 * call-seq:
11354 * ARGF.filename -> String
11355 * ARGF.path -> String
11356 *
11357 * Returns the current filename. "-" is returned when the current file is
11358 * STDIN.
11359 *
11360 * For example:
11361 *
11362 * $ echo "foo" > foo
11363 * $ echo "bar" > bar
11364 * $ echo "glark" > glark
11365 *
11366 * $ ruby argf.rb foo bar glark
11367 *
11368 * ARGF.filename #=> "foo"
11369 * ARGF.read(5) #=> "foo\nb"
11370 * ARGF.filename #=> "bar"
11371 * ARGF.skip
11372 * ARGF.filename #=> "glark"
11373 */
11374 static VALUE
11375 argf_filename(VALUE argf)
11376 {
11377 next_argv();
11378 return ARGF.filename;
11379 }
11380
11381 static VALUE
11382 argf_filename_getter(ID id, VALUE *var)
11383 {
11384 return argf_filename(*var);
11385 }
11386
11387 /*
11388 * call-seq:
11389 * ARGF.file -> IO or File object
11390 *
11391 * Returns the current file as an +IO+ or +File+ object. #<IO:<STDIN>> is
11392 * returned when the current file is STDIN.
11393 *
11394 * For example:
11395 *
11396 * $ echo "foo" > foo
11397 * $ echo "bar" > bar
11398 *
11399 * $ ruby argf.rb foo bar
11400 *
11401 * ARGF.file #=> #<File:foo>
11402 * ARGF.read(5) #=> "foo\nb"
11403 * ARGF.file #=> #<File:bar>
11404 */
11405 static VALUE
11406 argf_file(VALUE argf)
11407 {
11408 next_argv();
11409 return ARGF.current_file;
11410 }
11411
11412 /*
11413 * call-seq:
11414 * ARGF.binmode -> ARGF
11415 *
11416 * Puts +ARGF+ into binary mode. Once a stream is in binary mode, it cannot
11417 * be reset to non-binary mode. This option has the following effects:
11418 *
11419 * * Newline conversion is disabled.
11420 * * Encoding conversion is disabled.
11421 * * Content is treated as ASCII-8BIT.
11422 */
11423 static VALUE
11424 argf_binmode_m(VALUE argf)
11425 {
11426 ARGF.binmode = 1;
11427 next_argv();
11428 ARGF_FORWARD(0, 0);
11429 rb_io_ascii8bit_binmode(ARGF.current_file);
11430 return argf;
11431 }
11432
11433 /*
11434 * call-seq:
11435 * ARGF.binmode? -> true or false
11436 *
11437 * Returns true if +ARGF+ is being read in binary mode; false otherwise. (To
11438 * enable binary mode use +ARGF.binmode+.
11439 *
11440 * For example:
11441 *
11442 * ARGF.binmode? #=> false
11443 * ARGF.binmode
11444 * ARGF.binmode? #=> true
11445 */
11446 static VALUE
11447 argf_binmode_p(VALUE argf)
11448 {
11449 return ARGF.binmode ? Qtrue : Qfalse;
11450 }
11451
11452 /*
11453 * call-seq:
11454 * ARGF.skip -> ARGF
11455 *
11456 * Sets the current file to the next file in ARGV. If there aren't any more
11457 * files it has no effect.
11458 *
11459 * For example:
11460 *
11461 * $ ruby argf.rb foo bar
11462 * ARGF.filename #=> "foo"
11463 * ARGF.skip
11464 * ARGF.filename #=> "bar"
11465 */
11466 static VALUE
11467 argf_skip(VALUE argf)
11468 {
11469 if (ARGF.init_p && ARGF.next_p == 0) {
11470 argf_close(argf);
11471 ARGF.next_p = 1;
11472 }
11473 return argf;
11474 }
11475
11476 /*
11477 * call-seq:
11478 * ARGF.close -> ARGF
11479 *
11480 * Closes the current file and skips to the next in the stream. Trying to
11481 * close a file that has already been closed causes an +IOError+ to be
11482 * raised.
11483 *
11484 * For example:
11485 *
11486 * $ ruby argf.rb foo bar
11487 *
11488 * ARGF.filename #=> "foo"
11489 * ARGF.close
11490 * ARGF.filename #=> "bar"
11491 * ARGF.close
11492 * ARGF.close #=> closed stream (IOError)
11493 */
11494 static VALUE
11495 argf_close_m(VALUE argf)
11496 {
11497 next_argv();
11498 argf_close(argf);
11499 if (ARGF.next_p != -1) {
11500 ARGF.next_p = 1;
11501 }
11502 ARGF.lineno = 0;
11503 return argf;
11504 }
11505
11506 /*
11507 * call-seq:
11508 * ARGF.closed? -> true or false
11509 *
11510 * Returns _true_ if the current file has been closed; _false_ otherwise. Use
11511 * +ARGF.close+ to actually close the current file.
11512 */
11513 static VALUE
11514 argf_closed(VALUE argf)
11515 {
11516 next_argv();
11517 ARGF_FORWARD(0, 0);
11518 return rb_io_closed(ARGF.current_file);
11519 }
11520
11521 /*
11522 * call-seq:
11523 * ARGF.to_s -> String
11524 *
11525 * Returns "ARGF".
11526 */
11527 static VALUE
11528 argf_to_s(VALUE argf)
11529 {
11530 return rb_str_new2("ARGF");
11531 }
11532
11533 /*
11534 * call-seq:
11535 * ARGF.inplace_mode -> String
11536 *
11537 * Returns the file extension appended to the names of modified files under
11538 * inplace-edit mode. This value can be set using +ARGF.inplace_mode=+ or
11539 * passing the +-i+ switch to the Ruby binary.
11540 */
11541 static VALUE
11542 argf_inplace_mode_get(VALUE argf)
11543 {
11544 if (!ARGF.inplace) return Qnil;
11545 return rb_str_new2(ARGF.inplace);
11546 }
11547
11548 static VALUE
11549 opt_i_get(ID id, VALUE *var)
11550 {
11551 return argf_inplace_mode_get(*var);
11552 }
11553
11554 /*
11555 * call-seq:
11556 * ARGF.inplace_mode = ext -> ARGF
11557 *
11558 * Sets the filename extension for inplace editing mode to the given String.
11559 * Each file being edited has this value appended to its filename. The
11560 * modified file is saved under this new name.
11561 *
11562 * For example:
11563 *
11564 * $ ruby argf.rb file.txt
11565 *
11566 * ARGF.inplace_mode = '.bak'
11567 * ARGF.lines do |line|
11568 * print line.sub("foo","bar")
11569 * end
11570 *
11571 * Each line of _file.txt_ has the first occurrence of "foo" replaced with
11572 * "bar", then the new line is written out to _file.txt.bak_.
11573 */
11574 static VALUE
11575 argf_inplace_mode_set(VALUE argf, VALUE val)
11576 {
11577 if (rb_safe_level() >= 1 && OBJ_TAINTED(val))
11578 rb_insecure_operation();
11579
11580 if (!RTEST(val)) {
11581 if (ARGF.inplace) free(ARGF.inplace);
11582 ARGF.inplace = 0;
11583 }
11584 else {
11585 StringValue(val);
11586 if (ARGF.inplace) free(ARGF.inplace);
11587 ARGF.inplace = 0;
11588 ARGF.inplace = strdup(RSTRING_PTR(val));
11589 }
11590 return argf;
11591 }
11592
11593 static void
11594 opt_i_set(VALUE val, ID id, VALUE *var)
11595 {
11596 argf_inplace_mode_set(*var, val);
11597 }
11598
11599 const char *
11600 ruby_get_inplace_mode(void)
11601 {
11602 return ARGF.inplace;
11603 }
11604
11605 void
11606 ruby_set_inplace_mode(const char *suffix)
11607 {
11608 if (ARGF.inplace) free(ARGF.inplace);
11609 ARGF.inplace = 0;
11610 if (suffix) ARGF.inplace = strdup(suffix);
11611 }
11612
11613 /*
11614 * call-seq:
11615 * ARGF.argv -> ARGV
11616 *
11617 * Returns the +ARGV+ array, which contains the arguments passed to your
11618 * script, one per element.
11619 *
11620 * For example:
11621 *
11622 * $ ruby argf.rb -v glark.txt
11623 *
11624 * ARGF.argv #=> ["-v", "glark.txt"]
11625 *
11626 */
11627 static VALUE
11628 argf_argv(VALUE argf)
11629 {
11630 return ARGF.argv;
11631 }
11632
11633 static VALUE
11634 argf_argv_getter(ID id, VALUE *var)
11635 {
11636 return argf_argv(*var);
11637 }
11638
11639 VALUE
11640 rb_get_argv(void)
11641 {
11642 return ARGF.argv;
11643 }
11644
11645 /*
11646 * call-seq:
11647 * ARGF.to_write_io -> io
11648 *
11649 * Returns IO instance tied to _ARGF_ for writing if inplace mode is
11650 * enabled.
11651 */
11652 static VALUE
11653 argf_write_io(VALUE argf)
11654 {
11655 if (!RTEST(ARGF.current_file)) {
11656 rb_raise(rb_eIOError, "not opened for writing");
11657 }
11658 return GetWriteIO(ARGF.current_file);
11659 }
11660
11661 /*
11662 * call-seq:
11663 * ARGF.write(string) -> integer
11664 *
11665 * Writes _string_ if inplace mode.
11666 */
11667 static VALUE
11668 argf_write(VALUE argf, VALUE str)
11669 {
11670 return rb_io_write(argf_write_io(argf), str);
11671 }
11672
11673 void
11674 rb_readwrite_sys_fail(int writable, const char *mesg)
11675 {
11676 VALUE arg;
11677 int n = errno;
11678 arg = mesg ? rb_str_new2(mesg) : Qnil;
11679 if (writable == RB_IO_WAIT_WRITABLE) {
11680 switch (n) {
11681 case EAGAIN:
11682 rb_exc_raise(rb_class_new_instance(1, &arg, rb_eEAGAINWaitWritable));
11683 break;
11684 #if EAGAIN != EWOULDBLOCK
11685 case EWOULDBLOCK:
11686 rb_exc_raise(rb_class_new_instance(1, &arg, rb_eEWOULDBLOCKWaitWritable));
11687 break;
11688 #endif
11689 case EINPROGRESS:
11690 rb_exc_raise(rb_class_new_instance(1, &arg, rb_eEINPROGRESSWaitWritable));
11691 break;
11692 default:
11693 rb_mod_sys_fail_str(rb_mWaitWritable, arg);
11694 }
11695 }
11696 else if (writable == RB_IO_WAIT_READABLE) {
11697 switch (n) {
11698 case EAGAIN:
11699 rb_exc_raise(rb_class_new_instance(1, &arg, rb_eEAGAINWaitReadable));
11700 break;
11701 #if EAGAIN != EWOULDBLOCK
11702 case EWOULDBLOCK:
11703 rb_exc_raise(rb_class_new_instance(1, &arg, rb_eEWOULDBLOCKWaitReadable));
11704 break;
11705 #endif
11706 case EINPROGRESS:
11707 rb_exc_raise(rb_class_new_instance(1, &arg, rb_eEINPROGRESSWaitReadable));
11708 break;
11709 default:
11710 rb_mod_sys_fail_str(rb_mWaitReadable, arg);
11711 }
11712 }
11713 else {
11714 rb_bug("invalid read/write type passed to rb_readwrite_sys_fail: %d", writable);
11715 }
11716 }
11717
11718 /*
11719 * Document-class: IOError
11720 *
11721 * Raised when an IO operation fails.
11722 *
11723 * File.open("/etc/hosts") {|f| f << "example"}
11724 * #=> IOError: not opened for writing
11725 *
11726 * File.open("/etc/hosts") {|f| f.close; f.read }
11727 * #=> IOError: closed stream
11728 *
11729 * Note that some IO failures raise +SystemCallError+s and these are not
11730 * subclasses of IOError:
11731 *
11732 * File.open("does/not/exist")
11733 * #=> Errno::ENOENT: No such file or directory - does/not/exist
11734 */
11735
11736 /*
11737 * Document-class: EOFError
11738 *
11739 * Raised by some IO operations when reaching the end of file. Many IO
11740 * methods exist in two forms,
11741 *
11742 * one that returns +nil+ when the end of file is reached, the other
11743 * raises EOFError +EOFError+.
11744 *
11745 * +EOFError+ is a subclass of +IOError+.
11746 *
11747 * file = File.open("/etc/hosts")
11748 * file.read
11749 * file.gets #=> nil
11750 * file.readline #=> EOFError: end of file reached
11751 */
11752
11753 /*
11754 * Document-class: ARGF
11755 *
11756 * +ARGF+ is a stream designed for use in scripts that process files given as
11757 * command-line arguments or passed in via STDIN.
11758 *
11759 * The arguments passed to your script are stored in the +ARGV+ Array, one
11760 * argument per element. +ARGF+ assumes that any arguments that aren't
11761 * filenames have been removed from +ARGV+. For example:
11762 *
11763 * $ ruby argf.rb --verbose file1 file2
11764 *
11765 * ARGV #=> ["--verbose", "file1", "file2"]
11766 * option = ARGV.shift #=> "--verbose"
11767 * ARGV #=> ["file1", "file2"]
11768 *
11769 * You can now use +ARGF+ to work with a concatenation of each of these named
11770 * files. For instance, +ARGF.read+ will return the contents of _file1_
11771 * followed by the contents of _file2_.
11772 *
11773 * After a file in +ARGV+ has been read +ARGF+ removes it from the Array.
11774 * Thus, after all files have been read +ARGV+ will be empty.
11775 *
11776 * You can manipulate +ARGV+ yourself to control what +ARGF+ operates on. If
11777 * you remove a file from +ARGV+, it is ignored by +ARGF+; if you add files to
11778 * +ARGV+, they are treated as if they were named on the command line. For
11779 * example:
11780 *
11781 * ARGV.replace ["file1"]
11782 * ARGF.readlines # Returns the contents of file1 as an Array
11783 * ARGV #=> []
11784 * ARGV.replace ["file2", "file3"]
11785 * ARGF.read # Returns the contents of file2 and file3
11786 *
11787 * If +ARGV+ is empty, +ARGF+ acts as if it contained STDIN, i.e. the data
11788 * piped to your script. For example:
11789 *
11790 * $ echo "glark" | ruby -e 'p ARGF.read'
11791 * "glark\n"
11792 */
11793
11794 /*
11795 * The IO class is the basis for all input and output in Ruby.
11796 * An I/O stream may be <em>duplexed</em> (that is, bidirectional), and
11797 * so may use more than one native operating system stream.
11798 *
11799 * Many of the examples in this section use the File class, the only standard
11800 * subclass of IO. The two classes are closely associated. Like the File
11801 * class, the Socket library subclasses from IO (such as TCPSocket or
11802 * UDPSocket).
11803 *
11804 * The Kernel#open method can create an IO (or File) object for these types
11805 * of arguments:
11806 *
11807 * * A plain string represents a filename suitable for the underlying
11808 * operating system.
11809 *
11810 * * A string starting with <code>"|"</code> indicates a subprocess.
11811 * The remainder of the string following the <code>"|"</code> is
11812 * invoked as a process with appropriate input/output channels
11813 * connected to it.
11814 *
11815 * * A string equal to <code>"|-"</code> will create another Ruby
11816 * instance as a subprocess.
11817 *
11818 * The IO may be opened with different file modes (read-only, write-only) and
11819 * encodings for proper conversion. See IO.new for these options. See
11820 * Kernel#open for details of the various command formats described above.
11821 *
11822 * IO.popen, the Open3 library, or Process#spawn may also be used to
11823 * communicate with subprocesses through an IO.
11824 *
11825 * Ruby will convert pathnames between different operating system
11826 * conventions if possible. For instance, on a Windows system the
11827 * filename <code>"/gumby/ruby/test.rb"</code> will be opened as
11828 * <code>"\gumby\ruby\test.rb"</code>. When specifying a Windows-style
11829 * filename in a Ruby string, remember to escape the backslashes:
11830 *
11831 * "c:\\gumby\\ruby\\test.rb"
11832 *
11833 * Our examples here will use the Unix-style forward slashes;
11834 * File::ALT_SEPARATOR can be used to get the platform-specific separator
11835 * character.
11836 *
11837 * The global constant ARGF (also accessible as $<) provides an
11838 * IO-like stream which allows access to all files mentioned on the
11839 * command line (or STDIN if no files are mentioned). ARGF#path and its alias
11840 * ARGF#filename are provided to access the name of the file currently being
11841 * read.
11842 *
11843 * == io/console
11844 *
11845 * The io/console extension provides methods for interacting with the
11846 * console. The console can be accessed from IO.console or the standard
11847 * input/output/error IO objects.
11848 *
11849 * Requiring io/console adds the following methods:
11850 *
11851 * * IO::console
11852 * * IO#raw
11853 * * IO#raw!
11854 * * IO#cooked
11855 * * IO#cooked!
11856 * * IO#getch
11857 * * IO#echo=
11858 * * IO#echo?
11859 * * IO#noecho
11860 * * IO#winsize
11861 * * IO#winsize=
11862 * * IO#iflush
11863 * * IO#ioflush
11864 * * IO#oflush
11865 *
11866 * Example:
11867 *
11868 * require 'io/console'
11869 * rows, columns = $stdin.winsize
11870 * puts "Your screen is #{columns} wide and #{rows} tall"
11871 */
11872
11873 void
11874 Init_IO(void)
11875 {
11876 #undef rb_intern
11877 #define rb_intern(str) rb_intern_const(str)
11878
11879 VALUE rb_cARGF;
11880 #ifdef __CYGWIN__
11881 #include <sys/cygwin.h>
11882 static struct __cygwin_perfile pf[] =
11883 {
11884 {"", O_RDONLY | O_BINARY},
11885 {"", O_WRONLY | O_BINARY},
11886 {"", O_RDWR | O_BINARY},
11887 {"", O_APPEND | O_BINARY},
11888 {NULL, 0}
11889 };
11890 cygwin_internal(CW_PERFILE, pf);
11891 #endif
11892
11893 rb_eIOError = rb_define_class("IOError", rb_eStandardError);
11894 rb_eEOFError = rb_define_class("EOFError", rb_eIOError);
11895
11896 id_write = rb_intern("write");
11897 id_read = rb_intern("read");
11898 id_getc = rb_intern("getc");
11899 id_flush = rb_intern("flush");
11900 id_readpartial = rb_intern("readpartial");
11901 id_set_encoding = rb_intern("set_encoding");
11902
11903 rb_define_global_function("syscall", rb_f_syscall, -1);
11904
11905 rb_define_global_function("open", rb_f_open, -1);
11906 rb_define_global_function("printf", rb_f_printf, -1);
11907 rb_define_global_function("print", rb_f_print, -1);
11908 rb_define_global_function("putc", rb_f_putc, 1);
11909 rb_define_global_function("puts", rb_f_puts, -1);
11910 rb_define_global_function("gets", rb_f_gets, -1);
11911 rb_define_global_function("readline", rb_f_readline, -1);
11912 rb_define_global_function("select", rb_f_select, -1);
11913
11914 rb_define_global_function("readlines", rb_f_readlines, -1);
11915
11916 rb_define_global_function("`", rb_f_backquote, 1);
11917
11918 rb_define_global_function("p", rb_f_p, -1);
11919 rb_define_method(rb_mKernel, "display", rb_obj_display, -1);
11920
11921 rb_cIO = rb_define_class("IO", rb_cObject);
11922 rb_include_module(rb_cIO, rb_mEnumerable);
11923
11924 rb_mWaitReadable = rb_define_module_under(rb_cIO, "WaitReadable");
11925 rb_mWaitWritable = rb_define_module_under(rb_cIO, "WaitWritable");
11926 rb_eEAGAINWaitReadable = rb_define_class_under(rb_cIO, "EAGAINWaitReadable", rb_eEAGAIN);
11927 rb_include_module(rb_eEAGAINWaitReadable, rb_mWaitReadable);
11928 rb_eEAGAINWaitWritable = rb_define_class_under(rb_cIO, "EAGAINWaitWritable", rb_eEAGAIN);
11929 rb_include_module(rb_eEAGAINWaitWritable, rb_mWaitWritable);
11930 #if EAGAIN == EWOULDBLOCK
11931 rb_eEWOULDBLOCKWaitReadable = rb_eEAGAINWaitReadable;
11932 /* same as IO::EAGAINWaitReadable */
11933 rb_define_const(rb_cIO, "EWOULDBLOCKWaitReadable", rb_eEAGAINWaitReadable);
11934 rb_eEWOULDBLOCKWaitWritable = rb_eEAGAINWaitWritable;
11935 /* same as IO::EAGAINWaitWritable */
11936 rb_define_const(rb_cIO, "EWOULDBLOCKWaitWritable", rb_eEAGAINWaitWritable);
11937 #else
11938 rb_eEWOULDBLOCKWaitReadable = rb_define_class_under(rb_cIO, "EWOULDBLOCKWaitReadable", rb_eEWOULDBLOCK);
11939 rb_include_module(rb_eEWOULDBLOCKWaitReadable, rb_mWaitReadable);
11940 rb_eEWOULDBLOCKWaitWritable = rb_define_class_under(rb_cIO, "EWOULDBLOCKWaitWritable", rb_eEWOULDBLOCK);
11941 rb_include_module(rb_eEWOULDBLOCKWaitWritable, rb_mWaitWritable);
11942 #endif
11943 rb_eEINPROGRESSWaitReadable = rb_define_class_under(rb_cIO, "EINPROGRESSWaitReadable", rb_eEINPROGRESS);
11944 rb_include_module(rb_eEINPROGRESSWaitReadable, rb_mWaitReadable);
11945 rb_eEINPROGRESSWaitWritable = rb_define_class_under(rb_cIO, "EINPROGRESSWaitWritable", rb_eEINPROGRESS);
11946 rb_include_module(rb_eEINPROGRESSWaitWritable, rb_mWaitWritable);
11947
11948 #if 0
11949 /* This is necessary only for forcing rdoc handle File::open */
11950 rb_define_singleton_method(rb_cFile, "open", rb_io_s_open, -1);
11951 #endif
11952
11953 rb_define_alloc_func(rb_cIO, io_alloc);
11954 rb_define_singleton_method(rb_cIO, "new", rb_io_s_new, -1);
11955 rb_define_singleton_method(rb_cIO, "open", rb_io_s_open, -1);
11956 rb_define_singleton_method(rb_cIO, "sysopen", rb_io_s_sysopen, -1);
11957 rb_define_singleton_method(rb_cIO, "for_fd", rb_io_s_for_fd, -1);
11958 rb_define_singleton_method(rb_cIO, "popen", rb_io_s_popen, -1);
11959 rb_define_singleton_method(rb_cIO, "foreach", rb_io_s_foreach, -1);
11960 rb_define_singleton_method(rb_cIO, "readlines", rb_io_s_readlines, -1);
11961 rb_define_singleton_method(rb_cIO, "read", rb_io_s_read, -1);
11962 rb_define_singleton_method(rb_cIO, "binread", rb_io_s_binread, -1);
11963 rb_define_singleton_method(rb_cIO, "write", rb_io_s_write, -1);
11964 rb_define_singleton_method(rb_cIO, "binwrite", rb_io_s_binwrite, -1);
11965 rb_define_singleton_method(rb_cIO, "select", rb_f_select, -1);
11966 rb_define_singleton_method(rb_cIO, "pipe", rb_io_s_pipe, -1);
11967 rb_define_singleton_method(rb_cIO, "try_convert", rb_io_s_try_convert, 1);
11968 rb_define_singleton_method(rb_cIO, "copy_stream", rb_io_s_copy_stream, -1);
11969
11970 rb_define_method(rb_cIO, "initialize", rb_io_initialize, -1);
11971
11972 rb_output_fs = Qnil;
11973 rb_define_hooked_variable("$,", &rb_output_fs, 0, rb_str_setter);
11974
11975 rb_rs = rb_default_rs = rb_usascii_str_new2("\n");
11976 rb_gc_register_mark_object(rb_default_rs);
11977 rb_output_rs = Qnil;
11978 OBJ_FREEZE(rb_default_rs); /* avoid modifying RS_default */
11979 rb_define_hooked_variable("$/", &rb_rs, 0, rb_str_setter);
11980 rb_define_hooked_variable("$-0", &rb_rs, 0, rb_str_setter);
11981 rb_define_hooked_variable("$\\", &rb_output_rs, 0, rb_str_setter);
11982
11983 rb_define_virtual_variable("$_", rb_lastline_get, rb_lastline_set);
11984
11985 rb_define_method(rb_cIO, "initialize_copy", rb_io_init_copy, 1);
11986 rb_define_method(rb_cIO, "reopen", rb_io_reopen, -1);
11987
11988 rb_define_method(rb_cIO, "print", rb_io_print, -1);
11989 rb_define_method(rb_cIO, "putc", rb_io_putc, 1);
11990 rb_define_method(rb_cIO, "puts", rb_io_puts, -1);
11991 rb_define_method(rb_cIO, "printf", rb_io_printf, -1);
11992
11993 rb_define_method(rb_cIO, "each", rb_io_each_line, -1);
11994 rb_define_method(rb_cIO, "each_line", rb_io_each_line, -1);
11995 rb_define_method(rb_cIO, "each_byte", rb_io_each_byte, 0);
11996 rb_define_method(rb_cIO, "each_char", rb_io_each_char, 0);
11997 rb_define_method(rb_cIO, "each_codepoint", rb_io_each_codepoint, 0);
11998 rb_define_method(rb_cIO, "lines", rb_io_lines, -1);
11999 rb_define_method(rb_cIO, "bytes", rb_io_bytes, 0);
12000 rb_define_method(rb_cIO, "chars", rb_io_chars, 0);
12001 rb_define_method(rb_cIO, "codepoints", rb_io_codepoints, 0);
12002
12003 rb_define_method(rb_cIO, "syswrite", rb_io_syswrite, 1);
12004 rb_define_method(rb_cIO, "sysread", rb_io_sysread, -1);
12005
12006 rb_define_method(rb_cIO, "fileno", rb_io_fileno, 0);
12007 rb_define_alias(rb_cIO, "to_i", "fileno");
12008 rb_define_method(rb_cIO, "to_io", rb_io_to_io, 0);
12009
12010 rb_define_method(rb_cIO, "fsync", rb_io_fsync, 0);
12011 rb_define_method(rb_cIO, "fdatasync", rb_io_fdatasync, 0);
12012 rb_define_method(rb_cIO, "sync", rb_io_sync, 0);
12013 rb_define_method(rb_cIO, "sync=", rb_io_set_sync, 1);
12014
12015 rb_define_method(rb_cIO, "lineno", rb_io_lineno, 0);
12016 rb_define_method(rb_cIO, "lineno=", rb_io_set_lineno, 1);
12017
12018 rb_define_method(rb_cIO, "readlines", rb_io_readlines, -1);
12019
12020 rb_define_method(rb_cIO, "read_nonblock", io_read_nonblock, -1);
12021 rb_define_method(rb_cIO, "write_nonblock", rb_io_write_nonblock, -1);
12022 rb_define_method(rb_cIO, "readpartial", io_readpartial, -1);
12023 rb_define_method(rb_cIO, "read", io_read, -1);
12024 rb_define_method(rb_cIO, "write", io_write_m, 1);
12025 rb_define_method(rb_cIO, "gets", rb_io_gets_m, -1);
12026 rb_define_method(rb_cIO, "readline", rb_io_readline, -1);
12027 rb_define_method(rb_cIO, "getc", rb_io_getc, 0);
12028 rb_define_method(rb_cIO, "getbyte", rb_io_getbyte, 0);
12029 rb_define_method(rb_cIO, "readchar", rb_io_readchar, 0);
12030 rb_define_method(rb_cIO, "readbyte", rb_io_readbyte, 0);
12031 rb_define_method(rb_cIO, "ungetbyte",rb_io_ungetbyte, 1);
12032 rb_define_method(rb_cIO, "ungetc",rb_io_ungetc, 1);
12033 rb_define_method(rb_cIO, "<<", rb_io_addstr, 1);
12034 rb_define_method(rb_cIO, "flush", rb_io_flush, 0);
12035 rb_define_method(rb_cIO, "tell", rb_io_tell, 0);
12036 rb_define_method(rb_cIO, "seek", rb_io_seek_m, -1);
12037 /* Set I/O position from the beginning */
12038 rb_define_const(rb_cIO, "SEEK_SET", INT2FIX(SEEK_SET));
12039 /* Set I/O position from the current position */
12040 rb_define_const(rb_cIO, "SEEK_CUR", INT2FIX(SEEK_CUR));
12041 /* Set I/O position from the end */
12042 rb_define_const(rb_cIO, "SEEK_END", INT2FIX(SEEK_END));
12043 #ifdef SEEK_DATA
12044 /* Set I/O position to the next location containing data */
12045 rb_define_const(rb_cIO, "SEEK_DATA", INT2FIX(SEEK_DATA));
12046 #endif
12047 #ifdef SEEK_HOLE
12048 /* Set I/O position to the next hole */
12049 rb_define_const(rb_cIO, "SEEK_HOLE", INT2FIX(SEEK_HOLE));
12050 #endif
12051 rb_define_method(rb_cIO, "rewind", rb_io_rewind, 0);
12052 rb_define_method(rb_cIO, "pos", rb_io_tell, 0);
12053 rb_define_method(rb_cIO, "pos=", rb_io_set_pos, 1);
12054 rb_define_method(rb_cIO, "eof", rb_io_eof, 0);
12055 rb_define_method(rb_cIO, "eof?", rb_io_eof, 0);
12056
12057 rb_define_method(rb_cIO, "close_on_exec?", rb_io_close_on_exec_p, 0);
12058 rb_define_method(rb_cIO, "close_on_exec=", rb_io_set_close_on_exec, 1);
12059
12060 rb_define_method(rb_cIO, "close", rb_io_close_m, 0);
12061 rb_define_method(rb_cIO, "closed?", rb_io_closed, 0);
12062 rb_define_method(rb_cIO, "close_read", rb_io_close_read, 0);
12063 rb_define_method(rb_cIO, "close_write", rb_io_close_write, 0);
12064
12065 rb_define_method(rb_cIO, "isatty", rb_io_isatty, 0);
12066 rb_define_method(rb_cIO, "tty?", rb_io_isatty, 0);
12067 rb_define_method(rb_cIO, "binmode", rb_io_binmode_m, 0);
12068 rb_define_method(rb_cIO, "binmode?", rb_io_binmode_p, 0);
12069 rb_define_method(rb_cIO, "sysseek", rb_io_sysseek, -1);
12070 rb_define_method(rb_cIO, "advise", rb_io_advise, -1);
12071
12072 rb_define_method(rb_cIO, "ioctl", rb_io_ioctl, -1);
12073 rb_define_method(rb_cIO, "fcntl", rb_io_fcntl, -1);
12074 rb_define_method(rb_cIO, "pid", rb_io_pid, 0);
12075 rb_define_method(rb_cIO, "inspect", rb_io_inspect, 0);
12076
12077 rb_define_method(rb_cIO, "external_encoding", rb_io_external_encoding, 0);
12078 rb_define_method(rb_cIO, "internal_encoding", rb_io_internal_encoding, 0);
12079 rb_define_method(rb_cIO, "set_encoding", rb_io_set_encoding, -1);
12080
12081 rb_define_method(rb_cIO, "autoclose?", rb_io_autoclose_p, 0);
12082 rb_define_method(rb_cIO, "autoclose=", rb_io_set_autoclose, 1);
12083
12084 rb_define_variable("$stdin", &rb_stdin);
12085 rb_stdin = prep_stdio(stdin, FMODE_READABLE, rb_cIO, "<STDIN>");
12086 rb_define_hooked_variable("$stdout", &rb_stdout, 0, stdout_setter);
12087 rb_stdout = prep_stdio(stdout, FMODE_WRITABLE, rb_cIO, "<STDOUT>");
12088 rb_define_hooked_variable("$stderr", &rb_stderr, 0, stdout_setter);
12089 rb_stderr = prep_stdio(stderr, FMODE_WRITABLE|FMODE_SYNC, rb_cIO, "<STDERR>");
12090 rb_define_hooked_variable("$>", &rb_stdout, 0, stdout_setter);
12091 orig_stdout = rb_stdout;
12092 rb_deferr = orig_stderr = rb_stderr;
12093
12094 /* Holds the original stdin */
12095 rb_define_global_const("STDIN", rb_stdin);
12096 /* Holds the original stdout */
12097 rb_define_global_const("STDOUT", rb_stdout);
12098 /* Holds the original stderr */
12099 rb_define_global_const("STDERR", rb_stderr);
12100
12101 #if 0
12102 /* Hack to get rdoc to regard ARGF as a class: */
12103 rb_cARGF = rb_define_class("ARGF", rb_cObject);
12104 #endif
12105
12106 rb_cARGF = rb_class_new(rb_cObject);
12107 rb_set_class_path(rb_cARGF, rb_cObject, "ARGF.class");
12108 rb_define_alloc_func(rb_cARGF, argf_alloc);
12109
12110 rb_include_module(rb_cARGF, rb_mEnumerable);
12111
12112 rb_define_method(rb_cARGF, "initialize", argf_initialize, -2);
12113 rb_define_method(rb_cARGF, "initialize_copy", argf_initialize_copy, 1);
12114 rb_define_method(rb_cARGF, "to_s", argf_to_s, 0);
12115 rb_define_alias(rb_cARGF, "inspect", "to_s");
12116 rb_define_method(rb_cARGF, "argv", argf_argv, 0);
12117
12118 rb_define_method(rb_cARGF, "fileno", argf_fileno, 0);
12119 rb_define_method(rb_cARGF, "to_i", argf_fileno, 0);
12120 rb_define_method(rb_cARGF, "to_io", argf_to_io, 0);
12121 rb_define_method(rb_cARGF, "to_write_io", argf_write_io, 0);
12122 rb_define_method(rb_cARGF, "each", argf_each_line, -1);
12123 rb_define_method(rb_cARGF, "each_line", argf_each_line, -1);
12124 rb_define_method(rb_cARGF, "each_byte", argf_each_byte, 0);
12125 rb_define_method(rb_cARGF, "each_char", argf_each_char, 0);
12126 rb_define_method(rb_cARGF, "each_codepoint", argf_each_codepoint, 0);
12127 rb_define_method(rb_cARGF, "lines", argf_lines, -1);
12128 rb_define_method(rb_cARGF, "bytes", argf_bytes, 0);
12129 rb_define_method(rb_cARGF, "chars", argf_chars, 0);
12130 rb_define_method(rb_cARGF, "codepoints", argf_codepoints, 0);
12131
12132 rb_define_method(rb_cARGF, "read", argf_read, -1);
12133 rb_define_method(rb_cARGF, "readpartial", argf_readpartial, -1);
12134 rb_define_method(rb_cARGF, "read_nonblock", argf_read_nonblock, -1);
12135 rb_define_method(rb_cARGF, "readlines", argf_readlines, -1);
12136 rb_define_method(rb_cARGF, "to_a", argf_readlines, -1);
12137 rb_define_method(rb_cARGF, "gets", argf_gets, -1);
12138 rb_define_method(rb_cARGF, "readline", argf_readline, -1);
12139 rb_define_method(rb_cARGF, "getc", argf_getc, 0);
12140 rb_define_method(rb_cARGF, "getbyte", argf_getbyte, 0);
12141 rb_define_method(rb_cARGF, "readchar", argf_readchar, 0);
12142 rb_define_method(rb_cARGF, "readbyte", argf_readbyte, 0);
12143 rb_define_method(rb_cARGF, "tell", argf_tell, 0);
12144 rb_define_method(rb_cARGF, "seek", argf_seek_m, -1);
12145 rb_define_method(rb_cARGF, "rewind", argf_rewind, 0);
12146 rb_define_method(rb_cARGF, "pos", argf_tell, 0);
12147 rb_define_method(rb_cARGF, "pos=", argf_set_pos, 1);
12148 rb_define_method(rb_cARGF, "eof", argf_eof, 0);
12149 rb_define_method(rb_cARGF, "eof?", argf_eof, 0);
12150 rb_define_method(rb_cARGF, "binmode", argf_binmode_m, 0);
12151 rb_define_method(rb_cARGF, "binmode?", argf_binmode_p, 0);
12152
12153 rb_define_method(rb_cARGF, "write", argf_write, 1);
12154 rb_define_method(rb_cARGF, "print", rb_io_print, -1);
12155 rb_define_method(rb_cARGF, "putc", rb_io_putc, 1);
12156 rb_define_method(rb_cARGF, "puts", rb_io_puts, -1);
12157 rb_define_method(rb_cARGF, "printf", rb_io_printf, -1);
12158
12159 rb_define_method(rb_cARGF, "filename", argf_filename, 0);
12160 rb_define_method(rb_cARGF, "path", argf_filename, 0);
12161 rb_define_method(rb_cARGF, "file", argf_file, 0);
12162 rb_define_method(rb_cARGF, "skip", argf_skip, 0);
12163 rb_define_method(rb_cARGF, "close", argf_close_m, 0);
12164 rb_define_method(rb_cARGF, "closed?", argf_closed, 0);
12165
12166 rb_define_method(rb_cARGF, "lineno", argf_lineno, 0);
12167 rb_define_method(rb_cARGF, "lineno=", argf_set_lineno, 1);
12168
12169 rb_define_method(rb_cARGF, "inplace_mode", argf_inplace_mode_get, 0);
12170 rb_define_method(rb_cARGF, "inplace_mode=", argf_inplace_mode_set, 1);
12171
12172 rb_define_method(rb_cARGF, "external_encoding", argf_external_encoding, 0);
12173 rb_define_method(rb_cARGF, "internal_encoding", argf_internal_encoding, 0);
12174 rb_define_method(rb_cARGF, "set_encoding", argf_set_encoding, -1);
12175
12176 argf = rb_class_new_instance(0, 0, rb_cARGF);
12177
12178 rb_define_readonly_variable("$<", &argf);
12179 /*
12180 * ARGF is a stream designed for use in scripts that process files given
12181 * as command-line arguments or passed in via STDIN.
12182 *
12183 * See ARGF (the class) for more details.
12184 */
12185 rb_define_global_const("ARGF", argf);
12186
12187 rb_define_hooked_variable("$.", &argf, argf_lineno_getter, argf_lineno_setter);
12188 rb_define_hooked_variable("$FILENAME", &argf, argf_filename_getter, rb_gvar_readonly_setter);
12189 ARGF.filename = rb_str_new2("-");
12190
12191 rb_define_hooked_variable("$-i", &argf, opt_i_get, opt_i_set);
12192 rb_define_hooked_variable("$*", &argf, argf_argv_getter, rb_gvar_readonly_setter);
12193
12194 #if defined (_WIN32) || defined(__CYGWIN__)
12195 atexit(pipe_atexit);
12196 #endif
12197
12198 Init_File();
12199
12200 rb_define_method(rb_cFile, "initialize", rb_file_initialize, -1);
12201
12202 sym_mode = ID2SYM(rb_intern("mode"));
12203 sym_perm = ID2SYM(rb_intern("perm"));
12204 sym_extenc = ID2SYM(rb_intern("external_encoding"));
12205 sym_intenc = ID2SYM(rb_intern("internal_encoding"));
12206 sym_encoding = ID2SYM(rb_intern("encoding"));
12207 sym_open_args = ID2SYM(rb_intern("open_args"));
12208 sym_textmode = ID2SYM(rb_intern("textmode"));
12209 sym_binmode = ID2SYM(rb_intern("binmode"));
12210 sym_autoclose = ID2SYM(rb_intern("autoclose"));
12211 sym_normal = ID2SYM(rb_intern("normal"));
12212 sym_sequential = ID2SYM(rb_intern("sequential"));
12213 sym_random = ID2SYM(rb_intern("random"));
12214 sym_willneed = ID2SYM(rb_intern("willneed"));
12215 sym_dontneed = ID2SYM(rb_intern("dontneed"));
12216 sym_noreuse = ID2SYM(rb_intern("noreuse"));
12217 sym_SET = ID2SYM(rb_intern("SET"));
12218 sym_CUR = ID2SYM(rb_intern("CUR"));
12219 sym_END = ID2SYM(rb_intern("END"));
12220 #ifdef SEEK_DATA
12221 sym_DATA = ID2SYM(rb_intern("DATA"));
12222 #endif
12223 #ifdef SEEK_HOLE
12224 sym_HOLE = ID2SYM(rb_intern("HOLE"));
12225 #endif
12226 sym_exception = ID2SYM(rb_intern("exception"));
12227 }
argf_bytes
static VALUE argf_bytes(VALUE argf)
Definition: io.c:11266
STRNCASECMP
#define STRNCASECMP(s1, s2, n)
Definition: ruby.h:1784
rb_define_global_const
void rb_define_global_const(const char *, VALUE)
Definition: variable.c:2236
RBASIC_CLEAR_CLASS
#define RBASIC_CLEAR_CLASS(obj)
Definition: internal.h:607
rb_time_interval
struct timeval rb_time_interval(VALUE num)
Definition: time.c:2411
ruby_strtoul
unsigned long ruby_strtoul(const char *str, char **endptr, int base)
Definition: util.c:107
rb_gc
void rb_gc(void)
Definition: gc.c:5190
read_internal_arg::len
long len
Definition: io.c:2403
rb_econv_open_exc
VALUE rb_econv_open_exc(const char *senc, const char *denc, int ecflags)
Definition: transcode.c:2036
make_readconv
static void make_readconv(rb_io_t *fptr, int size)
Definition: io.c:2143
rb_eStandardError
VALUE rb_eStandardError
Definition: error.c:546
rb_execarg_setenv
void rb_execarg_setenv(VALUE execarg_obj, VALUE env)
Definition: process.c:2299
rb_io_rewind
static VALUE rb_io_rewind(VALUE io)
Definition: io.c:1655
rb_econv_asciicompat_encoding
const char * rb_econv_asciicompat_encoding(const char *encname)
Definition: transcode.c:1786
rb_io_close_read
static VALUE rb_io_close_read(VALUE io)
Definition: io.c:4434
argf_close
static void argf_close(VALUE argf)
Definition: io.c:7720
rb_pipe
int rb_pipe(int *pipes)
Definition: io.c:5651
rb_obj_display
static VALUE rb_obj_display(int argc, VALUE *argv, VALUE self)
Definition: io.c:7127
nogvl_copy_stream_wait_write
static int nogvl_copy_stream_wait_write(struct copy_stream_struct *stp)
Definition: io.c:9888
rb_io_getbyte
VALUE rb_io_getbyte(VALUE io)
Definition: io.c:3772
fcntl_narg_len
static long fcntl_narg_len(int cmd)
Definition: io.c:8889
rb_io_set_lineno
static VALUE rb_io_set_lineno(VALUE io, VALUE lineno)
Definition: io.c:3274
rb_io_wait_writable
int rb_io_wait_writable(int f)
Definition: io.c:1103
id_set_encoding
static ID id_set_encoding
Definition: io.c:160
MBCLEN_CHARFOUND_P
#define MBCLEN_CHARFOUND_P(ret)
Definition: encoding.h:139
rb_thread_atfork
void rb_thread_atfork(void)
Definition: thread.c:3931
io_internal_write_struct::capa
size_t capa
Definition: io.c:920
ECONV_NEWLINE_DECORATOR_WRITE_MASK
#define ECONV_NEWLINE_DECORATOR_WRITE_MASK
Definition: encoding.h:330
copy_stream_struct::total
off_t total
Definition: io.c:9819
argf_getpartial
static VALUE argf_getpartial(int argc, VALUE *argv, VALUE argf, int nonblock)
Definition: io.c:10956
argf_call_arg::argf
VALUE argf
Definition: io.c:10902
copy_stream_struct::error_no
int error_no
Definition: io.c:9821
rb_str_new4
#define rb_str_new4
Definition: intern.h:842
rb_econv_result_t
rb_econv_result_t
Definition: encoding.h:252
rb_io_set_sync
static VALUE rb_io_set_sync(VALUE io, VALUE sync)
Definition: io.c:1856
rb_ary_entry
VALUE rb_ary_entry(VALUE ary, long offset)
Definition: array.c:1171
MBCLEN_CHARFOUND_LEN
#define MBCLEN_CHARFOUND_LEN(ret)
Definition: encoding.h:140
ioctl_arg
Definition: io.c:8686
RARRAY_LEN
#define RARRAY_LEN(a)
Definition: ruby.h:878
rb_bug
void rb_bug(const char *fmt,...)
Definition: error.c:327
FALSE
#define FALSE
Definition: nkf.h:174
RUBY_TYPED_FREE_IMMEDIATELY
#define RUBY_TYPED_FREE_IMMEDIATELY
Definition: ruby.h:1015
ioctl
int ioctl(int, int,...)
Definition: win32.c:2540
rb_io_internal_encoding
static VALUE rb_io_internal_encoding(VALUE)
Definition: io.c:10513
rb_io_s_readlines
static VALUE rb_io_s_readlines(int argc, VALUE *argv, VALUE io)
Definition: io.c:9570
FMODE_READWRITE
#define FMODE_READWRITE
Definition: io.h:103
rb_str_coderange_scan_restartable
long rb_str_coderange_scan_restartable(const char *, const char *, rb_encoding *, int *)
Definition: string.c:340
rb_hash_lookup
#define rb_hash_lookup
Definition: tcltklib.c:269
sym_random
static VALUE sym_random
Definition: io.c:8340
rb_io_closed
static VALUE rb_io_closed(VALUE io)
Definition: io.c:4396
rb_execarg::invoke
union rb_execarg::@123 invoke
SSIZE_MAX
#define SSIZE_MAX
Definition: ruby.h:290
strlen
size_t strlen(const char *)
io_enc_str
static VALUE io_enc_str(VALUE str, rb_io_t *fptr)
Definition: io.c:2135
INT2NUM
#define INT2NUM(x)
Definition: ruby.h:1288
rb_cIO
VALUE rb_cIO
Definition: io.c:133
dln.h
rb_io_check_writable
void rb_io_check_writable(rb_io_t *fptr)
Definition: io.c:818
T_FIXNUM
#define T_FIXNUM
Definition: ruby.h:489
sym_autoclose
static VALUE sym_autoclose
Definition: io.c:162
setup_narg
static long setup_narg(ioctl_req_t cmd, VALUE *argp, int io_p)
Definition: io.c:8896
sym_encoding
static VALUE sym_encoding
Definition: io.c:161
argf_set_pos
static VALUE argf_set_pos(VALUE argf, VALUE offset)
Definition: io.c:10711
closed_stream
static const char closed_stream[]
Definition: io.c:593
id_getc
static ID id_getc
Definition: io.c:160
rb_io_codepoints
static VALUE rb_io_codepoints(VALUE io)
Definition: io.c:3701
sym_SET
static VALUE sym_SET
Definition: io.c:163
rb_io_modestr_fmode
int rb_io_modestr_fmode(const char *modestr)
Definition: io.c:4812
sym_noreuse
static VALUE sym_noreuse
Definition: io.c:8340
argf_set_lineno
static VALUE argf_set_lineno(VALUE argf, VALUE val)
Definition: io.c:7675
rb_stderr
VALUE rb_stderr
Definition: io.c:149
argf_inplace_mode_get
static VALUE argf_inplace_mode_get(VALUE argf)
Definition: io.c:11542
rb_file_open_str
VALUE rb_file_open_str(VALUE fname, const char *modestr)
Definition: io.c:5554
rb_f_putc
static VALUE rb_f_putc(VALUE recv, VALUE ch)
Definition: io.c:6918
rb_define_virtual_variable
void rb_define_virtual_variable(const char *, VALUE(*)(ANYARGS), void(*)(ANYARGS))
Definition: variable.c:616
argf_readpartial
static VALUE argf_readpartial(int argc, VALUE *argv, VALUE argf)
Definition: io.c:10936
rb_hash_dup
VALUE rb_hash_dup(VALUE hash)
Definition: hash.c:320
NUM2INT
#define NUM2INT(x)
Definition: ruby.h:630
count
int count
Definition: encoding.c:48
io_call_close
static VALUE io_call_close(VALUE io)
Definition: io.c:4347
max
static int max(int a, int b)
Definition: strftime.c:141
NUM2UINT
#define NUM2UINT(x)
Definition: ruby.h:631
id_read
static ID id_read
Definition: io.c:160
io_fflush
static int io_fflush(rb_io_t *)
Definition: io.c:1062
getuid
rb_uid_t getuid(void)
Definition: win32.c:2494
rb_io_eof
VALUE rb_io_eof(VALUE io)
Definition: io.c:1745
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:1655
rb_cloexec_open
int rb_cloexec_open(const char *pathname, int flags, mode_t mode)
Definition: io.c:228
rb_io_fmode_modestr
static const char * rb_io_fmode_modestr(int fmode)
Definition: io.c:4776
argf_init
static void argf_init(struct argf *p, VALUE v)
Definition: io.c:7611
rb_io_ioctl
static VALUE rb_io_ioctl(int argc, VALUE *argv, VALUE io)
Definition: io.c:8975
argf_inplace_mode_set
static VALUE argf_inplace_mode_set(VALUE argf, VALUE val)
Definition: io.c:11575
ruby.h
ioctl_req_t
int ioctl_req_t
Definition: io.c:8682
sysopen_struct::fname
VALUE fname
Definition: io.c:5326
rb_f_sprintf
VALUE rb_f_sprintf(int, const VALUE *)
Definition: sprintf.c:415
pipe_open
static VALUE pipe_open(VALUE execarg_obj, const char *modestr, int fmode, convconfig_t *convconfig)
Definition: io.c:5803
rb_econv_memsize
size_t rb_econv_memsize(rb_econv_t *)
Definition: transcode.c:1720
must_respond_to
static void must_respond_to(ID mid, VALUE val, ID id)
Definition: io.c:7180
FilePathValue
#define FilePathValue(v)
Definition: ruby.h:560
rb_usascii_str_new2
#define rb_usascii_str_new2
Definition: intern.h:846
binwrite_arg::str
VALUE str
Definition: io.c:1195
io_s_write
static VALUE io_s_write(int argc, VALUE *argv, int binary)
Definition: io.c:9701
rb_io_set_nonblock
void rb_io_set_nonblock(rb_io_t *fptr)
Definition: io.c:2378
CLASS_OF
#define CLASS_OF(v)
Definition: ruby.h:440
select_call
static VALUE select_call(VALUE arg)
Definition: io.c:8322
rb_str_cat
VALUE rb_str_cat(VALUE, const char *, long)
Definition: string.c:2140
PIDT2NUM
#define PIDT2NUM(v)
Definition: ruby.h:321
argf_readbyte
static VALUE argf_readbyte(VALUE argf)
Definition: io.c:11140
ARGF_FORWARD
#define ARGF_FORWARD(argc, argv)
Definition: io.c:7710
argf_gets
static VALUE argf_gets(int, VALUE *, VALUE)
Definition: io.c:8003
rb_io_t
struct rb_io_t rb_io_t
select_args::fdsets
rb_fdset_t fdsets[4]
Definition: io.c:8318
Qtrue
#define Qtrue
Definition: ruby.h:426
rb_io_t::cbuf
rb_io_buffer_t cbuf
Definition: io.h:88
rb_io_binmode
VALUE rb_io_binmode(VALUE io)
Definition: io.c:4679
argf_mark
static void argf_mark(void *ptr)
Definition: io.c:7577
rb_io_t::rb_io_enc_t::ecopts
VALUE ecopts
Definition: io.h:84
io_puts_ary
static VALUE io_puts_ary(VALUE ary, VALUE out, int recur)
Definition: io.c:6943
rb_io_binmode_p
static VALUE rb_io_binmode_p(VALUE io)
Definition: io.c:4768
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:2957
rb_io_t
Definition: io.h:61
OBJ_INIT_COPY
#define OBJ_INIT_COPY(obj, orig)
Definition: intern.h:287
io_internal_read_struct::buf
void * buf
Definition: io.c:913
ENC_CODERANGE_SET
#define ENC_CODERANGE_SET(obj, cr)
Definition: encoding.h:54
READ_DATA_PENDING_COUNT
#define READ_DATA_PENDING_COUNT(fptr)
Definition: io.c:387
rb_ary_shift
VALUE rb_ary_shift(VALUE ary)
Definition: array.c:991
bufread_arg::str_ptr
char * str_ptr
Definition: io.c:2064
rb_eEAGAINWaitWritable
static VALUE rb_eEAGAINWaitWritable
Definition: io.c:143
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:3104
ECONV_ERROR_HANDLER_MASK
#define ECONV_ERROR_HANDLER_MASK
Definition: encoding.h:318
IO_WBUF_CAPA_MIN
#define IO_WBUF_CAPA_MIN
Definition: io.c:125
F_DUPFD
#define F_DUPFD
Definition: win32.h:616
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:1366
orig_stderr
static VALUE orig_stderr
Definition: io.c:151
io_s_foreach
static VALUE io_s_foreach(struct foreach_arg *arg)
Definition: io.c:9495
FMODE_WRITABLE
#define FMODE_WRITABLE
Definition: io.h:102
rb_to_encoding
rb_encoding * rb_to_encoding(VALUE enc)
Definition: encoding.c:219
rb_fd_fix_cloexec
void rb_fd_fix_cloexec(int fd)
Definition: io.c:221
is_popen_fork
static int is_popen_fork(VALUE prog)
Definition: io.c:6027
FMODE_READABLE
#define FMODE_READABLE
Definition: io.h:101
rb_econv_close
void rb_econv_close(rb_econv_t *ec)
Definition: transcode.c:1702
io_flush_buffer_async
static VALUE io_flush_buffer_async(VALUE arg)
Definition: io.c:1022
io_binwrite_string
static VALUE io_binwrite_string(VALUE arg)
Definition: io.c:1207
rb_str_unlocktmp
VALUE rb_str_unlocktmp(VALUE)
Definition: string.c:1991
timeval::tv_sec
long tv_sec
Definition: ossl_asn1.c:17
argf_call_arg::argc
int argc
Definition: io.c:10900
io_encoding_set
static void io_encoding_set(rb_io_t *, VALUE, VALUE, VALUE)
Definition: io.c:9255
rb_io_syswrite
static VALUE rb_io_syswrite(VALUE io, VALUE str)
Definition: io.c:4580
FMODE_WSPLIT_INITIALIZED
#define FMODE_WSPLIT_INITIALIZED
Definition: io.h:112
rb_enc_from_encoding
VALUE rb_enc_from_encoding(rb_encoding *encoding)
Definition: encoding.c:102
find_encoding
static rb_encoding * find_encoding(VALUE v)
Definition: io.c:9247
rb_frame_this_func
ID rb_frame_this_func(void)
Definition: eval.c:943
argf_external_encoding
static VALUE argf_external_encoding(VALUE argf)
Definition: io.c:10585
rb_w32_get_osfhandle
SOCKET rb_w32_get_osfhandle(int)
Definition: win32.c:984
argf_call_arg
Definition: io.c:10899
rb_eTypeError
VALUE rb_eTypeError
Definition: error.c:548
id_write
static ID id_write
Definition: io.c:160
sym_mode
static VALUE sym_mode
Definition: io.c:161
argf_each_line
static VALUE argf_each_line(int argc, VALUE *argv, VALUE argf)
Definition: io.c:11205
UNREACHABLE
#define UNREACHABLE
Definition: ruby.h:42
rb_io_close_write
static VALUE rb_io_close_write(VALUE io)
Definition: io.c:4494
argf_call_arg::argv
VALUE * argv
Definition: io.c:10901
rb_default_internal_encoding
rb_encoding * rb_default_internal_encoding(void)
Definition: encoding.c:1436
argf_filename
static VALUE argf_filename(VALUE argf)
Definition: io.c:11375
rb_ary_push
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:896
fptr_finalize
static void fptr_finalize(rb_io_t *fptr, int noraise)
Definition: io.c:4153
rb_cFile
VALUE rb_cFile
Definition: file.c:139
rb_close_before_exec
void rb_close_before_exec(int lowfd, int maxhint, VALUE noclose_fds)
rb_io_fcntl
#define rb_io_fcntl
Definition: io.c:9077
opt_i_get
static VALUE opt_i_get(ID id, VALUE *var)
Definition: io.c:11549
fcntl
int fcntl(int, int,...)
Definition: win32.c:4085
rb_thread_alone
int rb_thread_alone(void)
Definition: thread.c:2990
rb_p
void rb_p(VALUE obj)
Definition: io.c:7032
rb_ary_tmp_new
VALUE rb_ary_tmp_new(long capa)
Definition: array.c:534
argf_argv
static VALUE argf_argv(VALUE argf)
Definition: io.c:11628
io_encname_bom_p
static int io_encname_bom_p(const char *name, long len)
Definition: io.c:4800
rb_io_seek
static VALUE rb_io_seek(VALUE io, VALUE offset, int whence)
Definition: io.c:1542
free
#define free(x)
Definition: io.c:24
rb_io_print
VALUE rb_io_print(int argc, VALUE *argv, VALUE out)
Definition: io.c:6818
rb_fd_zero
#define rb_fd_zero(f)
Definition: intern.h:349
rb_thread_fd_select
int rb_thread_fd_select(int, rb_fdset_t *, rb_fdset_t *, rb_fdset_t *, struct timeval *)
Definition: thread.c:3576
rb_io_getline_fast
static VALUE rb_io_getline_fast(rb_io_t *fptr, rb_encoding *enc, VALUE io)
Definition: io.c:2975
rb_fork_ruby
rb_pid_t rb_fork_ruby(int *status)
rb_funcall
VALUE rb_funcall(VALUE, ID, int,...)
Calls a method.
Definition: vm_eval.c:775
rb_io_buffer_t::ptr
char * ptr
Definition: io.h:55
argf::binmode
int8_t binmode
Definition: io.c:178
rb_str_locktmp_ensure
VALUE rb_str_locktmp_ensure(VALUE str, VALUE(*func)(VALUE), VALUE arg)
Definition: string.c:2001
rb_str_set_len
void rb_str_set_len(VALUE, long)
Definition: string.c:2008
rb_io_t::writeconv_pre_ecflags
int writeconv_pre_ecflags
Definition: io.h:92
rb_protect
VALUE rb_protect(VALUE(*proc)(VALUE), VALUE data, int *state)
Definition: eval.c:807
bufread_arg::fptr
rb_io_t * fptr
Definition: io.c:2066
RBASIC_SET_CLASS
#define RBASIC_SET_CLASS(obj, cls)
Definition: internal.h:609
rb_io_readchar
static VALUE rb_io_readchar(VALUE io)
Definition: io.c:3749
rb_enc_str_coderange
int rb_enc_str_coderange(VALUE)
Definition: string.c:435
argf_write
static VALUE argf_write(VALUE argf, VALUE str)
Definition: io.c:11668
rb_sysopen_internal
static int rb_sysopen_internal(struct sysopen_struct *data)
Definition: io.c:5340
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:676
rb_cloexec_dup2
int rb_cloexec_dup2(int oldfd, int newfd)
Definition: io.c:251
Check_Type
#define Check_Type(v, t)
Definition: ruby.h:532
rb_raise
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:1857
rb_io_sysseek
static VALUE rb_io_sysseek(int argc, VALUE *argv, VALUE io)
Definition: io.c:4540
PIPE_BUF
#define PIPE_BUF
Definition: io.c:109
SET_BINARY_MODE_WITH_SEEK_CUR
#define SET_BINARY_MODE_WITH_SEEK_CUR(fptr)
Definition: io.c:571
rb_io_t::writeconv_initialized
int writeconv_initialized
Definition: io.h:94
FMODE_CREATE
#define FMODE_CREATE
Definition: io.h:109
rb_enc_associate
VALUE rb_enc_associate(VALUE obj, rb_encoding *enc)
Definition: encoding.c:826
rb_ary_clear
VALUE rb_ary_clear(VALUE ary)
Definition: array.c:3381
pipe_add_fptr
static void pipe_add_fptr(rb_io_t *fptr)
Definition: io.c:5573
copy_stream_struct::close_src
int close_src
Definition: io.c:9817
rb_eEINPROGRESS
VALUE rb_eEINPROGRESS
Definition: error.c:42
rb_utf8_encindex
#define rb_utf8_encindex()
Definition: internal.h:403
rb_convert_type
VALUE rb_convert_type(VALUE, int, const char *, const char *)
Definition: object.c:2616
argf_binmode_p
static VALUE argf_binmode_p(VALUE argf)
Definition: io.c:11447
rb_exec_recursive
VALUE rb_exec_recursive(VALUE(*)(VALUE, VALUE, int), VALUE, VALUE)
Definition: thread.c:4982
NEED_WRITECONV
#define NEED_WRITECONV(fptr)
Definition: io.c:567
argf::lineno
long lineno
Definition: io.c:174
RB_GC_GUARD
#define RB_GC_GUARD(v)
Definition: ruby.h:523
rb_file_initialize
static VALUE rb_file_initialize(int argc, VALUE *argv, VALUE io)
Definition: io.c:7483
argf_write_io
static VALUE argf_write_io(VALUE argf)
Definition: io.c:11653
rb_define_alloc_func
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
FMODE_DUPLEX
#define FMODE_DUPLEX
Definition: io.h:107
finish_writeconv_arg
Definition: io.c:4102
rb_io_modestr_oflags
int rb_io_modestr_oflags(const char *modestr)
Definition: io.c:4931
ruby_dup
static int ruby_dup(int orig)
Definition: io.c:856
ENCODING_MAXNAMELEN
#define ENCODING_MAXNAMELEN
Definition: encoding.h:45
rb_enc_mbclen
int rb_enc_mbclen(const char *p, const char *e, rb_encoding *enc)
Definition: encoding.c:946
FMODE_BINMODE
#define FMODE_BINMODE
Definition: io.h:104
STDIO_READ_DATA_PENDING
#define STDIO_READ_DATA_PENDING(fp)
Definition: io.c:381
rb_thread_io_blocking_region
VALUE rb_thread_io_blocking_region(rb_blocking_function_t *func, void *data1, int fd)
Definition: thread.c:1380
rb_mutex_allow_trap
void rb_mutex_allow_trap(VALUE self, int val)
Definition: thread.c:4642
FMODE_APPEND
#define FMODE_APPEND
Definition: io.h:108
rb_include_module
void rb_include_module(VALUE klass, VALUE module)
Definition: class.c:827
MORE_CHAR_FINISHED
#define MORE_CHAR_FINISHED
Definition: io.c:2170
rb_block_call
VALUE rb_block_call(VALUE, ID, int, const VALUE *, rb_block_call_func_t, VALUE)
rb_syswait
void rb_syswait(rb_pid_t pid)
Definition: process.c:3754
rb_gc_mark
void rb_gc_mark(VALUE ptr)
Definition: gc.c:3604
more_char
static VALUE more_char(rb_io_t *fptr)
Definition: io.c:2246
rb_io_s_sysopen
static VALUE rb_io_s_sysopen(int argc, VALUE *argv)
Definition: io.c:6305
T_ARRAY
#define T_ARRAY
Definition: ruby.h:484
argf_lineno
static VALUE argf_lineno(VALUE argf)
Definition: io.c:7696
copy_stream_struct::copy_length
off_t copy_length
Definition: io.c:9812
RFILE
#define RFILE(obj)
Definition: ruby.h:1129
argf
Definition: io.c:171
copy_stream_struct::dst_fd
int dst_fd
Definition: io.c:9816
prepare_getline_args
static void prepare_getline_args(int argc, VALUE *argv, VALUE *rsp, long *limit, VALUE io)
Definition: io.c:3026
rb_define_global_function
void rb_define_global_function(const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a global function.
Definition: class.c:1684
ignore_closed_stream
static VALUE ignore_closed_stream(VALUE io, VALUE exc)
Definition: io.c:4354
rb_file_open_generic
static VALUE rb_file_open_generic(VALUE io, VALUE filename, int oflags, int fmode, convconfig_t *convconfig, mode_t perm)
Definition: io.c:5501
internal_write_func
static VALUE internal_write_func(void *ptr)
Definition: io.c:931
rb_io_check_initialized
void rb_io_check_initialized(rb_io_t *fptr)
Definition: io.c:609
rb_eEINPROGRESSWaitWritable
static VALUE rb_eEINPROGRESSWaitWritable
Definition: io.c:146
last
unsigned int last
Definition: nkf.c:4310
rb_io_each_byte
static VALUE rb_io_each_byte(VALUE io)
Definition: io.c:3415
rb_io_t::writeconv_pre_ecopts
VALUE writeconv_pre_ecopts
Definition: io.h:93
open_key_args
static void open_key_args(int argc, VALUE *argv, VALUE opt, struct foreach_arg *arg)
Definition: io.c:9458
argf_readchar
static VALUE argf_readchar(VALUE argf)
Definition: io.c:11100
EINPROGRESS
#define EINPROGRESS
Definition: win32.h:512
copy_stream_struct::syserr
const char * syserr
Definition: io.c:9820
rb_update_max_fd
void rb_update_max_fd(int fd)
Definition: io.c:183
FIXNUM_P
#define FIXNUM_P(f)
Definition: ruby.h:347
rb_io_external_encoding
static VALUE rb_io_external_encoding(VALUE io)
Definition: io.c:10488
rb_f_readlines
static VALUE rb_f_readlines(int argc, VALUE *argv, VALUE recv)
Definition: io.c:8105
io_set_read_length
static void io_set_read_length(VALUE str, long n)
Definition: io.c:2304
argf_next_argv
static int argf_next_argv(VALUE argf)
Definition: io.c:7732
rb_check_to_integer
VALUE rb_check_to_integer(VALUE, const char *)
Definition: object.c:2665
rb_io_t::rb_io_enc_t::enc2
rb_encoding * enc2
Definition: io.h:82
argf_type
static const rb_data_type_t argf_type
Definition: io.c:7604
io_fwrite
static long io_fwrite(VALUE str, rb_io_t *fptr, int nosync)
Definition: io.c:1351
rb_f_open
static VALUE rb_f_open(int argc, VALUE *argv)
Definition: io.c:6446
argf_each_codepoint
static VALUE argf_each_codepoint(VALUE argf)
Definition: io.c:11330
rb_io_memsize
RUBY_FUNC_EXPORTED size_t rb_io_memsize(const rb_io_t *fptr)
Definition: io.c:4280
rb_stdin
VALUE rb_stdin
Definition: io.c:149
GetOpenFile
#define GetOpenFile(obj, fp)
Definition: io.h:118
rb_io_printf
VALUE rb_io_printf(int argc, VALUE *argv, VALUE out)
Definition: io.c:6759
rb_write_internal2
static ssize_t rb_write_internal2(int fd, const void *buf, size_t count)
Definition: io.c:967
rb_execarg::envp_str
VALUE envp_str
Definition: internal.h:650
rb_f_p_arg::argc
int argc
Definition: io.c:7047
copy_stream_struct
Definition: io.c:9809
io.h
nogvl_ioctl
static VALUE nogvl_ioctl(void *ptr)
Definition: io.c:8693
validate_enc_binmode
static void validate_enc_binmode(int *fmode_p, int ecflags, rb_encoding *enc, rb_encoding *enc2)
Definition: io.c:5146
rb_f_p_internal
static VALUE rb_f_p_internal(VALUE arg)
Definition: io.c:7052
rb_io_buffer_t::capa
int capa
Definition: io.h:58
rb_io_ascii8bit_binmode
VALUE rb_io_ascii8bit_binmode(VALUE io)
Definition: io.c:4725
OBJ_TAINTED
#define OBJ_TAINTED(x)
Definition: ruby.h:1176
io_tell
#define io_tell(fptr)
Definition: io.c:757
rb_io_tell
static VALUE rb_io_tell(VALUE io)
Definition: io.c:1529
binwrite_arg::ptr
const char * ptr
Definition: io.c:1196
argf::argv
VALUE argv
Definition: io.c:175
argf
static VALUE argf
Definition: io.c:158
io_check_tty
static void io_check_tty(rb_io_t *fptr)
Definition: io.c:5412
io_write_nonblock
static VALUE io_write_nonblock(VALUE io, VALUE str, int no_exception)
Definition: io.c:2616
rb_mutex_new
VALUE rb_mutex_new(void)
Definition: thread.c:4251
ENC_CODERANGE_7BIT
#define ENC_CODERANGE_7BIT
Definition: encoding.h:49
rb_obj_classname
const char * rb_obj_classname(VALUE)
Definition: variable.c:406
rb_ary_new2
#define rb_ary_new2
Definition: intern.h:90
argf_seek_m
static VALUE argf_seek_m(int argc, VALUE *argv, VALUE argf)
Definition: io.c:10690
econv_destination_buffer_full
Definition: encoding.h:255
opt_i_set
static void opt_i_set(VALUE val, ID id, VALUE *var)
Definition: io.c:11594
GetWriteIO
#define GetWriteIO(io)
Definition: io.c:384
memmove
RUBY_EXTERN void * memmove(void *, const void *, size_t)
Definition: memmove.c:7
argf::last_lineno
long last_lineno
Definition: io.c:173
read_all
static VALUE read_all(rb_io_t *fptr, long siz, VALUE str)
Definition: io.c:2313
rb_fd_set
#define rb_fd_set(n, f)
Definition: intern.h:350
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:5076
exec_interrupts
static void * exec_interrupts(void *arg)
Definition: io.c:9828
sym
#define sym(x)
Definition: date_core.c:3695
id.h
rb_io_write
VALUE rb_io_write(VALUE io, VALUE str)
Definition: io.c:1427
rb_str_buf_cat
VALUE rb_str_buf_cat(VALUE, const char *, long)
Definition: string.c:2124
__sFILE
Definition: vsnprintf.c:175
rb_io_t::mode
int mode
Definition: io.h:64
rb_thread_fd_close
void rb_thread_fd_close(int)
Definition: thread.c:2131
rb_io_set_autoclose
static VALUE rb_io_set_autoclose(VALUE io, VALUE autoclose)
Definition: io.c:7565
NEWOBJ_OF
#define NEWOBJ_OF(obj, type, klass, flags)
Definition: ruby.h:694
rb_fd_isset
#define rb_fd_isset(n, f)
Definition: intern.h:352
maygvl_read
static ssize_t maygvl_read(int has_gvl, int fd, void *buf, size_t count)
Definition: io.c:10064
io_read_encoding
static rb_encoding * io_read_encoding(rb_io_t *fptr)
Definition: io.c:800
RB_BLOCK_CALL_FUNC_ARGLIST
#define RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg)
Definition: ruby.h:1511
rb_io_s_popen
static VALUE rb_io_s_popen(int argc, VALUE *argv, VALUE klass)
Definition: io.c:6141
rb_io_lines
static VALUE rb_io_lines(int argc, VALUE *argv, VALUE io)
Definition: io.c:3389
rb_enumeratorize
VALUE rb_enumeratorize(VALUE obj, VALUE meth, int argc, VALUE *argv)
Definition: enumerator.c:401
rb_exc_raise
void rb_exc_raise(VALUE mesg)
Definition: eval.c:567
SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2
#define SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags)
Definition: io.c:570
rb_io_set_close_on_exec
#define rb_io_set_close_on_exec
Definition: io.c:4032
rb_io_close
VALUE rb_io_close(VALUE io)
Definition: io.c:4292
rb_io_flush_raw
VALUE rb_io_flush_raw(VALUE io, int sync)
Definition: io.c:1466
rb_obj_dup
VALUE rb_obj_dup(VALUE)
Definition: object.c:406
select_args
Definition: io.c:8315
rb_io_sysread
static VALUE rb_io_sysread(int argc, VALUE *argv, VALUE io)
Definition: io.c:4625
ioctl_arg::narg
long narg
Definition: io.c:8689
io_ungetbyte
static void io_ungetbyte(VALUE str, rb_io_t *fptr)
Definition: io.c:714
argf_block_call
static void argf_block_call(ID mid, int argc, VALUE *argv, VALUE argf)
Definition: io.c:11166
ioctl_arg::cmd
ioctl_req_t cmd
Definition: io.c:8688
RB_TYPE_P
#define RB_TYPE_P(obj, type)
Definition: ruby.h:1664
rb_file_open_internal
static VALUE rb_file_open_internal(VALUE io, VALUE filename, const char *modestr)
Definition: io.c:5527
str_end_with_asciichar
static int str_end_with_asciichar(VALUE str, int c)
Definition: io.c:6928
argf_binmode_m
static VALUE argf_binmode_m(VALUE argf)
Definition: io.c:11424
fmode
#define fmode
argf::current_file
VALUE current_file
Definition: io.c:172
rb_thread_fd_writable
int rb_thread_fd_writable(int)
Definition: thread.c:3525
rb_econv_make_exception
VALUE rb_econv_make_exception(rb_econv_t *ec)
Definition: transcode.c:4207
O_CLOEXEC
#define O_CLOEXEC
MEMZERO
#define MEMZERO(p, type, n)
Definition: ruby.h:1351
sym_CUR
static VALUE sym_CUR
Definition: io.c:163
rb_econv_check_error
void rb_econv_check_error(rb_econv_t *ec)
Definition: transcode.c:4213
rb_io_t::rb_io_enc_t::enc
rb_encoding * enc
Definition: io.h:81
rb_lastline_get
VALUE rb_lastline_get(void)
Definition: vm.c:959
rb_to_encoding_index
int rb_to_encoding_index(VALUE enc)
Definition: encoding.c:171
rb_default_external_encoding
rb_encoding * rb_default_external_encoding(void)
Definition: encoding.c:1351
rb_str_setter
void rb_str_setter(VALUE, ID, VALUE *)
Definition: string.c:7875
io_internal_read_struct::fd
int fd
Definition: io.c:912
rb_maygvl_fd_fix_cloexec
void rb_maygvl_fd_fix_cloexec(int fd)
Definition: io.c:198
copy_stream_fallback_body
static VALUE copy_stream_fallback_body(VALUE arg)
Definition: io.c:10221
rb_thread_sleep
void rb_thread_sleep(int)
Definition: thread.c:1164
rb_fdset_t
fd_set rb_fdset_t
Definition: intern.h:348
copy_stream_struct::src_offset
off_t src_offset
Definition: io.c:9813
rb_fd_term
#define rb_fd_term(f)
Definition: intern.h:359
thread.h
io_internal_write_struct::fd
int fd
Definition: io.c:918
rb_class_new_instance
VALUE rb_class_new_instance(int, VALUE *, VALUE)
Definition: object.c:1855
rb_execarg_get
struct rb_execarg * rb_execarg_get(VALUE execarg_obj)
Definition: process.c:2272
ECONV_NEWLINE_DECORATOR_READ_MASK
#define ECONV_NEWLINE_DECORATOR_READ_MASK
Definition: encoding.h:329
orig_stdout
static VALUE orig_stdout
Definition: io.c:151
bufread_arg::len
long len
Definition: io.c:2065
io_internal_write_struct
Definition: io.c:917
rb_class_name
VALUE rb_class_name(VALUE)
Definition: variable.c:391
argf_lines
static VALUE argf_lines(int argc, VALUE *argv, VALUE argf)
Definition: io.c:11219
nogvl_close
static void * nogvl_close(void *ptr)
Definition: io.c:4115
ALLOC_N
#define ALLOC_N(type, n)
Definition: ruby.h:1333
io_internal_write_struct::buf
const void * buf
Definition: io.c:919
rb_block_given_p
int rb_block_given_p(void)
Definition: eval.c:712
rb_hash_aset
VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val)
Definition: hash.c:1393
rb_io_unbuffered
void rb_io_unbuffered(rb_io_t *fptr)
Definition: io.c:5645
ruby_atomic.h
rb_write_error2
void rb_write_error2(const char *mesg, long len)
Definition: io.c:7143
argf_internal_encoding
static VALUE argf_internal_encoding(VALUE argf)
Definition: io.c:10607
econv_invalid_byte_sequence
Definition: encoding.h:253
Init_File
void Init_File(void)
Definition: file.c:5614
rb_str_encode_ospath
VALUE rb_str_encode_ospath(VALUE path)
Definition: file.c:231
F_SETFL
#define F_SETFL
Definition: win32.h:622
rb_str_substr
VALUE rb_str_substr(VALUE, long, long)
Definition: string.c:1945
write_arg::nosync
int nosync
Definition: io.c:1203
val
#define val
io_readpartial
static VALUE io_readpartial(int argc, VALUE *argv, VALUE io)
Definition: io.c:2531
argf_getbyte
static VALUE argf_getbyte(VALUE argf)
Definition: io.c:11060
stdout_setter
static void stdout_setter(VALUE val, ID id, VALUE *variable)
Definition: io.c:7190
timeval::tv_usec
long tv_usec
Definition: ossl_asn1.c:18
rb_stdout
VALUE rb_stdout
Definition: io.c:149
rb_cObject
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:1553
rb_f_backquote
static VALUE rb_f_backquote(VALUE obj, VALUE str)
Definition: io.c:8168
rb_eRuntimeError
VALUE rb_eRuntimeError
Definition: error.c:547
PREP_STDIO_NAME
#define PREP_STDIO_NAME(f)
Definition: io.c:4037
pipe_list
static struct pipe_list * pipe_list
argf_block_call_i
static VALUE argf_block_call_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, argf))
Definition: io.c:11155
argf_readlines
static VALUE argf_readlines(int, VALUE *, VALUE)
Definition: io.c:8130
argf_getline
static VALUE argf_getline(int argc, VALUE *argv, VALUE argf)
Definition: io.c:7898
FMODE_SETENC_BY_BOM
#define FMODE_SETENC_BY_BOM
Definition: io.h:116
rb_eEWOULDBLOCKWaitWritable
static VALUE rb_eEWOULDBLOCKWaitWritable
Definition: io.c:145
rb_deferr
VALUE rb_deferr
Definition: io.c:150
copy_stream_struct::close_dst
int close_dst
Definition: io.c:9818
MBCLEN_NEEDMORE_P
#define MBCLEN_NEEDMORE_P(ret)
Definition: encoding.h:142
RSTRING_END
#define RSTRING_END(str)
Definition: ruby.h:849
rb_io_s_binread
static VALUE rb_io_s_binread(int argc, VALUE *argv, VALUE io)
Definition: io.c:9677
ruby_strdup
char * ruby_strdup(const char *)
Definition: util.c:457
io_flush_buffer_sync
static VALUE io_flush_buffer_sync(void *arg)
Definition: io.c:990
rb_io_stdio_file
FILE * rb_io_stdio_file(rb_io_t *fptr)
Definition: io.c:7247
rb_io_oflags_fmode
int rb_io_oflags_fmode(int oflags)
Definition: io.c:4861
RB_IO_WAIT_WRITABLE
#define RB_IO_WAIT_WRITABLE
Definition: ruby.h:1508
io_strip_bom
static int io_strip_bom(VALUE io)
Definition: io.c:5422
copy_stream_struct::src
VALUE src
Definition: io.c:9810
rb_str_cat2
VALUE rb_str_cat2(VALUE, const char *)
Definition: string.c:2159
rb_obj_as_string
VALUE rb_obj_as_string(VALUE)
Definition: string.c:1011
io_s_readlines
static VALUE io_s_readlines(struct foreach_arg *arg)
Definition: io.c:9546
ECONV_STATEFUL_DECORATOR_MASK
#define ECONV_STATEFUL_DECORATOR_MASK
Definition: encoding.h:338
writable
static struct StringIO * writable(VALUE strio)
Definition: stringio.c:136
maygvl_copy_stream_read
static ssize_t maygvl_copy_stream_read(int has_gvl, struct copy_stream_struct *stp, char *buf, size_t len, off_t offset)
Definition: io.c:10073
rb_ary_new
VALUE rb_ary_new(void)
Definition: array.c:495
dp
#define dp(v)
Definition: vm_debug.h:21
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:2578
UINT2NUM
#define UINT2NUM(x)
Definition: ruby.h:1298
rb_io_get_write_io
VALUE rb_io_get_write_io(VALUE io)
Definition: io.c:639
rb_execarg_extract_options
VALUE rb_execarg_extract_options(VALUE execarg_obj, VALUE opthash)
Definition: process.c:1959
swallow
static int swallow(rb_io_t *fptr, int term)
Definition: io.c:2926
argf_set_encoding
static VALUE argf_set_encoding(int argc, VALUE *argv, VALUE argf)
Definition: io.c:10647
ARGF_GENERIC_INPUT_P
#define ARGF_GENERIC_INPUT_P()
Definition: io.c:7708
ECONV_PARTIAL_INPUT
#define ECONV_PARTIAL_INPUT
Definition: encoding.h:350
copy_stream_struct::dst
VALUE dst
Definition: io.c:9811
rb_io_ungetbyte
VALUE rb_io_ungetbyte(VALUE io, VALUE b)
Definition: io.c:3833
ECONV_AFTER_OUTPUT
#define ECONV_AFTER_OUTPUT
Definition: encoding.h:351
rb_mKernel
RUBY_EXTERN VALUE rb_mKernel
Definition: ruby.h:1541
rb_thread_current
VALUE rb_thread_current(void)
Definition: thread.c:2401
rb_cloexec_fcntl_dupfd
int rb_cloexec_fcntl_dupfd(int fd, int minfd)
Definition: io.c:323
pipe_finalize
static void pipe_finalize(rb_io_t *fptr, int noraise)
Definition: io.c:5620
NIL_P
#define NIL_P(v)
Definition: ruby.h:438
copy_stream_fallback
static VALUE copy_stream_fallback(struct copy_stream_struct *stp)
Definition: io.c:10279
ISASCII
#define ISASCII(c)
Definition: ruby.h:1766
rb_io_flush
VALUE rb_io_flush(VALUE io)
Definition: io.c:1510
sym_textmode
static VALUE sym_textmode
Definition: io.c:162
finish_writeconv_sync
static VALUE finish_writeconv_sync(VALUE arg)
Definition: io.c:4108
io_write
static VALUE io_write(VALUE io, VALUE str, int nosync)
Definition: io.c:1375
rb_f_puts
static VALUE rb_f_puts(int argc, VALUE *argv, VALUE recv)
Definition: io.c:7023
rb_define_class
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition: class.c:630
pipe_pair_close
static VALUE pipe_pair_close(VALUE rw)
Definition: io.c:9318
ruby_get_inplace_mode
const char * ruby_get_inplace_mode(void)
Definition: io.c:11600
appendline
static int appendline(rb_io_t *fptr, int delim, VALUE *strp, long *lp)
Definition: io.c:2844
chown
int chown(const char *, int, int)
Definition: win32.c:4425
ECONV_DEFAULT_NEWLINE_DECORATOR
#define ECONV_DEFAULT_NEWLINE_DECORATOR
Definition: encoding.h:344
rb_io_t::fd
int fd
Definition: io.h:62
rb_mutex_synchronize
VALUE rb_mutex_synchronize(VALUE mutex, VALUE(*func)(VALUE arg), VALUE arg)
Definition: thread.c:4619
rb_io_each_line
static VALUE rb_io_each_line(int argc, VALUE *argv, VALUE io)
Definition: io.c:3369
MODE_BINARY
#define MODE_BINARY(a, b)
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)
rb_define_const
void rb_define_const(VALUE, const char *, VALUE)
Definition: variable.c:2225
unistd.h
rb_io_wait_readable
int rb_io_wait_readable(int f)
Definition: io.c:1077
argf::next_p
int8_t next_p
Definition: io.c:178
rb_sys_fail_str
void rb_sys_fail_str(VALUE mesg)
Definition: error.c:1982
select_internal
static VALUE select_internal(VALUE read, VALUE write, VALUE except, struct timeval *tp, rb_fdset_t *fds)
Definition: io.c:8191
cnt
rb_atomic_t cnt[RUBY_NSIG]
Definition: signal.c:496
rb_io_each_char
static VALUE rb_io_each_char(VALUE io)
Definition: io.c:3571
rb_io_open_with_args
static VALUE rb_io_open_with_args(int argc, const VALUE *argv)
Definition: io.c:6503
rb_io_check_io
VALUE rb_io_check_io(VALUE io)
Definition: io.c:633
rb_lastline_set
void rb_lastline_set(VALUE)
Definition: vm.c:965
argf_chars
static VALUE argf_chars(VALUE argf)
Definition: io.c:11305
rb_io_getline
static VALUE rb_io_getline(int argc, VALUE *argv, VALUE io)
Definition: io.c:3177
write_arg::str
VALUE str
Definition: io.c:1202
rb_io_fdatasync
#define rb_io_fdatasync
Definition: io.c:1901
rb_io_t::encs
struct rb_io_t::rb_io_enc_t encs
Init_IO
void Init_IO(void)
Definition: io.c:11874
nogvl_fclose
static void * nogvl_fclose(void *ptr)
Definition: io.c:4136
TYPE
#define TYPE(x)
Definition: ruby.h:505
NUM2IOCTLREQ
#define NUM2IOCTLREQ(num)
Definition: io.c:8683
argc
int argc
Definition: ruby.c:131
READ_DATA_PENDING
#define READ_DATA_PENDING(fptr)
Definition: io.c:386
rb_io_t::writeconv_asciicompat
VALUE writeconv_asciicompat
Definition: io.h:91
FMODE_TRUNC
#define FMODE_TRUNC
Definition: io.h:113
finish_writeconv
static VALUE finish_writeconv(rb_io_t *fptr, int noalloc)
Definition: io.c:4040
Qfalse
#define Qfalse
Definition: ruby.h:425
copy_stream_struct::notimp
const char * notimp
Definition: io.c:9822
rb_open_file
static VALUE rb_open_file(int argc, const VALUE *argv, VALUE io)
Definition: io.c:6232
rb_io_t::pid
rb_pid_t pid
Definition: io.h:65
T_BIGNUM
#define T_BIGNUM
Definition: ruby.h:487
LONG_MAX
#define LONG_MAX
Definition: ruby.h:191
NEED_NEWLINE_DECORATOR_ON_READ_CHECK
#define NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr)
Definition: io.c:569
rb_gc_register_mark_object
void rb_gc_register_mark_object(VALUE obj)
Definition: gc.c:4920
rb_io_gets_m
static VALUE rb_io_gets_m(int argc, VALUE *argv, VALUE io)
Definition: io.c:3214
if
if((ID)(DISPID) nameid!=nameid)
Definition: win32ole.c:770
rb_io_get_io
VALUE rb_io_get_io(VALUE io)
Definition: io.c:627
RUBY_FUNC_EXPORTED
#define RUBY_FUNC_EXPORTED
Definition: defines.h:246
argf_eof
static VALUE argf_eof(VALUE argf)
Definition: io.c:10801
rb_io_buffer_t::len
int len
Definition: io.h:57
ENC_CODERANGE_BROKEN
#define ENC_CODERANGE_BROKEN
Definition: encoding.h:51
rb_ary_new4
#define rb_ary_new4
Definition: intern.h:92
io_setstrbuf
static void io_setstrbuf(VALUE *str, long len)
Definition: io.c:2283
rb_str_new2
#define rb_str_new2
Definition: intern.h:840
rb_obj_alloc
VALUE rb_obj_alloc(VALUE)
Definition: object.c:1801
ARGF
#define ARGF
Definition: io.c:366
err
int err
Definition: win32.c:114
io_flush_buffer
static int io_flush_buffer(rb_io_t *fptr)
Definition: io.c:1048
rb_enc_codepoint
#define rb_enc_codepoint(p, e, enc)
Definition: encoding.h:155
OBJ_FREEZE
#define OBJ_FREEZE(x)
Definition: ruby.h:1186
argf_of
#define argf_of(obj)
Definition: io.c:365
rb_enc_mbminlen
#define rb_enc_mbminlen(enc)
Definition: encoding.h:128
write_arg
Definition: io.c:1200
rb_io_gets
VALUE rb_io_gets(VALUE io)
Definition: io.c:3187
rb_cloexec_dup
int rb_cloexec_dup(int oldfd)
Definition: io.c:244
rb_f_printf
static VALUE rb_f_printf(int argc, VALUE *argv)
Definition: io.c:6777
rscheck
static void rscheck(const char *rsptr, long rslen, VALUE rs)
Definition: io.c:2836
rb_f_p_arg::argv
VALUE * argv
Definition: io.c:7048
nogvl_copy_stream_write
static int nogvl_copy_stream_write(struct copy_stream_struct *stp, char *buf, size_t len)
Definition: io.c:10116
argf_initialize
static VALUE argf_initialize(VALUE argf, VALUE argv)
Definition: io.c:7633
rb_f_syscall
#define rb_f_syscall
Definition: io.c:9237
rb_thread_call_without_gvl
void * rb_thread_call_without_gvl(void *(*func)(void *), void *data1, rb_unblock_function_t *ubf, void *data2)
ENC_CODERANGE_VALID
#define ENC_CODERANGE_VALID
Definition: encoding.h:50
bufread_arg
Definition: io.c:2063
ATOMIC_CAS
#define ATOMIC_CAS(var, oldval, newval)
Definition: ruby_atomic.h:132
rb_io_seek_m
static VALUE rb_io_seek_m(int argc, VALUE *argv, VALUE io)
Definition: io.c:1597
numberof
#define numberof(array)
Definition: etc.c:595
ALLOC
#define ALLOC(type)
Definition: ruby.h:1334
ioctl_arg::fd
int fd
Definition: io.c:8687
EOF
#define EOF
Definition: vsnprintf.c:207
copy_stream_struct::src_fd
int src_fd
Definition: io.c:9815
select_args::read
VALUE read
Definition: io.c:8316
rb_str_resize
VALUE rb_str_resize(VALUE, long)
Definition: string.c:2025
io_set_encoding_by_bom
static void io_set_encoding_by_bom(VALUE io)
Definition: io.c:5485
DEFAULT_TEXTMODE
#define DEFAULT_TEXTMODE
Definition: io.c:565
advice_arg_check
static void advice_arg_check(VALUE advice)
Definition: io.c:8428
NUM2OFFT
#define NUM2OFFT(x)
Definition: ruby.h:672
IO_CBUF_CAPA_MIN
#define IO_CBUF_CAPA_MIN
Definition: io.c:123
rb_find_encoding
rb_encoding * rb_find_encoding(VALUE enc)
Definition: encoding.c:226
rb_enc_ascget
int rb_enc_ascget(const char *p, const char *e, int *len, rb_encoding *enc)
Definition: encoding.c:970
argf_alloc
static VALUE argf_alloc(VALUE klass)
Definition: io.c:7620
io_ascii8bit_binmode
static void io_ascii8bit_binmode(rb_io_t *fptr)
Definition: io.c:4703
NEXT_ARGF_FORWARD
#define NEXT_ARGF_FORWARD(argc, argv)
Definition: io.c:7714
prep_io
static VALUE prep_io(int fd, int fmode, VALUE klass, const char *path)
Definition: io.c:7197
rb_define_alias
void rb_define_alias(VALUE klass, const char *name1, const char *name2)
Defines an alias of a method.
Definition: class.c:1697
rb_cloexec_pipe
int rb_cloexec_pipe(int fildes[2])
Definition: io.c:286
rb_f_gets
static VALUE rb_f_gets(int argc, VALUE *argv, VALUE recv)
Definition: io.c:7979
RSTRING_LEN
#define RSTRING_LEN(str)
Definition: ruby.h:841
rb_get_argv
VALUE rb_get_argv(void)
Definition: io.c:11640
rb_yield
VALUE rb_yield(VALUE)
Definition: vm_eval.c:942
ruby_set_inplace_mode
void ruby_set_inplace_mode(const char *suffix)
Definition: io.c:11606
rb_io_t::wbuf
rb_io_buffer_t wbuf
Definition: io.h:70
RARRAY_CONST_PTR
#define RARRAY_CONST_PTR(a)
Definition: ruby.h:886
rb_define_readonly_variable
void rb_define_readonly_variable(const char *, VALUE *)
Definition: variable.c:610
timeval
Definition: ossl_asn1.c:16
errno
int errno
util.h
copy_stream_body
static VALUE copy_stream_body(VALUE arg)
Definition: io.c:10291
TRUE
#define TRUE
Definition: nkf.h:175
off_t
#define off_t
Definition: io.c:65
seek_before_access
static VALUE seek_before_access(VALUE argp)
Definition: io.c:9594
S_ISREG
#define S_ISREG(m)
Definition: io.c:885
rb_io_set_pos
static VALUE rb_io_set_pos(VALUE io, VALUE offset)
Definition: io.c:1623
rb_last_status_clear
void rb_last_status_clear(void)
Definition: process.c:336
max_file_descriptor
static rb_atomic_t max_file_descriptor
Definition: io.c:181
rb_io_init_copy
static VALUE rb_io_init_copy(VALUE dest, VALUE io)
Definition: io.c:6704
rb_mEnumerable
VALUE rb_mEnumerable
Definition: enum.c:20
rb_sprintf
VALUE rb_sprintf(const char *format,...)
Definition: sprintf.c:1250
binwrite_arg::fptr
rb_io_t * fptr
Definition: io.c:1194
nogvl_copy_stream_read_write
static void nogvl_copy_stream_read_write(struct copy_stream_struct *stp)
Definition: io.c:10142
io_input_encoding
static rb_encoding * io_input_encoding(rb_io_t *fptr)
Definition: io.c:809
io_close
static VALUE io_close(VALUE io)
Definition: io.c:4367
pipe_list
Definition: io.c:5567
rb_sysopen
static int rb_sysopen(VALUE fname, int oflags, mode_t perm)
Definition: io.c:5350
rb_enc_precise_mbclen
int rb_enc_precise_mbclen(const char *p, const char *e, rb_encoding *enc)
Definition: encoding.c:958
IO_RBUF_CAPA_FOR
#define IO_RBUF_CAPA_FOR(fptr)
Definition: io.c:124
rb_execarg_fixup
void rb_execarg_fixup(VALUE execarg_obj)
Definition: process.c:2325
argf_rewind
static VALUE argf_rewind(VALUE argf)
Definition: io.c:10733
NEED_READCONV
#define NEED_READCONV(fptr)
Definition: io.c:566
rb_io_pid
static VALUE rb_io_pid(VALUE io)
Definition: io.c:1949
rb_eEINPROGRESSWaitReadable
static VALUE rb_eEINPROGRESSWaitReadable
Definition: io.c:147
rb_fatal
void rb_fatal(const char *fmt,...)
Definition: error.c:1911
io_s_read
static VALUE io_s_read(struct foreach_arg *arg)
Definition: io.c:9582
rb_enc_name
#define rb_enc_name(enc)
Definition: encoding.h:125
rb_eSystemCallError
VALUE rb_eSystemCallError
Definition: error.c:566
afd
Definition: getaddrinfo.c:115
io_flush_buffer_sync2
static void * io_flush_buffer_sync2(void *arg)
Definition: io.c:1010
maygvl_copy_stream_continue_p
static int maygvl_copy_stream_continue_p(int has_gvl, struct copy_stream_struct *stp)
Definition: io.c:9841
rb_last_status_set
void rb_last_status_set(int status, rb_pid_t pid)
Definition: process.c:327
rb_io_readlines
static VALUE rb_io_readlines(int argc, VALUE *argv, VALUE io)
Definition: io.c:3324
rb_io_s_for_fd
static VALUE rb_io_s_for_fd(int argc, VALUE *argv, VALUE klass)
Definition: io.c:7524
argf::encs
struct rb_io_enc_t encs
Definition: io.c:177
rb_f_select
static VALUE rb_f_select(int argc, VALUE *argv, VALUE obj)
Definition: io.c:8656
rb_io_chars
static VALUE rb_io_chars(VALUE io)
Definition: io.c:3594
MEMMOVE
#define MEMMOVE(p1, p2, type, n)
Definition: ruby.h:1353
rb_hash_new
VALUE rb_hash_new(void)
Definition: hash.c:298
wsplit_p
static int wsplit_p(rb_io_t *fptr)
Definition: io.c:889
rb_io_s_open
static VALUE rb_io_s_open(int argc, VALUE *argv, VALUE klass)
Definition: io.c:6283
NUM2CHR
#define NUM2CHR(x)
Definition: ruby.h:1329
rb_f_print
static VALUE rb_f_print(int argc, VALUE *argv)
Definition: io.c:6866
argf_lineno_setter
static void argf_lineno_setter(VALUE val, ID id, VALUE *var)
Definition: io.c:7936
strdup
#define strdup(s)
Definition: util.h:67
rb_scan_args
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:1728
argf_read_nonblock
static VALUE argf_read_nonblock(int argc, VALUE *argv, VALUE argf)
Definition: io.c:10950
rb_write_error_str
void rb_write_error_str(VALUE mesg)
Definition: io.c:7163
rb_str_modify_expand
void rb_str_modify_expand(VALUE, long)
Definition: string.c:1492
argf_to_io
static VALUE argf_to_io(VALUE argf)
Definition: io.c:10775
rb_thread_execute_interrupts
void rb_thread_execute_interrupts(VALUE th)
Definition: thread.c:2026
rb_ivar_set
VALUE rb_ivar_set(VALUE, ID, VALUE)
Definition: variable.c:1133
RFile
Definition: ruby.h:934
rb_check_hash_type
VALUE rb_check_hash_type(VALUE hash)
Definition: hash.c:588
io_unread
static void io_unread(rb_io_t *fptr)
Definition: io.c:691
buf
unsigned char buf[MIME_BUF_SIZE]
Definition: nkf.c:4308
rb_assoc_new
VALUE rb_assoc_new(VALUE car, VALUE cdr)
Definition: array.c:616
PRIsVALUE
#define PRIsVALUE
Definition: ruby.h:137
internal.h
ID
unsigned long ID
Definition: ruby.h:89
rb_execarg
Definition: internal.h:636
FMODE_WSPLIT
#define FMODE_WSPLIT
Definition: io.h:111
rb_thread_wait_fd
void rb_thread_wait_fd(int)
Definition: thread.c:3519
rb_io_t::tied_io_for_writing
VALUE tied_io_for_writing
Definition: io.h:72
RUBY_METHOD_FUNC
#define RUBY_METHOD_FUNC(func)
Definition: ruby.h:1399
rb_io_close_m
static VALUE rb_io_close_m(VALUE io)
Definition: io.c:4339
argf_lineno_getter
static VALUE argf_lineno_getter(ID id, VALUE *var)
Definition: io.c:7929
rb_write_internal
static ssize_t rb_write_internal(int fd, const void *buf, size_t count)
Definition: io.c:956
Qnil
#define Qnil
Definition: ruby.h:427
argf::init_p
int8_t init_p
Definition: io.c:178
FMODE_TEXTMODE
#define FMODE_TEXTMODE
Definition: io.h:114
rb_io_extract_modeenc
static 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:5199
rb_enc_uint_chr
VALUE rb_enc_uint_chr(unsigned int code, rb_encoding *enc)
Definition: numeric.c:2514
EWOULDBLOCK
#define EWOULDBLOCK
Definition: io.c:114
mode_t
#define mode_t
Definition: win32.h:116
ONIGENC_CONSTRUCT_MBCLEN_CHARFOUND
#define ONIGENC_CONSTRUCT_MBCLEN_CHARFOUND(n)
Definition: oniguruma.h:245
OBJ_TAINT
#define OBJ_TAINT(x)
Definition: ruby.h:1177
VALUE
unsigned long VALUE
Definition: ruby.h:88
argf_readline
static VALUE argf_readline(int, VALUE *, VALUE)
Definition: io.c:8078
IS_PREP_STDIO
#define IS_PREP_STDIO(f)
Definition: io.c:4036
rb_funcall2
#define rb_funcall2
Definition: ruby.h:1456
rb_io_s_binwrite
static VALUE rb_io_s_binwrite(int argc, VALUE *argv, VALUE io)
Definition: io.c:9804
result
static VALUE result
Definition: nkf.c:40
rb_gets
VALUE rb_gets(void)
Definition: io.c:8014
rb_readwrite_sys_fail
void rb_readwrite_sys_fail(int writable, const char *mesg)
Definition: io.c:11674
rb_class2name
const char * rb_class2name(VALUE)
Definition: variable.c:397
strchr
char * strchr(char *, char)
RB_IO_WAIT_READABLE
#define RB_IO_WAIT_READABLE
Definition: ruby.h:1507
intptr_t
int intptr_t
Definition: win32.h:87
prep_stdio
static VALUE prep_stdio(FILE *f, int fmode, VALUE klass, const char *path)
Definition: io.c:7228
NEED_NEWLINE_DECORATOR_ON_WRITE
#define NEED_NEWLINE_DECORATOR_ON_WRITE(fptr)
Definition: io.c:427
read_internal_arg::str_ptr
char * str_ptr
Definition: io.c:2402
FIX2INT
#define FIX2INT(x)
Definition: ruby.h:632
internal_write_func2
static void * internal_write_func2(void *ptr)
Definition: io.c:938
ECONV_NEWLINE_DECORATOR_MASK
#define ECONV_NEWLINE_DECORATOR_MASK
Definition: encoding.h:328
rb_rs
VALUE rb_rs
Definition: io.c:154
rb_io_synchronized
void rb_io_synchronized(rb_io_t *fptr)
Definition: io.c:5638
rb_rescue2
VALUE rb_rescue2(VALUE(*b_proc)(ANYARGS), VALUE data1, VALUE(*r_proc)(ANYARGS), VALUE data2,...)
Definition: eval.c:741
rb_check_funcall
VALUE rb_check_funcall(VALUE, ID, int, const VALUE *)
Definition: vm_eval.c:409
rb_io_s_write
static VALUE rb_io_s_write(int argc, VALUE *argv, VALUE io)
Definition: io.c:9788
io_bufread
static long io_bufread(char *ptr, long len, rb_io_t *fptr)
Definition: io.c:2025
copy_stream_struct::fds
rb_fdset_t fds
Definition: io.c:9823
rb_enc_asciicompat
#define rb_enc_asciicompat(enc)
Definition: encoding.h:188
rb_ensure
VALUE rb_ensure(VALUE(*b_proc)(ANYARGS), VALUE data1, VALUE(*e_proc)(ANYARGS), VALUE data2)
Definition: eval.c:839
rb_str_new_cstr
VALUE rb_str_new_cstr(const char *)
Definition: string.c:560
memcmp
int memcmp(const void *s1, const void *s2, size_t len)
Definition: memcmp.c:7
argf_read
static VALUE argf_read(int argc, VALUE *argv, VALUE argf)
Definition: io.c:10855
maygvl_select
static int maygvl_select(int has_gvl, int n, rb_fdset_t *rfds, rb_fdset_t *wfds, rb_fdset_t *efds, struct timeval *timeout)
Definition: io.c:9860
maygvl_copy_stream_wait_read
static int maygvl_copy_stream_wait_read(int has_gvl, struct copy_stream_struct *stp)
Definition: io.c:9869
do_writeconv
static VALUE do_writeconv(VALUE str, rb_io_t *fptr)
Definition: io.c:1296
io_shift_cbuf
static VALUE io_shift_cbuf(rb_io_t *fptr, int len, VALUE *strp)
Definition: io.c:2256
rb_uninterruptible
VALUE rb_uninterruptible(VALUE(*b_proc)(ANYARGS), VALUE data)
Definition: thread.c:5307
rb_sys_fail
void rb_sys_fail(const char *mesg)
Definition: error.c:1976
read_internal_call
static VALUE read_internal_call(VALUE arg)
Definition: io.c:2407
sym_willneed
static VALUE sym_willneed
Definition: io.c:8340
rb_io_autoclose_p
static VALUE rb_io_autoclose_p(VALUE io)
Definition: io.c:7540
io_write_m
static VALUE io_write_m(VALUE io, VALUE str)
Definition: io.c:1421
rb_jump_tag
void rb_jump_tag(int tag)
Definition: eval.c:706
read_internal_arg::fd
int fd
Definition: io.c:2401
rb_io_set_encoding
static VALUE rb_io_set_encoding(int argc, VALUE *argv, VALUE io)
Definition: io.c:10542
rb_reserved_fd_p
int rb_reserved_fd_p(int fd)
econv_finished
Definition: encoding.h:257
rb_define_hooked_variable
void rb_define_hooked_variable(const char *, VALUE *, VALUE(*)(ANYARGS), void(*)(ANYARGS))
Definition: variable.c:585
READ_DATA_BUFFERED
#define READ_DATA_BUFFERED(fptr)
Definition: io.c:389
rb_io_close_on_exec_p
#define rb_io_close_on_exec_p
Definition: io.c:3974
io_internal_read_struct
Definition: io.c:911
rb_respond_to
int rb_respond_to(VALUE, ID)
Definition: vm_method.c:1639
select_args::timeout
struct timeval * timeout
Definition: io.c:8317
bufread_call
static VALUE bufread_call(VALUE arg)
Definition: io.c:2070
rb_define_module_under
VALUE rb_define_module_under(VALUE outer, const char *name)
Definition: class.c:766
StringValueCStr
#define StringValueCStr(v)
Definition: ruby.h:541
rb_io_t::readconv
rb_econv_t * readconv
Definition: io.h:87
argf_tell
static VALUE argf_tell(VALUE argf)
Definition: io.c:10673
shutdown
#define shutdown(a, b)
Definition: io.c:575
rb_fd_max
#define rb_fd_max(f)
Definition: intern.h:360
argf_each_byte
static VALUE argf_each_byte(VALUE argf)
Definition: io.c:11252
argf_memsize
static size_t argf_memsize(const void *ptr)
Definition: io.c:7595
SEEK_END
#define SEEK_END
Definition: io.c:762
rb_iter_break_value
void rb_iter_break_value(VALUE val)
Definition: vm.c:1160
do_ioctl
static int do_ioctl(int fd, ioctl_req_t cmd, long narg)
Definition: io.c:8701
recur
#define recur(fmt)
Definition: date_strptime.c:147
foreach_arg::argc
int argc
Definition: io.c:9452
rb_econv_putbackable
int rb_econv_putbackable(rb_econv_t *ec)
Definition: transcode.c:1742
RSTRING_PTR
#define RSTRING_PTR(str)
Definition: ruby.h:845
argf_codepoints
static VALUE argf_codepoints(VALUE argf)
Definition: io.c:11344
sym_extenc
static VALUE sym_extenc
Definition: io.c:161
rb_io_t::write_lock
VALUE write_lock
Definition: io.h:96
pipe_list::next
struct pipe_list * next
Definition: io.c:5569
rb_exc_new3
#define rb_exc_new3
Definition: intern.h:248
argf_filename_getter
static VALUE argf_filename_getter(ID id, VALUE *var)
Definition: io.c:11382
rb_io_binmode_m
static VALUE rb_io_binmode_m(VALUE io)
Definition: io.c:4749
rb_str_modify
void rb_str_modify(VALUE)
Definition: string.c:1484
sym_perm
static VALUE sym_perm
Definition: io.c:161
rb_io_isatty
static VALUE rb_io_isatty(VALUE io)
Definition: io.c:3925
ENCODING_GET
#define ENCODING_GET(obj)
Definition: encoding.h:38
rb_enc_get
rb_encoding * rb_enc_get(VALUE obj)
Definition: encoding.c:832
io_getpartial
static VALUE io_getpartial(int argc, VALUE *argv, VALUE io, int nonblock, int no_exception)
Definition: io.c:2415
write_arg::io
VALUE io
Definition: io.c:1201
io_s_write0
static VALUE io_s_write0(struct write_arg *arg)
Definition: io.c:9695
rb_mod_sys_fail_str
void rb_mod_sys_fail_str(VALUE mod, VALUE mesg)
Definition: error.c:2024
rb_execarg::cmd
struct rb_execarg::@123::@125 cmd
rb_insecure_operation
void rb_insecure_operation(void)
Definition: safe.c:109
io_flush_buffer_async2
static VALUE io_flush_buffer_async2(VALUE arg)
Definition: io.c:1029
rb_io_lineno
static VALUE rb_io_lineno(VALUE io)
Definition: io.c:3247
io_writable_length
static long io_writable_length(rb_io_t *fptr, long l)
Definition: io.c:979
io_read
static VALUE io_read(int argc, VALUE *argv, VALUE io)
Definition: io.c:2788
size
int size
Definition: encoding.c:49
rb_funcallv
VALUE rb_funcallv(VALUE, ID, int, const VALUE *)
Calls a method.
Definition: vm_eval.c:806
rb_yield_values2
VALUE rb_yield_values2(int n, const VALUE *argv)
Definition: vm_eval.c:975
f
#define f
rb_hash_lookup2
VALUE rb_hash_lookup2(VALUE hash, VALUE key, VALUE def)
Definition: hash.c:708
INT2FIX
#define INT2FIX(i)
Definition: ruby.h:231
pipe_atexit
static void pipe_atexit(void)
Definition: io.c:5607
io_new_instance
static VALUE io_new_instance(VALUE args)
Definition: io.c:9241
rb_econv_t
Definition: transcode.c:111
rb_io_putc
static VALUE rb_io_putc(VALUE io, VALUE ch)
Definition: io.c:6891
rb_io_bytes
static VALUE rb_io_bytes(VALUE io)
Definition: io.c:3440
MBCLEN_INVALID_P
#define MBCLEN_INVALID_P(ret)
Definition: encoding.h:141
RARRAY_AREF
#define RARRAY_AREF(a, i)
Definition: ruby.h:901
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:1446
rb_check_convert_type
VALUE rb_check_convert_type(VALUE, int, const char *, const char *)
Definition: object.c:2631
io_fread
static long io_fread(VALUE str, long offset, long size, rb_io_t *fptr)
Definition: io.c:2078
rb_io_fmode_oflags
static int rb_io_fmode_oflags(int fmode)
Definition: io.c:4896
check_pipe_command
static VALUE check_pipe_command(VALUE filename_or_command)
Definition: io.c:6332
rb_io_fptr_finalize
int rb_io_fptr_finalize(rb_io_t *fptr)
Definition: io.c:4257
rb_mWaitReadable
VALUE rb_mWaitReadable
Definition: io.c:136
foreach_arg::io
VALUE io
Definition: io.c:9454
rb_io_s_pipe
static VALUE rb_io_s_pipe(int argc, VALUE *argv, VALUE klass)
Definition: io.c:9385
rb_io_fdopen
VALUE rb_io_fdopen(int fd, int oflags, const char *path)
Definition: io.c:7219
rb_str_buf_cat_ascii
VALUE rb_str_buf_cat_ascii(VALUE, const char *)
Definition: string.c:2258
rb_eEAGAIN
VALUE rb_eEAGAIN
Definition: error.c:40
rb_io_to_io
static VALUE rb_io_to_io(VALUE io)
Definition: io.c:2004
rb_eIOError
VALUE rb_eIOError
Definition: io.c:135
rb_execarg::sh
struct rb_execarg::@123::@124 sh
rb_io_inspect
static VALUE rb_io_inspect(VALUE obj)
Definition: io.c:1968
rb_io_buffer_t::off
int off
Definition: io.h:56
rb_scan_open_args
static void rb_scan_open_args(int argc, const VALUE *argv, VALUE *fname_p, int *oflags_p, int *fmode_p, convconfig_t *convconfig_p, mode_t *perm_p)
Definition: io.c:6210
sym_intenc
static VALUE sym_intenc
Definition: io.c:161
rb_intern
#define rb_intern(str)
ANYARGS
#define ANYARGS
Definition: defines.h:98
rb_data_type_struct
Definition: ruby.h:966
rb_io_s_try_convert
static VALUE rb_io_s_try_convert(VALUE dummy, VALUE io)
Definition: io.c:684
rb_check_array_type
VALUE rb_check_array_type(VALUE ary)
Definition: array.c:628
rb_thread_call_with_gvl
RUBY_SYMBOL_EXPORT_BEGIN void * rb_thread_call_with_gvl(void *(*func)(void *), void *data1)
Definition: thread.c:1450
clear_codeconv
static void clear_codeconv(rb_io_t *fptr)
Definition: io.c:4250
rb_hash_aref
VALUE rb_hash_aref(VALUE hash, VALUE key)
Definition: hash.c:697
rb_io_fptr_cleanup
static void rb_io_fptr_cleanup(rb_io_t *fptr, int noraise)
Definition: io.c:4216
rb_error_arity
void rb_error_arity(int argc, int min, int max)
Definition: vm_insnhelper.c:149
RARRAY_PTR
#define RARRAY_PTR(a)
Definition: ruby.h:907
rb_fd_select
#define rb_fd_select(n, rfds, wfds, efds, timeout)
Definition: intern.h:361
parse_mode_enc
static void parse_mode_enc(const char *estr, rb_encoding **enc_p, rb_encoding **enc2_p, int *fmode_p)
Definition: io.c:5005
rb_str_catf
VALUE rb_str_catf(VALUE str, const char *format,...)
Definition: sprintf.c:1290
rb_syserr_fail_str
void rb_syserr_fail_str(int e, VALUE mesg)
Definition: error.c:1970
finish_writeconv_arg::noalloc
int noalloc
Definition: io.c:4104
rb_w32_write_console
long rb_w32_write_console(uintptr_t, int)
Definition: win32.c:6525
rb_eEAGAINWaitReadable
static VALUE rb_eEAGAINWaitReadable
Definition: io.c:142
rb_check_string_type
VALUE rb_check_string_type(VALUE)
Definition: string.c:1679
is_socket
#define is_socket(fd, path)
Definition: io.c:581
rb_funcall3
#define rb_funcall3
Definition: ruby.h:1457
rb_any_to_s
VALUE rb_any_to_s(VALUE)
Definition: object.c:452
rb_gvar_readonly_setter
void rb_gvar_readonly_setter(VALUE val, ID id, void *data, struct rb_global_variable *gvar)
strerror
RUBY_EXTERN char * strerror(int)
Definition: strerror.c:11
argf_each_char
static VALUE argf_each_char(VALUE argf)
Definition: io.c:11291
LONG2FIX
#define LONG2FIX(i)
Definition: ruby.h:232
rb_io_t::pathv
VALUE pathv
Definition: io.h:67
rb_io_advise
static VALUE rb_io_advise(int argc, VALUE *argv, VALUE io)
Definition: io.c:8488
O_NONBLOCK
#define O_NONBLOCK
Definition: win32.h:626
ARGVSTR2ARGV
#define ARGVSTR2ARGV(argv_str)
Definition: internal.h:683
RTEST
#define RTEST(v)
Definition: ruby.h:437
rb_io_getc
static VALUE rb_io_getc(VALUE io)
Definition: io.c:3723
rb_thread_check_ints
void rb_thread_check_ints(void)
Definition: thread.c:1139
T_STRING
#define T_STRING
Definition: ruby.h:482
rb_eEOFError
VALUE rb_eEOFError
Definition: io.c:134
rb_str_locktmp
VALUE rb_str_locktmp(VALUE)
io_binwrite
static long io_binwrite(VALUE str, const char *ptr, long len, rb_io_t *fptr, int nosync)
Definition: io.c:1215
rb_io_t::finalize
void(* finalize)(struct rb_io_t *, int)
Definition: io.h:68
seek_arg::offset
VALUE offset
Definition: io.c:9589
OBJ_INFECT
#define OBJ_INFECT(x, s)
Definition: ruby.h:1180
rb_execarg::use_shell
int use_shell
Definition: internal.h:637
argf_closed
static VALUE argf_closed(VALUE argf)
Definition: io.c:11514
list
struct rb_encoding_entry * list
Definition: encoding.c:47
rb_method_basic_definition_p
int rb_method_basic_definition_p(VALUE, ID)
Definition: vm_method.c:1573
rb_define_variable
void rb_define_variable(const char *, VALUE *)
Definition: variable.c:604
READ_CHECK
#define READ_CHECK(fptr)
Definition: io.c:402
T_FILE
#define T_FILE
Definition: ruby.h:488
rb_io_s_read
static VALUE rb_io_s_read(int argc, VALUE *argv, VALUE io)
Definition: io.c:9638
fsync
#define fsync
Definition: win32.h:222
rb_io_check_readable
void rb_io_check_readable(rb_io_t *fptr)
Definition: io.c:794
rb_fdopen
FILE * rb_fdopen(int fd, const char *modestr)
Definition: io.c:5373
flush_before_seek
static rb_io_t * flush_before_seek(rb_io_t *fptr)
Definition: io.c:747
TypedData_Make_Struct
#define TypedData_Make_Struct(klass, type, data_type, sval)
Definition: ruby.h:1030
rb_enc_left_char_head
#define rb_enc_left_char_head(s, p, e, enc)
Definition: encoding.h:170
rb_ary_dup
VALUE rb_ary_dup(VALUE ary)
Definition: array.c:1888
rb_notimplement
void rb_notimplement(void)
Definition: error.c:1903
rb_io_t::rb_io_enc_t::ecflags
int ecflags
Definition: io.h:83
sym_binmode
static VALUE sym_binmode
Definition: io.c:162
rb_ary_concat
VALUE rb_ary_concat(VALUE x, VALUE y)
Definition: array.c:3542
remain_size
static long remain_size(rb_io_t *fptr)
Definition: io.c:2106
binwrite_arg::length
long length
Definition: io.c:1197
argf_argv_getter
static VALUE argf_argv_getter(ID id, VALUE *var)
Definition: io.c:11634
RETURN_ENUMERATOR
#define RETURN_ENUMERATOR(obj, argc, argv)
Definition: intern.h:242
finish_writeconv_arg::fptr
rb_io_t * fptr
Definition: io.c:4103
SafeStringValue
#define SafeStringValue(v)
Definition: ruby.h:545
rb_ary_join
VALUE rb_ary_join(VALUE ary, VALUE sep)
Definition: array.c:1995
rb_eNotImpError
VALUE rb_eNotImpError
Definition: error.c:558
rb_atomic_t
int rb_atomic_t
Definition: ruby_atomic.h:120
FOREACH_ARGF
#define FOREACH_ARGF()
Definition: io.c:11152
io_reopen
static VALUE io_reopen(VALUE io, VALUE nfile)
Definition: io.c:6513
sysopen_func
static void * sysopen_func(void *ptr)
Definition: io.c:5332
rb_io_readline
static VALUE rb_io_readline(int argc, VALUE *argv, VALUE io)
Definition: io.c:3295
FMODE_PREP
#define FMODE_PREP
Definition: io.c:4035
rb_enc_str_new
VALUE rb_enc_str_new(const char *, long, rb_encoding *)
Definition: string.c:548
rb_eEWOULDBLOCKWaitReadable
static VALUE rb_eEWOULDBLOCKWaitReadable
Definition: io.c:144
rb_safe_level
#define rb_safe_level()
Definition: tcltklib.c:95
rb_sys_fail_path
#define rb_sys_fail_path(path)
Definition: internal.h:450
OFFT2NUM
#define OFFT2NUM(v)
Definition: ruby.h:252
rb_io_addstr
VALUE rb_io_addstr(VALUE io, VALUE str)
Definition: io.c:1449
ioctl.h
ioctl_narg_len
static long ioctl_narg_len(ioctl_req_t cmd)
Definition: io.c:8739
internal_read_func
static VALUE internal_read_func(void *ptr)
Definition: io.c:924
sysopen_struct::oflags
int oflags
Definition: io.c:5327
rb_set_class_path
void rb_set_class_path(VALUE, VALUE, const char *)
Definition: variable.c:316
rb_thread_interrupted
int rb_thread_interrupted(VALUE thval)
Definition: thread.c:1156
rb_io_initialize
static VALUE rb_io_initialize(int argc, VALUE *argv, VALUE io)
Definition: io.c:7403
make_writeconv
static void make_writeconv(rb_io_t *fptr)
Definition: io.c:1138
rb_io_taint_check
VALUE rb_io_taint_check(VALUE io)
Definition: io.c:602
name
const char * name
Definition: nkf.c:208
rb_execarg_addopt
int rb_execarg_addopt(VALUE execarg_obj, VALUE key, VALUE val)
Definition: process.c:1670
ID2SYM
#define ID2SYM(x)
Definition: ruby.h:355
NUM2MODET
#define NUM2MODET(v)
Definition: ruby.h:339
econv_source_buffer_empty
Definition: encoding.h:256
rb_io_puts
VALUE rb_io_puts(int argc, VALUE *argv, VALUE out)
Definition: io.c:6983
rb_io_readbyte
static VALUE rb_io_readbyte(VALUE io)
Definition: io.c:3805
rb_id2name
const char * rb_id2name(ID id)
Definition: ripper.c:17230
READ_CHAR_PENDING_PTR
#define READ_CHAR_PENDING_PTR(fptr)
Definition: io.c:393
FMODE_SYNC
#define FMODE_SYNC
Definition: io.h:105
FMODE_TTY
#define FMODE_TTY
Definition: io.h:106
MakeOpenFile
#define MakeOpenFile(obj, fp)
Definition: io.h:127
io_internal_read_struct::capa
size_t capa
Definition: io.c:914
StringValuePtr
#define StringValuePtr(v)
Definition: ruby.h:540
econv_incomplete_input
Definition: encoding.h:259
SHUT_WR
#define SHUT_WR
SHUT_RD
#define SHUT_RD
rb_default_rs
VALUE rb_default_rs
Definition: io.c:156
MORE_CHAR_SUSPENDED
#define MORE_CHAR_SUSPENDED
Definition: io.c:2169
dup2
RUBY_EXTERN int dup2(int, int)
Definition: dup2.c:27
sym_sequential
static VALUE sym_sequential
Definition: io.c:8340
rb_str_new_frozen
VALUE rb_str_new_frozen(VALUE)
Definition: string.c:833
rb_io_t::rbuf
rb_io_buffer_t rbuf
Definition: io.h:70
argf::inplace
char * inplace
Definition: io.c:176
rb_io_s_copy_stream
static VALUE rb_io_s_copy_stream(int argc, VALUE *argv, VALUE io)
Definition: io.c:10451
rb_fd_init
#define rb_fd_init(f)
Definition: intern.h:357
rb_inspect
VALUE rb_inspect(VALUE)
Definition: object.c:470
clear_writeconv
static void clear_writeconv(rb_io_t *fptr)
Definition: io.c:4240
convconfig_t
struct rb_io_enc_t convconfig_t
Definition: io.c:5143
fill_cbuf
static VALUE fill_cbuf(rb_io_t *fptr, int ec_flags)
Definition: io.c:2172
rb_io_reopen
static VALUE rb_io_reopen(int argc, VALUE *argv, VALUE file)
Definition: io.c:6615
rb_ascii8bit_encoding
rb_encoding * rb_ascii8bit_encoding(void)
Definition: encoding.c:1227
read_buffered_data
static long read_buffered_data(char *ptr, long len, rb_io_t *fptr)
Definition: io.c:2011
sym_dontneed
static VALUE sym_dontneed
Definition: io.c:8340
FIX2UINT
#define FIX2UINT(x)
Definition: ruby.h:633
interpret_seek_whence
static int interpret_seek_whence(VALUE vwhence)
Definition: io.c:1556
rb_warning
void rb_warning(const char *fmt,...)
Definition: error.c:236
rb_enc_find_index
int rb_enc_find_index(const char *name)
Definition: encoding.c:684
rb_syserr_fail_path
#define rb_syserr_fail_path(err, path)
Definition: internal.h:451
rb_io_fsync
#define rb_io_fsync
Definition: io.c:1853
sym_END
static VALUE sym_END
Definition: io.c:163
rb_secure
void rb_secure(int)
Definition: safe.c:88
fileno
#define fileno(p)
Definition: vsnprintf.c:223
copy_stream_struct::th
VALUE th
Definition: io.c:9824
sym_open_args
static VALUE sym_open_args
Definition: io.c:161
sym_exception
static VALUE sym_exception
Definition: io.c:162
rb_execarg_new
VALUE rb_execarg_new(int argc, VALUE *argv, int accept_shell)
Definition: process.c:2261
rb_io_read_pending
int rb_io_read_pending(rb_io_t *fptr)
Definition: io.c:830
rb_check_frozen
#define rb_check_frozen(obj)
Definition: intern.h:277
NEED_NEWLINE_DECORATOR_ON_READ
#define NEED_NEWLINE_DECORATOR_ON_READ(fptr)
Definition: io.c:426
CONST_ID
#define CONST_ID(var, str)
Definition: ruby.h:1428
rb_io_t::stdio_file
FILE * stdio_file
Definition: io.h:63
rb_eEWOULDBLOCK
VALUE rb_eEWOULDBLOCK
Definition: error.c:41
rb_io_fileno
static VALUE rb_io_fileno(VALUE io)
Definition: io.c:1917
rb_io_bufread
ssize_t rb_io_bufread(VALUE io, void *buf, size_t size)
Definition: io.c:2094
sym_normal
static VALUE sym_normal
Definition: io.c:8340
MODE_BTMODE
#define MODE_BTMODE(a, b, c)
Definition: io.c:1293
rb_obj_freeze
VALUE rb_obj_freeze(VALUE)
Definition: object.c:1076
argf::filename
VALUE filename
Definition: io.c:172
id_readpartial
static ID id_readpartial
Definition: io.c:160
rb_f_p_arg
Definition: io.c:7046
rb_f_p
static VALUE rb_f_p(int argc, VALUE *argv, VALUE self)
Definition: io.c:7094
argf_forward
static VALUE argf_forward(int argc, VALUE *argv, VALUE argf)
Definition: io.c:7702
pipe_open_s
static VALUE pipe_open_s(VALUE prog, const char *modestr, int fmode, convconfig_t *convconfig)
Definition: io.c:6041
rb_f_readline
static VALUE rb_f_readline(int argc, VALUE *argv, VALUE recv)
Definition: io.c:8052
rb_str_encode
VALUE rb_str_encode(VALUE str, VALUE to, int ecflags, VALUE ecopts)
Definition: transcode.c:2885
xfree
void void xfree(void *)
rb_w32_fd_is_text
char rb_w32_fd_is_text(int)
Definition: win32.c:6980
io_seek
#define io_seek(fptr, ofs, whence)
Definition: io.c:756
rb_io_write_nonblock
static VALUE rb_io_write_nonblock(int argc, VALUE *argv, VALUE io)
Definition: io.c:2707
argf_fileno
static VALUE argf_fileno(VALUE argf)
Definition: io.c:10753
select_args::write
VALUE write
Definition: io.c:8316
rb_read_internal
static ssize_t rb_read_internal(int fd, void *buf, size_t count)
Definition: io.c:945
argf_to_s
static VALUE argf_to_s(VALUE argf)
Definition: io.c:11528
rb_output_rs
VALUE rb_output_rs
Definition: io.c:155
io_alloc
static VALUE io_alloc(VALUE klass)
Definition: io.c:875
foreach_arg::argv
VALUE * argv
Definition: io.c:9453
READ_CHAR_PENDING_COUNT
#define READ_CHAR_PENDING_COUNT(fptr)
Definition: io.c:392
rb_io_getline_1
static VALUE rb_io_getline_1(VALUE rs, long limit, VALUE io)
Definition: io.c:3071
rb_stdio_set_default_encoding
void rb_stdio_set_default_encoding(void)
Definition: io.c:10558
rb_io_t::lineno
int lineno
Definition: io.h:66
rb_str_buf_new
VALUE rb_str_buf_new(long)
Definition: string.c:891
rb_usascii_str_new
VALUE rb_usascii_str_new(const char *, long)
Definition: string.c:540
rb_mWaitWritable
VALUE rb_mWaitWritable
Definition: io.c:137
rb_io_read_check
void rb_io_read_check(rb_io_t *fptr)
Definition: io.c:847
fstat
#define fstat(fd, st)
Definition: win32.h:214
SYMBOL_P
#define SYMBOL_P(x)
Definition: ruby.h:354
rb_ioctl
static VALUE rb_ioctl(VALUE io, VALUE req, VALUE arg)
Definition: io.c:8940
stat
#define stat(path, st)
Definition: win32.h:213
io_read_nonblock
static VALUE io_read_nonblock(int argc, VALUE *argv, VALUE io)
Definition: io.c:2593
nogvl_copy_stream_func
static void * nogvl_copy_stream_func(void *arg)
Definition: io.c:10199
select_args::except
VALUE except
Definition: io.c:8316
rb_io_oflags_modestr
static const char * rb_io_oflags_modestr(int oflags)
Definition: io.c:4937
rb_io_sync
#define rb_io_sync
Definition: io.c:1854
DEFULT_IOCTL_NARG_LEN
#define DEFULT_IOCTL_NARG_LEN
Definition: io.c:8715
env
#define env
sysopen_struct::perm
mode_t perm
Definition: io.c:5328
rb_io_bufwrite
ssize_t rb_io_bufwrite(VALUE io, const void *buf, size_t size)
Definition: io.c:1365
NULL
#define NULL
Definition: _sdbm.c:103
FIX2LONG
#define FIX2LONG(x)
Definition: ruby.h:345
argf_file
static VALUE argf_file(VALUE argf)
Definition: io.c:11406
copy_stream_finalize
static VALUE copy_stream_finalize(VALUE arg)
Definition: io.c:10402
Qundef
#define Qundef
Definition: ruby.h:428
io_getc
static VALUE io_getc(rb_io_t *fptr, rb_encoding *enc)
Definition: io.c:3449
foreach_arg
Definition: io.c:9451
READ_CHAR_PENDING
#define READ_CHAR_PENDING(fptr)
Definition: io.c:391
argf_free
static void argf_free(void *ptr)
Definition: io.c:7587
READ_DATA_PENDING_PTR
#define READ_DATA_PENDING_PTR(fptr)
Definition: io.c:388
extract_binmode
static void extract_binmode(VALUE opthash, int *fmode)
Definition: io.c:5170
argf_close_m
static VALUE argf_close_m(VALUE argf)
Definition: io.c:11495
binwrite_arg
Definition: io.c:1193
id_flush
static ID id_flush
Definition: io.c:160
sysopen_struct
Definition: io.c:5325
select_end
static VALUE select_end(VALUE arg)
Definition: io.c:8330
rb_io_ext_int_to_encs
static void rb_io_ext_int_to_encs(rb_encoding *ext, rb_encoding *intern, rb_encoding **enc, rb_encoding **enc2, int fmode)
Definition: io.c:4971
rb_class_new
VALUE rb_class_new(VALUE super)
Creates a new class.
Definition: class.c:228
rb_define_method
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1488
ruby_verbose
#define ruby_verbose
Definition: ruby.h:1475
rb_str_append
VALUE rb_str_append(VALUE, VALUE)
Definition: string.c:2298
rb_file_open
VALUE rb_file_open(const char *fname, const char *modestr)
Definition: io.c:5561
econv_undefined_conversion
Definition: encoding.h:254
NOFILE
#define NOFILE
Definition: io.c:76
rb_io_check_byte_readable
void rb_io_check_byte_readable(rb_io_t *fptr)
Definition: io.c:785
rb_io_each_codepoint
static VALUE rb_io_each_codepoint(VALUE io)
Definition: io.c:3619
pipe_del_fptr
static void pipe_del_fptr(rb_io_t *fptr)
Definition: io.c:5584
rb_io_check_char_readable
void rb_io_check_char_readable(rb_io_t *fptr)
Definition: io.c:766
next_argv
#define next_argv()
Definition: io.c:7707
rb_econv_prepare_options
int rb_econv_prepare_options(VALUE opthash, VALUE *ecopts, int ecflags)
Definition: transcode.c:2527
rb_econv_binmode
void rb_econv_binmode(rb_econv_t *ec)
Definition: transcode.c:1942
rb_warn
void rb_warn(const char *fmt,...)
Definition: error.c:223
rb_io_s_foreach
static VALUE rb_io_s_foreach(int argc, VALUE *argv, VALUE self)
Definition: io.c:9532
pipe_list::fptr
rb_io_t * fptr
Definition: io.c:5568
SEEK_SET
#define SEEK_SET
Definition: io.c:760
rb_eArgError
VALUE rb_eArgError
Definition: error.c:549
rb_io_open
static VALUE rb_io_open(VALUE filename, VALUE vmode, VALUE vperm, VALUE opt)
Definition: io.c:6483
ECONV_UNIVERSAL_NEWLINE_DECORATOR
#define ECONV_UNIVERSAL_NEWLINE_DECORATOR
Definition: encoding.h:332
O_BINARY
#define O_BINARY
Definition: _sdbm.c:89
seek_arg::mode
int mode
Definition: io.c:9590
NUM2LONG
#define NUM2LONG(x)
Definition: ruby.h:600
rb_io_set_write_io
VALUE rb_io_set_write_io(VALUE io, VALUE w)
Definition: io.c:651
argf_initialize_copy
static VALUE argf_initialize_copy(VALUE argf, VALUE orig)
Definition: io.c:7643
rb_io_ungetc
VALUE rb_io_ungetc(VALUE io, VALUE c)
Definition: io.c:3868
rb_output_fs
VALUE rb_output_fs
Definition: io.c:153
argf_getc
static VALUE argf_getc(VALUE argf)
Definition: io.c:11020
rb_mutex_owned_p
VALUE rb_mutex_owned_p(VALUE self)
Definition: thread.c:4449
maygvl_close
static int maygvl_close(int fd, int keepgvl)
Definition: io.c:4123
rb_econv_putback
void rb_econv_putback(rb_econv_t *ec, unsigned char *p, int n)
Definition: transcode.c:1753
argf_skip
static VALUE argf_skip(VALUE argf)
Definition: io.c:11467
rb_io_check_closed
void rb_io_check_closed(rb_io_t *fptr)
Definition: io.c:617
rb_attr_get
VALUE rb_attr_get(VALUE, ID)
Definition: variable.c:1127
SEEK_CUR
#define SEEK_CUR
Definition: io.c:761
SET_BINARY_MODE
#define SET_BINARY_MODE(fptr)
Definition: io.c:568
strrchr
char * strrchr(const char *, const char)
argv
char ** argv
Definition: ruby.c:132
rb_econv_str_convert
VALUE rb_econv_str_convert(rb_econv_t *ec, VALUE src, int flags)
Definition: transcode.c:1877
seek_arg::io
VALUE io
Definition: io.c:9588
maygvl_fclose
static int maygvl_fclose(FILE *file, int keepgvl)
Definition: io.c:4144
StringValue
#define StringValue(v)
Definition: ruby.h:539
rb_io_t::writeconv
rb_econv_t * writeconv
Definition: io.h:90
argf_forward_call
static VALUE argf_forward_call(VALUE arg)
Definition: io.c:10906
rb_read_check
void rb_read_check(FILE *fp)
Definition: io.c:839
flock
Definition: ioctl.h:6
rb_write_error
void rb_write_error(const char *mesg)
Definition: io.c:7157
io_fillbuf
static int io_fillbuf(rb_io_t *fptr)
Definition: io.c:1673
seek_arg
Definition: io.c:9587
RUBY_UBF_IO
#define RUBY_UBF_IO
Definition: intern.h:872
read_internal_arg
Definition: io.c:2400
rb_enc_from_index
rb_encoding * rb_enc_from_index(int index)
Definition: encoding.c:590
OnigEncodingTypeST
Definition: oniguruma.h:158
unsupported_encoding
static void unsupported_encoding(const char *name)
Definition: io.c:4999
rb_obj_class
VALUE rb_obj_class(VALUE)
Definition: object.c:226
rb_str_new
VALUE rb_str_new(const char *, long)
Definition: string.c:534
SIGNED_VALUE
#define SIGNED_VALUE
Definition: ruby.h:90
rb_io_s_new
static VALUE rb_io_s_new(int argc, VALUE *argv, VALUE klass)
Definition: io.c:7503
clear_readconv
static void clear_readconv(rb_io_t *fptr)
Definition: io.c:4227
rb_eof_error
void rb_eof_error(void)
Definition: io.c:596