Ruby 2.0.0p353(2013-11-22revision43784)

- 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 #if defined(HAVE___SYSCALL) && (defined(__APPLE__) || defined(__OpenBSD__))
114 /* Mac OS X and OpenBSD have __syscall but don't define it in headers */
115 off_t __syscall(quad_t number, ...);
116 #endif
117
118 #define numberof(array) (int)(sizeof(array) / sizeof((array)[0]))
119
120 #define IO_RBUF_CAPA_MIN 8192
121 #define IO_CBUF_CAPA_MIN (128*1024)
122 #define IO_RBUF_CAPA_FOR(fptr) (NEED_READCONV(fptr) ? IO_CBUF_CAPA_MIN : IO_RBUF_CAPA_MIN)
123 #define IO_WBUF_CAPA_MIN 8192
124
125 /* define system APIs */
126 #ifdef _WIN32
127 #undef open
128 #define open rb_w32_uopen
129 #endif
130
131 VALUE rb_cIO;
132 VALUE rb_eEOFError;
133 VALUE rb_eIOError;
134 VALUE rb_mWaitReadable;
135 VALUE rb_mWaitWritable;
136
137 VALUE rb_stdin, rb_stdout, rb_stderr;
138 VALUE rb_deferr; /* rescue VIM plugin */
139 static VALUE orig_stdout, orig_stderr;
140
141 VALUE rb_output_fs;
142 VALUE rb_rs;
143 VALUE rb_output_rs;
144 VALUE rb_default_rs;
145
146 static VALUE argf;
147
148 static ID id_write, id_read, id_getc, id_flush, id_readpartial, id_set_encoding;
149 static VALUE sym_mode, sym_perm, sym_extenc, sym_intenc, sym_encoding, sym_open_args;
150 static VALUE sym_textmode, sym_binmode, sym_autoclose;
151
152 struct argf {
153 VALUE filename, current_file;
154 long last_lineno; /* $. */
155 long lineno;
156 VALUE argv;
157 char *inplace;
158 struct rb_io_enc_t encs;
159 int8_t init_p, next_p, binmode;
160 };
161
162 static rb_atomic_t max_file_descriptor = NOFILE;
163 void
164 rb_update_max_fd(int fd)
165 {
166 struct stat buf;
167 rb_atomic_t afd = (rb_atomic_t)fd;
168
169 if (fstat(fd, &buf) != 0 && errno == EBADF) {
170 rb_bug("rb_update_max_fd: invalid fd (%d) given.", fd);
171 }
172
173 while (max_file_descriptor < afd) {
174 ATOMIC_CAS(max_file_descriptor, max_file_descriptor, afd);
175 }
176 }
177
178 void
179 rb_maygvl_fd_fix_cloexec(int fd)
180 {
181 /* MinGW don't have F_GETFD and FD_CLOEXEC. [ruby-core:40281] */
182 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
183 int flags, flags2, ret;
184 flags = fcntl(fd, F_GETFD); /* should not fail except EBADF. */
185 if (flags == -1) {
186 rb_bug("rb_maygvl_fd_fix_cloexec: fcntl(%d, F_GETFD) failed: %s", fd, strerror(errno));
187 }
188 if (fd <= 2)
189 flags2 = flags & ~FD_CLOEXEC; /* Clear CLOEXEC for standard file descriptors: 0, 1, 2. */
190 else
191 flags2 = flags | FD_CLOEXEC; /* Set CLOEXEC for non-standard file descriptors: 3, 4, 5, ... */
192 if (flags != flags2) {
193 ret = fcntl(fd, F_SETFD, flags2);
194 if (ret == -1) {
195 rb_bug("rb_maygvl_fd_fix_cloexec: fcntl(%d, F_SETFD, %d) failed: %s", fd, flags2, strerror(errno));
196 }
197 }
198 #endif
199 }
200
201 void
202 rb_fd_fix_cloexec(int fd)
203 {
204 rb_maygvl_fd_fix_cloexec(fd);
205 rb_update_max_fd(fd);
206 }
207
208 int
209 rb_cloexec_open(const char *pathname, int flags, mode_t mode)
210 {
211 int ret;
212 #ifdef O_CLOEXEC
213 /* O_CLOEXEC is available since Linux 2.6.23. Linux 2.6.18 silently ignore it. */
214 flags |= O_CLOEXEC;
215 #elif defined O_NOINHERIT
216 flags |= O_NOINHERIT;
217 #endif
218 ret = open(pathname, flags, mode);
219 if (ret == -1) return -1;
220 rb_maygvl_fd_fix_cloexec(ret);
221 return ret;
222 }
223
224 int
225 rb_cloexec_dup(int oldfd)
226 {
227 /* Don't allocate standard file descriptors: 0, 1, 2 */
228 return rb_cloexec_fcntl_dupfd(oldfd, 3);
229 }
230
231 int
232 rb_cloexec_dup2(int oldfd, int newfd)
233 {
234 int ret;
235
236 /* When oldfd == newfd, dup2 succeeds but dup3 fails with EINVAL.
237 * rb_cloexec_dup2 succeeds as dup2. */
238 if (oldfd == newfd) {
239 ret = newfd;
240 }
241 else {
242 #if defined(HAVE_DUP3) && defined(O_CLOEXEC)
243 static int try_dup3 = 1;
244 if (2 < newfd && try_dup3) {
245 ret = dup3(oldfd, newfd, O_CLOEXEC);
246 if (ret != -1)
247 return ret;
248 /* dup3 is available since Linux 2.6.27, glibc 2.9. */
249 if (errno == ENOSYS) {
250 try_dup3 = 0;
251 ret = dup2(oldfd, newfd);
252 }
253 }
254 else {
255 ret = dup2(oldfd, newfd);
256 }
257 #else
258 ret = dup2(oldfd, newfd);
259 # ifdef _WIN32
260 if (newfd >= 0 && newfd <= 2)
261 SetStdHandle(newfd == 0 ? STD_INPUT_HANDLE : newfd == 1 ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE, (HANDLE)rb_w32_get_osfhandle(newfd));
262 # endif
263 #endif
264 if (ret == -1) return -1;
265 }
266 rb_maygvl_fd_fix_cloexec(ret);
267 return ret;
268 }
269
270 int
271 rb_cloexec_pipe(int fildes[2])
272 {
273 int ret;
274
275 #if defined(HAVE_PIPE2)
276 static int try_pipe2 = 1;
277 if (try_pipe2) {
278 ret = pipe2(fildes, O_CLOEXEC);
279 if (ret != -1)
280 return ret;
281 /* pipe2 is available since Linux 2.6.27, glibc 2.9. */
282 if (errno == ENOSYS) {
283 try_pipe2 = 0;
284 ret = pipe(fildes);
285 }
286 }
287 else {
288 ret = pipe(fildes);
289 }
290 #else
291 ret = pipe(fildes);
292 #endif
293 if (ret == -1) return -1;
294 #ifdef __CYGWIN__
295 if (ret == 0 && fildes[1] == -1) {
296 close(fildes[0]);
297 fildes[0] = -1;
298 errno = ENFILE;
299 return -1;
300 }
301 #endif
302 rb_maygvl_fd_fix_cloexec(fildes[0]);
303 rb_maygvl_fd_fix_cloexec(fildes[1]);
304 return ret;
305 }
306
307 int
308 rb_cloexec_fcntl_dupfd(int fd, int minfd)
309 {
310 int ret;
311
312 #if defined(HAVE_FCNTL) && defined(F_DUPFD_CLOEXEC) && defined(F_DUPFD)
313 static int try_dupfd_cloexec = 1;
314 if (try_dupfd_cloexec) {
315 ret = fcntl(fd, F_DUPFD_CLOEXEC, minfd);
316 if (ret != -1) {
317 if (ret <= 2)
318 rb_maygvl_fd_fix_cloexec(ret);
319 return ret;
320 }
321 /* F_DUPFD_CLOEXEC is available since Linux 2.6.24. Linux 2.6.18 fails with EINVAL */
322 if (errno == EINVAL) {
323 ret = fcntl(fd, F_DUPFD, minfd);
324 if (ret != -1) {
325 try_dupfd_cloexec = 0;
326 }
327 }
328 }
329 else {
330 ret = fcntl(fd, F_DUPFD, minfd);
331 }
332 #elif defined(HAVE_FCNTL) && defined(F_DUPFD)
333 ret = fcntl(fd, F_DUPFD, minfd);
334 #elif defined(HAVE_DUP)
335 ret = dup(fd);
336 if (ret != -1 && ret < minfd) {
337 const int prev_fd = ret;
338 ret = rb_cloexec_fcntl_dupfd(fd, minfd);
339 close(prev_fd);
340 }
341 return ret;
342 #else
343 # error "dup() or fcntl(F_DUPFD) must be supported."
344 #endif
345 if (ret == -1) return -1;
346 rb_maygvl_fd_fix_cloexec(ret);
347 return ret;
348 }
349
350 #define argf_of(obj) (*(struct argf *)DATA_PTR(obj))
351 #define ARGF argf_of(argf)
352
353 #ifdef _STDIO_USES_IOSTREAM /* GNU libc */
354 # ifdef _IO_fpos_t
355 # define STDIO_READ_DATA_PENDING(fp) ((fp)->_IO_read_ptr != (fp)->_IO_read_end)
356 # else
357 # define STDIO_READ_DATA_PENDING(fp) ((fp)->_gptr < (fp)->_egptr)
358 # endif
359 #elif defined(FILE_COUNT)
360 # define STDIO_READ_DATA_PENDING(fp) ((fp)->FILE_COUNT > 0)
361 #elif defined(FILE_READEND)
362 # define STDIO_READ_DATA_PENDING(fp) ((fp)->FILE_READPTR < (fp)->FILE_READEND)
363 #elif defined(__BEOS__) || defined(__HAIKU__)
364 # define STDIO_READ_DATA_PENDING(fp) ((fp)->_state._eof == 0)
365 #else
366 # define STDIO_READ_DATA_PENDING(fp) (!feof(fp))
367 #endif
368
369 #define GetWriteIO(io) rb_io_get_write_io(io)
370
371 #define READ_DATA_PENDING(fptr) ((fptr)->rbuf.len)
372 #define READ_DATA_PENDING_COUNT(fptr) ((fptr)->rbuf.len)
373 #define READ_DATA_PENDING_PTR(fptr) ((fptr)->rbuf.ptr+(fptr)->rbuf.off)
374 #define READ_DATA_BUFFERED(fptr) READ_DATA_PENDING(fptr)
375
376 #define READ_CHAR_PENDING(fptr) ((fptr)->cbuf.len)
377 #define READ_CHAR_PENDING_COUNT(fptr) ((fptr)->cbuf.len)
378 #define READ_CHAR_PENDING_PTR(fptr) ((fptr)->cbuf.ptr+(fptr)->cbuf.off)
379
380 #if defined(_WIN32)
381 #define WAIT_FD_IN_WIN32(fptr) \
382 (rb_w32_io_cancelable_p((fptr)->fd) ? 0 : rb_thread_wait_fd((fptr)->fd))
383 #else
384 #define WAIT_FD_IN_WIN32(fptr)
385 #endif
386
387 #define READ_CHECK(fptr) do {\
388 if (!READ_DATA_PENDING(fptr)) {\
389 WAIT_FD_IN_WIN32(fptr);\
390 rb_io_check_closed(fptr);\
391 }\
392 } while(0)
393
394 #ifndef S_ISSOCK
395 # ifdef _S_ISSOCK
396 # define S_ISSOCK(m) _S_ISSOCK(m)
397 # else
398 # ifdef _S_IFSOCK
399 # define S_ISSOCK(m) (((m) & S_IFMT) == _S_IFSOCK)
400 # else
401 # ifdef S_IFSOCK
402 # define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
403 # endif
404 # endif
405 # endif
406 #endif
407
408 #define rb_sys_fail_path(path) rb_sys_fail_str(path)
409
410 static int io_fflush(rb_io_t *);
411 static rb_io_t *flush_before_seek(rb_io_t *fptr);
412
413 #define NEED_NEWLINE_DECORATOR_ON_READ(fptr) ((fptr)->mode & FMODE_TEXTMODE)
414 #define NEED_NEWLINE_DECORATOR_ON_WRITE(fptr) ((fptr)->mode & FMODE_TEXTMODE)
415 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
416 /* Windows */
417 # define DEFAULT_TEXTMODE FMODE_TEXTMODE
418 # define TEXTMODE_NEWLINE_DECORATOR_ON_WRITE ECONV_CRLF_NEWLINE_DECORATOR
419 /*
420 * CRLF newline is set as default newline decorator.
421 * If only CRLF newline conversion is needed, we use binary IO process
422 * with OS's text mode for IO performance improvement.
423 * If encoding conversion is needed or a user sets text mode, we use encoding
424 * conversion IO process and universal newline decorator by default.
425 */
426 #define NEED_READCONV(fptr) ((fptr)->encs.enc2 != NULL || (fptr)->encs.ecflags & ~ECONV_CRLF_NEWLINE_DECORATOR)
427 #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)))
428 #define SET_BINARY_MODE(fptr) setmode((fptr)->fd, O_BINARY)
429
430 #define NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr) do {\
431 if (NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {\
432 if (((fptr)->mode & FMODE_READABLE) &&\
433 !((fptr)->encs.ecflags & ECONV_NEWLINE_DECORATOR_MASK)) {\
434 setmode((fptr)->fd, O_BINARY);\
435 }\
436 else {\
437 setmode((fptr)->fd, O_TEXT);\
438 }\
439 }\
440 } while(0)
441
442 #define SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags) do {\
443 if ((enc2) && ((ecflags) & ECONV_DEFAULT_NEWLINE_DECORATOR)) {\
444 (ecflags) |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;\
445 }\
446 } while(0)
447
448 /*
449 * IO unread with taking care of removed '\r' in text mode.
450 */
451 static void
452 io_unread(rb_io_t *fptr)
453 {
454 off_t r, pos;
455 ssize_t read_size;
456 long i;
457 long newlines = 0;
458 long extra_max;
459 char *p;
460 char *buf;
461
462 rb_io_check_closed(fptr);
463 if (fptr->rbuf.len == 0 || fptr->mode & FMODE_DUPLEX) {
464 return;
465 }
466
467 errno = 0;
468 if (!rb_w32_fd_is_text(fptr->fd)) {
469 r = lseek(fptr->fd, -fptr->rbuf.len, SEEK_CUR);
470 if (r < 0 && errno) {
471 if (errno == ESPIPE)
472 fptr->mode |= FMODE_DUPLEX;
473 return;
474 }
475
476 fptr->rbuf.off = 0;
477 fptr->rbuf.len = 0;
478 return;
479 }
480
481 pos = lseek(fptr->fd, 0, SEEK_CUR);
482 if (pos < 0 && errno) {
483 if (errno == ESPIPE)
484 fptr->mode |= FMODE_DUPLEX;
485 return;
486 }
487
488 /* add extra offset for removed '\r' in rbuf */
489 extra_max = (long)(pos - fptr->rbuf.len);
490 p = fptr->rbuf.ptr + fptr->rbuf.off;
491
492 /* if the end of rbuf is '\r', rbuf doesn't have '\r' within rbuf.len */
493 if (*(fptr->rbuf.ptr + fptr->rbuf.capa - 1) == '\r') {
494 newlines++;
495 }
496
497 for (i = 0; i < fptr->rbuf.len; i++) {
498 if (*p == '\n') newlines++;
499 if (extra_max == newlines) break;
500 p++;
501 }
502
503 buf = ALLOC_N(char, fptr->rbuf.len + newlines);
504 while (newlines >= 0) {
505 r = lseek(fptr->fd, pos - fptr->rbuf.len - newlines, SEEK_SET);
506 if (newlines == 0) break;
507 if (r < 0) {
508 newlines--;
509 continue;
510 }
511 read_size = _read(fptr->fd, buf, fptr->rbuf.len + newlines);
512 if (read_size < 0) {
513 free(buf);
514 rb_sys_fail_path(fptr->pathv);
515 }
516 if (read_size == fptr->rbuf.len) {
517 lseek(fptr->fd, r, SEEK_SET);
518 break;
519 }
520 else {
521 newlines--;
522 }
523 }
524 free(buf);
525 fptr->rbuf.off = 0;
526 fptr->rbuf.len = 0;
527 return;
528 }
529
530 /*
531 * We use io_seek to back cursor position when changing mode from text to binary,
532 * but stdin and pipe cannot seek back. Stdin and pipe read should use encoding
533 * conversion for working properly with mode change.
534 *
535 * Return previous translation mode.
536 */
537 static inline int
538 set_binary_mode_with_seek_cur(rb_io_t *fptr)
539 {
540 if (!rb_w32_fd_is_text(fptr->fd)) return O_BINARY;
541
542 if (fptr->rbuf.len == 0 || fptr->mode & FMODE_DUPLEX) {
543 return setmode(fptr->fd, O_BINARY);
544 }
545 flush_before_seek(fptr);
546 return setmode(fptr->fd, O_BINARY);
547 }
548 #define SET_BINARY_MODE_WITH_SEEK_CUR(fptr) set_binary_mode_with_seek_cur(fptr)
549
550 #else
551 /* Unix */
552 # define DEFAULT_TEXTMODE 0
553 #define NEED_READCONV(fptr) ((fptr)->encs.enc2 != NULL || NEED_NEWLINE_DECORATOR_ON_READ(fptr))
554 #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)))
555 #define SET_BINARY_MODE(fptr) (void)(fptr)
556 #define NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr) (void)(fptr)
557 #define SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags) ((void)(enc2), (void)(ecflags))
558 #define SET_BINARY_MODE_WITH_SEEK_CUR(fptr) (void)(fptr)
559 #endif
560
561 #if !defined HAVE_SHUTDOWN && !defined shutdown
562 #define shutdown(a,b) 0
563 #endif
564
565 #if defined(_WIN32)
566 #define is_socket(fd, path) rb_w32_is_socket(fd)
567 #elif !defined(S_ISSOCK)
568 #define is_socket(fd, path) 0
569 #else
570 static int
571 is_socket(int fd, VALUE path)
572 {
573 struct stat sbuf;
574 if (fstat(fd, &sbuf) < 0)
575 rb_sys_fail_path(path);
576 return S_ISSOCK(sbuf.st_mode);
577 }
578 #endif
579
580 void
581 rb_eof_error(void)
582 {
583 rb_raise(rb_eEOFError, "end of file reached");
584 }
585
586 VALUE
587 rb_io_taint_check(VALUE io)
588 {
589 if (!OBJ_UNTRUSTED(io) && rb_safe_level() >= 4)
590 rb_raise(rb_eSecurityError, "Insecure: operation on trusted IO");
591 rb_check_frozen(io);
592 return io;
593 }
594
595 void
596 rb_io_check_initialized(rb_io_t *fptr)
597 {
598 if (!fptr) {
599 rb_raise(rb_eIOError, "uninitialized stream");
600 }
601 }
602
603 void
604 rb_io_check_closed(rb_io_t *fptr)
605 {
606 rb_io_check_initialized(fptr);
607 if (fptr->fd < 0) {
608 rb_raise(rb_eIOError, "closed stream");
609 }
610 }
611
612
613 VALUE
614 rb_io_get_io(VALUE io)
615 {
616 return rb_convert_type(io, T_FILE, "IO", "to_io");
617 }
618
619 VALUE
620 rb_io_check_io(VALUE io)
621 {
622 return rb_check_convert_type(io, T_FILE, "IO", "to_io");
623 }
624
625 VALUE
626 rb_io_get_write_io(VALUE io)
627 {
628 VALUE write_io;
629 rb_io_check_initialized(RFILE(io)->fptr);
630 write_io = RFILE(io)->fptr->tied_io_for_writing;
631 if (write_io) {
632 return write_io;
633 }
634 return io;
635 }
636
637 VALUE
638 rb_io_set_write_io(VALUE io, VALUE w)
639 {
640 VALUE write_io;
641 rb_io_check_initialized(RFILE(io)->fptr);
642 if (!RTEST(w)) {
643 w = 0;
644 }
645 else {
646 GetWriteIO(w);
647 }
648 write_io = RFILE(io)->fptr->tied_io_for_writing;
649 RFILE(io)->fptr->tied_io_for_writing = w;
650 return write_io ? write_io : Qnil;
651 }
652
653 /*
654 * call-seq:
655 * IO.try_convert(obj) -> io or nil
656 *
657 * Try to convert <i>obj</i> into an IO, using to_io method.
658 * Returns converted IO or nil if <i>obj</i> cannot be converted
659 * for any reason.
660 *
661 * IO.try_convert(STDOUT) #=> STDOUT
662 * IO.try_convert("STDOUT") #=> nil
663 *
664 * require 'zlib'
665 * f = open("/tmp/zz.gz") #=> #<File:/tmp/zz.gz>
666 * z = Zlib::GzipReader.open(f) #=> #<Zlib::GzipReader:0x81d8744>
667 * IO.try_convert(z) #=> #<File:/tmp/zz.gz>
668 *
669 */
670 static VALUE
671 rb_io_s_try_convert(VALUE dummy, VALUE io)
672 {
673 return rb_io_check_io(io);
674 }
675
676 #if !(defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32))
677 static void
678 io_unread(rb_io_t *fptr)
679 {
680 off_t r;
681 rb_io_check_closed(fptr);
682 if (fptr->rbuf.len == 0 || fptr->mode & FMODE_DUPLEX)
683 return;
684 /* xxx: target position may be negative if buffer is filled by ungetc */
685 errno = 0;
686 r = lseek(fptr->fd, -fptr->rbuf.len, SEEK_CUR);
687 if (r < 0 && errno) {
688 if (errno == ESPIPE)
689 fptr->mode |= FMODE_DUPLEX;
690 return;
691 }
692 fptr->rbuf.off = 0;
693 fptr->rbuf.len = 0;
694 return;
695 }
696 #endif
697
698 static rb_encoding *io_input_encoding(rb_io_t *fptr);
699
700 static void
701 io_ungetbyte(VALUE str, rb_io_t *fptr)
702 {
703 long len = RSTRING_LEN(str);
704
705 if (fptr->rbuf.ptr == NULL) {
706 const int min_capa = IO_RBUF_CAPA_FOR(fptr);
707 fptr->rbuf.off = 0;
708 fptr->rbuf.len = 0;
709 #if SIZEOF_LONG > SIZEOF_INT
710 if (len > INT_MAX)
711 rb_raise(rb_eIOError, "ungetbyte failed");
712 #endif
713 if (len > min_capa)
714 fptr->rbuf.capa = (int)len;
715 else
716 fptr->rbuf.capa = min_capa;
717 fptr->rbuf.ptr = ALLOC_N(char, fptr->rbuf.capa);
718 }
719 if (fptr->rbuf.capa < len + fptr->rbuf.len) {
720 rb_raise(rb_eIOError, "ungetbyte failed");
721 }
722 if (fptr->rbuf.off < len) {
723 MEMMOVE(fptr->rbuf.ptr+fptr->rbuf.capa-fptr->rbuf.len,
724 fptr->rbuf.ptr+fptr->rbuf.off,
725 char, fptr->rbuf.len);
726 fptr->rbuf.off = fptr->rbuf.capa-fptr->rbuf.len;
727 }
728 fptr->rbuf.off-=(int)len;
729 fptr->rbuf.len+=(int)len;
730 MEMMOVE(fptr->rbuf.ptr+fptr->rbuf.off, RSTRING_PTR(str), char, len);
731 }
732
733 static rb_io_t *
734 flush_before_seek(rb_io_t *fptr)
735 {
736 if (io_fflush(fptr) < 0)
737 rb_sys_fail(0);
738 io_unread(fptr);
739 errno = 0;
740 return fptr;
741 }
742
743 #define io_seek(fptr, ofs, whence) (errno = 0, lseek(flush_before_seek(fptr)->fd, (ofs), (whence)))
744 #define io_tell(fptr) lseek(flush_before_seek(fptr)->fd, 0, SEEK_CUR)
745
746 #ifndef SEEK_CUR
747 # define SEEK_SET 0
748 # define SEEK_CUR 1
749 # define SEEK_END 2
750 #endif
751
752 void
753 rb_io_check_char_readable(rb_io_t *fptr)
754 {
755 rb_io_check_closed(fptr);
756 if (!(fptr->mode & FMODE_READABLE)) {
757 rb_raise(rb_eIOError, "not opened for reading");
758 }
759 if (fptr->wbuf.len) {
760 if (io_fflush(fptr) < 0)
761 rb_sys_fail(0);
762 }
763 if (fptr->tied_io_for_writing) {
764 rb_io_t *wfptr;
765 GetOpenFile(fptr->tied_io_for_writing, wfptr);
766 if (io_fflush(wfptr) < 0)
767 rb_sys_fail(0);
768 }
769 }
770
771 void
772 rb_io_check_byte_readable(rb_io_t *fptr)
773 {
774 rb_io_check_char_readable(fptr);
775 if (READ_CHAR_PENDING(fptr)) {
776 rb_raise(rb_eIOError, "byte oriented read for character buffered IO");
777 }
778 }
779
780 void
781 rb_io_check_readable(rb_io_t *fptr)
782 {
783 rb_io_check_byte_readable(fptr);
784 }
785
786 static rb_encoding*
787 io_read_encoding(rb_io_t *fptr)
788 {
789 if (fptr->encs.enc) {
790 return fptr->encs.enc;
791 }
792 return rb_default_external_encoding();
793 }
794
795 static rb_encoding*
796 io_input_encoding(rb_io_t *fptr)
797 {
798 if (fptr->encs.enc2) {
799 return fptr->encs.enc2;
800 }
801 return io_read_encoding(fptr);
802 }
803
804 void
805 rb_io_check_writable(rb_io_t *fptr)
806 {
807 rb_io_check_closed(fptr);
808 if (!(fptr->mode & FMODE_WRITABLE)) {
809 rb_raise(rb_eIOError, "not opened for writing");
810 }
811 if (fptr->rbuf.len) {
812 io_unread(fptr);
813 }
814 }
815
816 int
817 rb_io_read_pending(rb_io_t *fptr)
818 {
819 /* This function is used for bytes and chars. Confusing. */
820 if (READ_CHAR_PENDING(fptr))
821 return 1; /* should raise? */
822 return READ_DATA_PENDING(fptr);
823 }
824
825 void
826 rb_read_check(FILE *fp)
827 {
828 if (!STDIO_READ_DATA_PENDING(fp)) {
829 rb_thread_wait_fd(fileno(fp));
830 }
831 }
832
833 void
834 rb_io_read_check(rb_io_t *fptr)
835 {
836 if (!READ_DATA_PENDING(fptr)) {
837 rb_thread_wait_fd(fptr->fd);
838 }
839 return;
840 }
841
842 static int
843 ruby_dup(int orig)
844 {
845 int fd;
846
847 fd = rb_cloexec_dup(orig);
848 if (fd < 0) {
849 if (errno == EMFILE || errno == ENFILE || errno == ENOMEM) {
850 rb_gc();
851 fd = rb_cloexec_dup(orig);
852 }
853 if (fd < 0) {
854 rb_sys_fail(0);
855 }
856 }
857 rb_update_max_fd(fd);
858 return fd;
859 }
860
861 static VALUE
862 io_alloc(VALUE klass)
863 {
864 NEWOBJ_OF(io, struct RFile, klass, T_FILE);
865
866 io->fptr = 0;
867
868 return (VALUE)io;
869 }
870
871 #ifndef S_ISREG
872 # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
873 #endif
874
875 static int
876 wsplit_p(rb_io_t *fptr)
877 {
878 #if defined(HAVE_FCNTL) && defined(F_GETFL) && defined(O_NONBLOCK)
879 int r;
880 #endif
881
882 if (!(fptr->mode & FMODE_WSPLIT_INITIALIZED)) {
883 struct stat buf;
884 if (fstat(fptr->fd, &buf) == 0 &&
885 !S_ISREG(buf.st_mode)
886 #if defined(HAVE_FCNTL) && defined(F_GETFL) && defined(O_NONBLOCK)
887 && (r = fcntl(fptr->fd, F_GETFL)) != -1 &&
888 !(r & O_NONBLOCK)
889 #endif
890 ) {
891 fptr->mode |= FMODE_WSPLIT;
892 }
893 fptr->mode |= FMODE_WSPLIT_INITIALIZED;
894 }
895 return fptr->mode & FMODE_WSPLIT;
896 }
897
898 struct io_internal_read_struct {
899 int fd;
900 void *buf;
901 size_t capa;
902 };
903
904 struct io_internal_write_struct {
905 int fd;
906 const void *buf;
907 size_t capa;
908 };
909
910 static VALUE
911 internal_read_func(void *ptr)
912 {
913 struct io_internal_read_struct *iis = ptr;
914 return read(iis->fd, iis->buf, iis->capa);
915 }
916
917 static VALUE
918 internal_write_func(void *ptr)
919 {
920 struct io_internal_write_struct *iis = ptr;
921 return write(iis->fd, iis->buf, iis->capa);
922 }
923
924 static void*
925 internal_write_func2(void *ptr)
926 {
927 struct io_internal_write_struct *iis = ptr;
928 return (void*)(intptr_t)write(iis->fd, iis->buf, iis->capa);
929 }
930
931 static ssize_t
932 rb_read_internal(int fd, void *buf, size_t count)
933 {
934 struct io_internal_read_struct iis;
935 iis.fd = fd;
936 iis.buf = buf;
937 iis.capa = count;
938
939 return (ssize_t)rb_thread_io_blocking_region(internal_read_func, &iis, fd);
940 }
941
942 static ssize_t
943 rb_write_internal(int fd, const void *buf, size_t count)
944 {
945 struct io_internal_write_struct iis;
946 iis.fd = fd;
947 iis.buf = buf;
948 iis.capa = count;
949
950 return (ssize_t)rb_thread_io_blocking_region(internal_write_func, &iis, fd);
951 }
952
953 static ssize_t
954 rb_write_internal2(int fd, const void *buf, size_t count)
955 {
956 struct io_internal_write_struct iis;
957 iis.fd = fd;
958 iis.buf = buf;
959 iis.capa = count;
960
961 return (ssize_t)rb_thread_call_without_gvl2(internal_write_func2, &iis,
962 RUBY_UBF_IO, NULL);
963 }
964
965 static long
966 io_writable_length(rb_io_t *fptr, long l)
967 {
968 if (PIPE_BUF < l &&
969 !rb_thread_alone() &&
970 wsplit_p(fptr)) {
971 l = PIPE_BUF;
972 }
973 return l;
974 }
975
976 static VALUE
977 io_flush_buffer_sync(void *arg)
978 {
979 rb_io_t *fptr = arg;
980 long l = io_writable_length(fptr, fptr->wbuf.len);
981 ssize_t r = write(fptr->fd, fptr->wbuf.ptr+fptr->wbuf.off, (size_t)l);
982
983 if (fptr->wbuf.len <= r) {
984 fptr->wbuf.off = 0;
985 fptr->wbuf.len = 0;
986 return 0;
987 }
988 if (0 <= r) {
989 fptr->wbuf.off += (int)r;
990 fptr->wbuf.len -= (int)r;
991 errno = EAGAIN;
992 }
993 return (VALUE)-1;
994 }
995
996 static void*
997 io_flush_buffer_sync2(void *arg)
998 {
999 VALUE result = io_flush_buffer_sync(arg);
1000
1001 /*
1002 * rb_thread_call_without_gvl2 uses 0 as interrupted.
1003 * So, we need to avoid to use 0.
1004 */
1005 return !result ? (void*)1 : (void*)result;
1006 }
1007
1008 static VALUE
1009 io_flush_buffer_async(VALUE arg)
1010 {
1011 rb_io_t *fptr = (rb_io_t *)arg;
1012 return rb_thread_io_blocking_region(io_flush_buffer_sync, fptr, fptr->fd);
1013 }
1014
1015 static VALUE
1016 io_flush_buffer_async2(VALUE arg)
1017 {
1018 rb_io_t *fptr = (rb_io_t *)arg;
1019 VALUE ret;
1020
1021 ret = (VALUE)rb_thread_call_without_gvl2(io_flush_buffer_sync2, fptr,
1022 RUBY_UBF_IO, NULL);
1023
1024 if (!ret) {
1025 /* pending async interrupt is there. */
1026 errno = EAGAIN;
1027 return -1;
1028 } else if (ret == 1) {
1029 return 0;
1030 } else
1031 return ret;
1032 }
1033
1034 static inline int
1035 io_flush_buffer(rb_io_t *fptr)
1036 {
1037 if (fptr->write_lock) {
1038 if (rb_mutex_owned_p(fptr->write_lock))
1039 return (int)io_flush_buffer_async2((VALUE)fptr);
1040 else
1041 return (int)rb_mutex_synchronize(fptr->write_lock, io_flush_buffer_async2, (VALUE)fptr);
1042 }
1043 else {
1044 return (int)io_flush_buffer_async((VALUE)fptr);
1045 }
1046 }
1047
1048 static int
1049 io_fflush(rb_io_t *fptr)
1050 {
1051 rb_io_check_closed(fptr);
1052 if (fptr->wbuf.len == 0)
1053 return 0;
1054 rb_io_check_closed(fptr);
1055 while (fptr->wbuf.len > 0 && io_flush_buffer(fptr) != 0) {
1056 if (!rb_io_wait_writable(fptr->fd))
1057 return -1;
1058 rb_io_check_closed(fptr);
1059 }
1060 return 0;
1061 }
1062
1063 int
1064 rb_io_wait_readable(int f)
1065 {
1066 if (f < 0) {
1067 rb_raise(rb_eIOError, "closed stream");
1068 }
1069 switch (errno) {
1070 case EINTR:
1071 #if defined(ERESTART)
1072 case ERESTART:
1073 #endif
1074 rb_thread_check_ints();
1075 return TRUE;
1076
1077 case EAGAIN:
1078 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
1079 case EWOULDBLOCK:
1080 #endif
1081 rb_thread_wait_fd(f);
1082 return TRUE;
1083
1084 default:
1085 return FALSE;
1086 }
1087 }
1088
1089 int
1090 rb_io_wait_writable(int f)
1091 {
1092 if (f < 0) {
1093 rb_raise(rb_eIOError, "closed stream");
1094 }
1095 switch (errno) {
1096 case EINTR:
1097 #if defined(ERESTART)
1098 case ERESTART:
1099 #endif
1100 /*
1101 * In old Linux, several special files under /proc and /sys don't handle
1102 * select properly. Thus we need avoid to call if don't use O_NONBLOCK.
1103 * Otherwise, we face nasty hang up. Sigh.
1104 * e.g. http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=31b07093c44a7a442394d44423e21d783f5523b8
1105 * http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=31b07093c44a7a442394d44423e21d783f5523b8
1106 * In EINTR case, we only need to call RUBY_VM_CHECK_INTS_BLOCKING().
1107 * Then rb_thread_check_ints() is enough.
1108 */
1109 rb_thread_check_ints();
1110 return TRUE;
1111
1112 case EAGAIN:
1113 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
1114 case EWOULDBLOCK:
1115 #endif
1116 rb_thread_fd_writable(f);
1117 return TRUE;
1118
1119 default:
1120 return FALSE;
1121 }
1122 }
1123
1124 static void
1125 make_writeconv(rb_io_t *fptr)
1126 {
1127 if (!fptr->writeconv_initialized) {
1128 const char *senc, *denc;
1129 rb_encoding *enc;
1130 int ecflags;
1131 VALUE ecopts;
1132
1133 fptr->writeconv_initialized = 1;
1134
1135 ecflags = fptr->encs.ecflags & ~ECONV_NEWLINE_DECORATOR_READ_MASK;
1136 ecopts = fptr->encs.ecopts;
1137
1138 if (!fptr->encs.enc || (fptr->encs.enc == rb_ascii8bit_encoding() && !fptr->encs.enc2)) {
1139 /* no encoding conversion */
1140 fptr->writeconv_pre_ecflags = 0;
1141 fptr->writeconv_pre_ecopts = Qnil;
1142 fptr->writeconv = rb_econv_open_opts("", "", ecflags, ecopts);
1143 if (!fptr->writeconv)
1144 rb_exc_raise(rb_econv_open_exc("", "", ecflags));
1145 fptr->writeconv_asciicompat = Qnil;
1146 }
1147 else {
1148 enc = fptr->encs.enc2 ? fptr->encs.enc2 : fptr->encs.enc;
1149 senc = rb_econv_asciicompat_encoding(rb_enc_name(enc));
1150 if (!senc && !(fptr->encs.ecflags & ECONV_STATEFUL_DECORATOR_MASK)) {
1151 /* single conversion */
1152 fptr->writeconv_pre_ecflags = ecflags;
1153 fptr->writeconv_pre_ecopts = ecopts;
1154 fptr->writeconv = NULL;
1155 fptr->writeconv_asciicompat = Qnil;
1156 }
1157 else {
1158 /* double conversion */
1159 fptr->writeconv_pre_ecflags = ecflags & ~ECONV_STATEFUL_DECORATOR_MASK;
1160 fptr->writeconv_pre_ecopts = ecopts;
1161 if (senc) {
1162 denc = rb_enc_name(enc);
1163 fptr->writeconv_asciicompat = rb_str_new2(senc);
1164 }
1165 else {
1166 senc = denc = "";
1167 fptr->writeconv_asciicompat = rb_str_new2(rb_enc_name(enc));
1168 }
1169 ecflags = fptr->encs.ecflags & (ECONV_ERROR_HANDLER_MASK|ECONV_STATEFUL_DECORATOR_MASK);
1170 ecopts = fptr->encs.ecopts;
1171 fptr->writeconv = rb_econv_open_opts(senc, denc, ecflags, ecopts);
1172 if (!fptr->writeconv)
1173 rb_exc_raise(rb_econv_open_exc(senc, denc, ecflags));
1174 }
1175 }
1176 }
1177 }
1178
1179 /* writing functions */
1180 struct binwrite_arg {
1181 rb_io_t *fptr;
1182 VALUE str;
1183 const char *ptr;
1184 long length;
1185 };
1186
1187 struct write_arg {
1188 VALUE io;
1189 VALUE str;
1190 int nosync;
1191 };
1192
1193 static VALUE
1194 io_binwrite_string(VALUE arg)
1195 {
1196 struct binwrite_arg *p = (struct binwrite_arg *)arg;
1197 long l = io_writable_length(p->fptr, p->length);
1198 return rb_write_internal2(p->fptr->fd, p->ptr, l);
1199 }
1200
1201 static long
1202 io_binwrite(VALUE str, const char *ptr, long len, rb_io_t *fptr, int nosync)
1203 {
1204 long n, r, offset = 0;
1205
1206 /* don't write anything if current thread has a pending interrupt. */
1207 rb_thread_check_ints();
1208
1209 if ((n = len) <= 0) return n;
1210 if (fptr->wbuf.ptr == NULL && !(!nosync && (fptr->mode & FMODE_SYNC))) {
1211 fptr->wbuf.off = 0;
1212 fptr->wbuf.len = 0;
1213 fptr->wbuf.capa = IO_WBUF_CAPA_MIN;
1214 fptr->wbuf.ptr = ALLOC_N(char, fptr->wbuf.capa);
1215 fptr->write_lock = rb_mutex_new();
1216 rb_mutex_allow_trap(fptr->write_lock, 1);
1217 }
1218 if ((!nosync && (fptr->mode & (FMODE_SYNC|FMODE_TTY))) ||
1219 (fptr->wbuf.ptr && fptr->wbuf.capa <= fptr->wbuf.len + len)) {
1220 struct binwrite_arg arg;
1221
1222 /*
1223 * xxx: use writev to avoid double write if available
1224 * writev may help avoid context switch between "a" and "\n" in
1225 * STDERR.puts "a" [ruby-dev:25080] (rebroken since native threads
1226 * introduced in 1.9)
1227 */
1228 if (fptr->wbuf.len && fptr->wbuf.len+len <= fptr->wbuf.capa) {
1229 if (fptr->wbuf.capa < fptr->wbuf.off+fptr->wbuf.len+len) {
1230 MEMMOVE(fptr->wbuf.ptr, fptr->wbuf.ptr+fptr->wbuf.off, char, fptr->wbuf.len);
1231 fptr->wbuf.off = 0;
1232 }
1233 MEMMOVE(fptr->wbuf.ptr+fptr->wbuf.off+fptr->wbuf.len, ptr+offset, char, len);
1234 fptr->wbuf.len += (int)len;
1235 n = 0;
1236 }
1237 if (io_fflush(fptr) < 0)
1238 return -1L;
1239 if (n == 0)
1240 return len;
1241
1242 rb_io_check_closed(fptr);
1243 arg.fptr = fptr;
1244 arg.str = str;
1245 retry:
1246 arg.ptr = ptr + offset;
1247 arg.length = n;
1248 if (fptr->write_lock) {
1249 r = rb_mutex_synchronize(fptr->write_lock, io_binwrite_string, (VALUE)&arg);
1250 }
1251 else {
1252 long l = io_writable_length(fptr, n);
1253 r = rb_write_internal(fptr->fd, ptr+offset, l);
1254 }
1255 /* xxx: other threads may modify given string. */
1256 if (r == n) return len;
1257 if (0 <= r) {
1258 offset += r;
1259 n -= r;
1260 errno = EAGAIN;
1261 }
1262 if (rb_io_wait_writable(fptr->fd)) {
1263 rb_io_check_closed(fptr);
1264 if (offset < len)
1265 goto retry;
1266 }
1267 return -1L;
1268 }
1269
1270 if (fptr->wbuf.off) {
1271 if (fptr->wbuf.len)
1272 MEMMOVE(fptr->wbuf.ptr, fptr->wbuf.ptr+fptr->wbuf.off, char, fptr->wbuf.len);
1273 fptr->wbuf.off = 0;
1274 }
1275 MEMMOVE(fptr->wbuf.ptr+fptr->wbuf.off+fptr->wbuf.len, ptr+offset, char, len);
1276 fptr->wbuf.len += (int)len;
1277 return len;
1278 }
1279
1280 # define MODE_BTMODE(a,b,c) ((fmode & FMODE_BINMODE) ? (b) : \
1281 (fmode & FMODE_TEXTMODE) ? (c) : (a))
1282 static VALUE
1283 do_writeconv(VALUE str, rb_io_t *fptr)
1284 {
1285 if (NEED_WRITECONV(fptr)) {
1286 VALUE common_encoding = Qnil;
1287 SET_BINARY_MODE(fptr);
1288
1289 make_writeconv(fptr);
1290
1291 if (fptr->writeconv) {
1292 #define fmode (fptr->mode)
1293 if (!NIL_P(fptr->writeconv_asciicompat))
1294 common_encoding = fptr->writeconv_asciicompat;
1295 else if (MODE_BTMODE(DEFAULT_TEXTMODE,0,1) && !rb_enc_asciicompat(rb_enc_get(str))) {
1296 rb_raise(rb_eArgError, "ASCII incompatible string written for text mode IO without encoding conversion: %s",
1297 rb_enc_name(rb_enc_get(str)));
1298 }
1299 #undef fmode
1300 }
1301 else {
1302 if (fptr->encs.enc2)
1303 common_encoding = rb_enc_from_encoding(fptr->encs.enc2);
1304 else if (fptr->encs.enc != rb_ascii8bit_encoding())
1305 common_encoding = rb_enc_from_encoding(fptr->encs.enc);
1306 }
1307
1308 if (!NIL_P(common_encoding)) {
1309 str = rb_str_encode(str, common_encoding,
1310 fptr->writeconv_pre_ecflags, fptr->writeconv_pre_ecopts);
1311 }
1312
1313 if (fptr->writeconv) {
1314 str = rb_econv_str_convert(fptr->writeconv, str, ECONV_PARTIAL_INPUT);
1315 }
1316 }
1317 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
1318 #define fmode (fptr->mode)
1319 else if (MODE_BTMODE(DEFAULT_TEXTMODE,0,1)) {
1320 if ((fptr->mode & FMODE_READABLE) &&
1321 !(fptr->encs.ecflags & ECONV_NEWLINE_DECORATOR_MASK)) {
1322 setmode(fptr->fd, O_BINARY);
1323 }
1324 else {
1325 setmode(fptr->fd, O_TEXT);
1326 }
1327 if (!rb_enc_asciicompat(rb_enc_get(str))) {
1328 rb_raise(rb_eArgError, "ASCII incompatible string written for text mode IO without encoding conversion: %s",
1329 rb_enc_name(rb_enc_get(str)));
1330 }
1331 }
1332 #undef fmode
1333 #endif
1334 return str;
1335 }
1336
1337 static long
1338 io_fwrite(VALUE str, rb_io_t *fptr, int nosync)
1339 {
1340 #ifdef _WIN32
1341 if (fptr->mode & FMODE_TTY) {
1342 long len = rb_w32_write_console(str, fptr->fd);
1343 if (len > 0) return len;
1344 }
1345 #endif
1346 str = do_writeconv(str, fptr);
1347 return io_binwrite(str, RSTRING_PTR(str), RSTRING_LEN(str),
1348 fptr, nosync);
1349 }
1350
1351 ssize_t
1352 rb_io_bufwrite(VALUE io, const void *buf, size_t size)
1353 {
1354 rb_io_t *fptr;
1355
1356 GetOpenFile(io, fptr);
1357 rb_io_check_writable(fptr);
1358 return (ssize_t)io_binwrite(0, buf, (long)size, fptr, 0);
1359 }
1360
1361 static VALUE
1362 io_write(VALUE io, VALUE str, int nosync)
1363 {
1364 rb_io_t *fptr;
1365 long n;
1366 VALUE tmp;
1367
1368 rb_secure(4);
1369 io = GetWriteIO(io);
1370 str = rb_obj_as_string(str);
1371 tmp = rb_io_check_io(io);
1372 if (NIL_P(tmp)) {
1373 /* port is not IO, call write method for it. */
1374 return rb_funcall(io, id_write, 1, str);
1375 }
1376 io = tmp;
1377 if (RSTRING_LEN(str) == 0) return INT2FIX(0);
1378
1379 str = rb_str_new_frozen(str);
1380
1381 GetOpenFile(io, fptr);
1382 rb_io_check_writable(fptr);
1383
1384 n = io_fwrite(str, fptr, nosync);
1385 if (n == -1L) rb_sys_fail_path(fptr->pathv);
1386
1387 return LONG2FIX(n);
1388 }
1389
1390 /*
1391 * call-seq:
1392 * ios.write(string) -> integer
1393 *
1394 * Writes the given string to <em>ios</em>. The stream must be opened
1395 * for writing. If the argument is not a string, it will be converted
1396 * to a string using <code>to_s</code>. Returns the number of bytes
1397 * written.
1398 *
1399 * count = $stdout.write("This is a test\n")
1400 * puts "That was #{count} bytes of data"
1401 *
1402 * <em>produces:</em>
1403 *
1404 * This is a test
1405 * That was 15 bytes of data
1406 */
1407
1408 static VALUE
1409 io_write_m(VALUE io, VALUE str)
1410 {
1411 return io_write(io, str, 0);
1412 }
1413
1414 VALUE
1415 rb_io_write(VALUE io, VALUE str)
1416 {
1417 return rb_funcall(io, id_write, 1, str);
1418 }
1419
1420 /*
1421 * call-seq:
1422 * ios << obj -> ios
1423 *
1424 * String Output---Writes <i>obj</i> to <em>ios</em>.
1425 * <i>obj</i> will be converted to a string using
1426 * <code>to_s</code>.
1427 *
1428 * $stdout << "Hello " << "world!\n"
1429 *
1430 * <em>produces:</em>
1431 *
1432 * Hello world!
1433 */
1434
1435
1436 VALUE
1437 rb_io_addstr(VALUE io, VALUE str)
1438 {
1439 rb_io_write(io, str);
1440 return io;
1441 }
1442
1443 #ifdef HAVE_FSYNC
1444 static VALUE
1445 nogvl_fsync(void *ptr)
1446 {
1447 rb_io_t *fptr = ptr;
1448
1449 return (VALUE)fsync(fptr->fd);
1450 }
1451 #endif
1452
1453 /*
1454 * call-seq:
1455 * ios.flush -> ios
1456 *
1457 * Flushes any buffered data within <em>ios</em> to the underlying
1458 * operating system (note that this is Ruby internal buffering only;
1459 * the OS may buffer the data as well).
1460 *
1461 * $stdout.print "no newline"
1462 * $stdout.flush
1463 *
1464 * <em>produces:</em>
1465 *
1466 * no newline
1467 */
1468
1469 VALUE
1470 rb_io_flush(VALUE io)
1471 {
1472 rb_io_t *fptr;
1473
1474 if (!RB_TYPE_P(io, T_FILE)) {
1475 return rb_funcall(io, id_flush, 0);
1476 }
1477
1478 io = GetWriteIO(io);
1479 GetOpenFile(io, fptr);
1480
1481 if (fptr->mode & FMODE_WRITABLE) {
1482 if (io_fflush(fptr) < 0)
1483 rb_sys_fail(0);
1484 #ifdef _WIN32
1485 if (GetFileType((HANDLE)rb_w32_get_osfhandle(fptr->fd)) == FILE_TYPE_DISK) {
1486 rb_thread_io_blocking_region(nogvl_fsync, fptr, fptr->fd);
1487 }
1488 #endif
1489 }
1490 if (fptr->mode & FMODE_READABLE) {
1491 io_unread(fptr);
1492 }
1493
1494 return io;
1495 }
1496
1497 /*
1498 * call-seq:
1499 * ios.pos -> integer
1500 * ios.tell -> integer
1501 *
1502 * Returns the current offset (in bytes) of <em>ios</em>.
1503 *
1504 * f = File.new("testfile")
1505 * f.pos #=> 0
1506 * f.gets #=> "This is line one\n"
1507 * f.pos #=> 17
1508 */
1509
1510 static VALUE
1511 rb_io_tell(VALUE io)
1512 {
1513 rb_io_t *fptr;
1514 off_t pos;
1515
1516 GetOpenFile(io, fptr);
1517 pos = io_tell(fptr);
1518 if (pos < 0 && errno) rb_sys_fail_path(fptr->pathv);
1519 pos -= fptr->rbuf.len;
1520 return OFFT2NUM(pos);
1521 }
1522
1523 static VALUE
1524 rb_io_seek(VALUE io, VALUE offset, int whence)
1525 {
1526 rb_io_t *fptr;
1527 off_t pos;
1528
1529 pos = NUM2OFFT(offset);
1530 GetOpenFile(io, fptr);
1531 pos = io_seek(fptr, pos, whence);
1532 if (pos < 0 && errno) rb_sys_fail_path(fptr->pathv);
1533
1534 return INT2FIX(0);
1535 }
1536
1537 /*
1538 * call-seq:
1539 * ios.seek(amount, whence=IO::SEEK_SET) -> 0
1540 *
1541 * Seeks to a given offset <i>anInteger</i> in the stream according to
1542 * the value of <i>whence</i>:
1543 *
1544 * IO::SEEK_CUR | Seeks to _amount_ plus current position
1545 * --------------+----------------------------------------------------
1546 * IO::SEEK_END | Seeks to _amount_ plus end of stream (you probably
1547 * | want a negative value for _amount_)
1548 * --------------+----------------------------------------------------
1549 * IO::SEEK_SET | Seeks to the absolute location given by _amount_
1550 *
1551 * Example:
1552 *
1553 * f = File.new("testfile")
1554 * f.seek(-13, IO::SEEK_END) #=> 0
1555 * f.readline #=> "And so on...\n"
1556 */
1557
1558 static VALUE
1559 rb_io_seek_m(int argc, VALUE *argv, VALUE io)
1560 {
1561 VALUE offset, ptrname;
1562 int whence = SEEK_SET;
1563
1564 if (rb_scan_args(argc, argv, "11", &offset, &ptrname) == 2) {
1565 whence = NUM2INT(ptrname);
1566 }
1567
1568 return rb_io_seek(io, offset, whence);
1569 }
1570
1571 /*
1572 * call-seq:
1573 * ios.pos = integer -> integer
1574 *
1575 * Seeks to the given position (in bytes) in <em>ios</em>.
1576 * It is not guranteed that seeking to the right position when <em>ios</em>
1577 * is textmode.
1578 *
1579 * f = File.new("testfile")
1580 * f.pos = 17
1581 * f.gets #=> "This is line two\n"
1582 */
1583
1584 static VALUE
1585 rb_io_set_pos(VALUE io, VALUE offset)
1586 {
1587 rb_io_t *fptr;
1588 off_t pos;
1589
1590 pos = NUM2OFFT(offset);
1591 GetOpenFile(io, fptr);
1592 pos = io_seek(fptr, pos, SEEK_SET);
1593 if (pos < 0 && errno) rb_sys_fail_path(fptr->pathv);
1594
1595 return OFFT2NUM(pos);
1596 }
1597
1598 static void clear_readconv(rb_io_t *fptr);
1599
1600 /*
1601 * call-seq:
1602 * ios.rewind -> 0
1603 *
1604 * Positions <em>ios</em> to the beginning of input, resetting
1605 * <code>lineno</code> to zero.
1606 *
1607 * f = File.new("testfile")
1608 * f.readline #=> "This is line one\n"
1609 * f.rewind #=> 0
1610 * f.lineno #=> 0
1611 * f.readline #=> "This is line one\n"
1612 *
1613 * Note that it cannot be used with streams such as pipes, ttys, and sockets.
1614 */
1615
1616 static VALUE
1617 rb_io_rewind(VALUE io)
1618 {
1619 rb_io_t *fptr;
1620
1621 GetOpenFile(io, fptr);
1622 if (io_seek(fptr, 0L, 0) < 0 && errno) rb_sys_fail_path(fptr->pathv);
1623 #ifdef _WIN32
1624 if (GetFileType((HANDLE)rb_w32_get_osfhandle(fptr->fd)) == FILE_TYPE_DISK) {
1625 fsync(fptr->fd);
1626 }
1627 #endif
1628 if (io == ARGF.current_file) {
1629 ARGF.lineno -= fptr->lineno;
1630 }
1631 fptr->lineno = 0;
1632 if (fptr->readconv) {
1633 clear_readconv(fptr);
1634 }
1635
1636 return INT2FIX(0);
1637 }
1638
1639 static int
1640 io_fillbuf(rb_io_t *fptr)
1641 {
1642 ssize_t r;
1643
1644 if (fptr->rbuf.ptr == NULL) {
1645 fptr->rbuf.off = 0;
1646 fptr->rbuf.len = 0;
1647 fptr->rbuf.capa = IO_RBUF_CAPA_FOR(fptr);
1648 fptr->rbuf.ptr = ALLOC_N(char, fptr->rbuf.capa);
1649 #ifdef _WIN32
1650 fptr->rbuf.capa--;
1651 #endif
1652 }
1653 if (fptr->rbuf.len == 0) {
1654 retry:
1655 {
1656 r = rb_read_internal(fptr->fd, fptr->rbuf.ptr, fptr->rbuf.capa);
1657 }
1658 if (r < 0) {
1659 if (rb_io_wait_readable(fptr->fd))
1660 goto retry;
1661 rb_sys_fail_path(fptr->pathv);
1662 }
1663 fptr->rbuf.off = 0;
1664 fptr->rbuf.len = (int)r; /* r should be <= rbuf_capa */
1665 if (r == 0)
1666 return -1; /* EOF */
1667 }
1668 return 0;
1669 }
1670
1671 /*
1672 * call-seq:
1673 * ios.eof -> true or false
1674 * ios.eof? -> true or false
1675 *
1676 * Returns true if <em>ios</em> is at end of file that means
1677 * there are no more data to read.
1678 * The stream must be opened for reading or an <code>IOError</code> will be
1679 * raised.
1680 *
1681 * f = File.new("testfile")
1682 * dummy = f.readlines
1683 * f.eof #=> true
1684 *
1685 * If <em>ios</em> is a stream such as pipe or socket, <code>IO#eof?</code>
1686 * blocks until the other end sends some data or closes it.
1687 *
1688 * r, w = IO.pipe
1689 * Thread.new { sleep 1; w.close }
1690 * r.eof? #=> true after 1 second blocking
1691 *
1692 * r, w = IO.pipe
1693 * Thread.new { sleep 1; w.puts "a" }
1694 * r.eof? #=> false after 1 second blocking
1695 *
1696 * r, w = IO.pipe
1697 * r.eof? # blocks forever
1698 *
1699 * Note that <code>IO#eof?</code> reads data to the input byte buffer.
1700 * So <code>IO#sysread</code> may not behave as you intend with
1701 * <code>IO#eof?</code>, unless you call <code>IO#rewind</code>
1702 * first (which is not available for some streams).
1703 */
1704
1705 VALUE
1706 rb_io_eof(VALUE io)
1707 {
1708 rb_io_t *fptr;
1709
1710 GetOpenFile(io, fptr);
1711 rb_io_check_char_readable(fptr);
1712
1713 if (READ_CHAR_PENDING(fptr)) return Qfalse;
1714 if (READ_DATA_PENDING(fptr)) return Qfalse;
1715 READ_CHECK(fptr);
1716 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
1717 if (!NEED_READCONV(fptr) && NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {
1718 return eof(fptr->fd) ? Qtrue : Qfalse;
1719 }
1720 #endif
1721 if (io_fillbuf(fptr) < 0) {
1722 return Qtrue;
1723 }
1724 return Qfalse;
1725 }
1726
1727 /*
1728 * call-seq:
1729 * ios.sync -> true or false
1730 *
1731 * Returns the current ``sync mode'' of <em>ios</em>. When sync mode is
1732 * true, all output is immediately flushed to the underlying operating
1733 * system and is not buffered by Ruby internally. See also
1734 * <code>IO#fsync</code>.
1735 *
1736 * f = File.new("testfile")
1737 * f.sync #=> false
1738 */
1739
1740 static VALUE
1741 rb_io_sync(VALUE io)
1742 {
1743 rb_io_t *fptr;
1744
1745 io = GetWriteIO(io);
1746 GetOpenFile(io, fptr);
1747 return (fptr->mode & FMODE_SYNC) ? Qtrue : Qfalse;
1748 }
1749
1750 #ifdef HAVE_FSYNC
1751
1752 /*
1753 * call-seq:
1754 * ios.sync = boolean -> boolean
1755 *
1756 * Sets the ``sync mode'' to <code>true</code> or <code>false</code>.
1757 * When sync mode is true, all output is immediately flushed to the
1758 * underlying operating system and is not buffered internally. Returns
1759 * the new state. See also <code>IO#fsync</code>.
1760 *
1761 * f = File.new("testfile")
1762 * f.sync = true
1763 *
1764 * <em>(produces no output)</em>
1765 */
1766
1767 static VALUE
1768 rb_io_set_sync(VALUE io, VALUE sync)
1769 {
1770 rb_io_t *fptr;
1771
1772 io = GetWriteIO(io);
1773 GetOpenFile(io, fptr);
1774 if (RTEST(sync)) {
1775 fptr->mode |= FMODE_SYNC;
1776 }
1777 else {
1778 fptr->mode &= ~FMODE_SYNC;
1779 }
1780 return sync;
1781 }
1782
1783 /*
1784 * call-seq:
1785 * ios.fsync -> 0 or nil
1786 *
1787 * Immediately writes all buffered data in <em>ios</em> to disk.
1788 * Note that <code>fsync</code> differs from
1789 * using <code>IO#sync=</code>. The latter ensures that data is flushed
1790 * from Ruby's buffers, but does not guarantee that the underlying
1791 * operating system actually writes it to disk.
1792 *
1793 * <code>NotImplementedError</code> is raised
1794 * if the underlying operating system does not support <em>fsync(2)</em>.
1795 */
1796
1797 static VALUE
1798 rb_io_fsync(VALUE io)
1799 {
1800 rb_io_t *fptr;
1801
1802 io = GetWriteIO(io);
1803 GetOpenFile(io, fptr);
1804
1805 if (io_fflush(fptr) < 0)
1806 rb_sys_fail(0);
1807 # ifndef _WIN32 /* already called in io_fflush() */
1808 if ((int)rb_thread_io_blocking_region(nogvl_fsync, fptr, fptr->fd) < 0)
1809 rb_sys_fail_path(fptr->pathv);
1810 # endif
1811 return INT2FIX(0);
1812 }
1813 #else
1814 # define rb_io_fsync rb_f_notimplement
1815 # define rb_io_sync rb_f_notimplement
1816 static VALUE
1817 rb_io_set_sync(VALUE io, VALUE sync)
1818 {
1819 rb_notimplement();
1820 UNREACHABLE;
1821 }
1822 #endif
1823
1824 #ifdef HAVE_FDATASYNC
1825 static VALUE
1826 nogvl_fdatasync(void *ptr)
1827 {
1828 rb_io_t *fptr = ptr;
1829
1830 return (VALUE)fdatasync(fptr->fd);
1831 }
1832
1833 /*
1834 * call-seq:
1835 * ios.fdatasync -> 0 or nil
1836 *
1837 * Immediately writes all buffered data in <em>ios</em> to disk.
1838 *
1839 * If the underlying operating system does not support <em>fdatasync(2)</em>,
1840 * <code>IO#fsync</code> is called instead (which might raise a
1841 * <code>NotImplementedError</code>).
1842 */
1843
1844 static VALUE
1845 rb_io_fdatasync(VALUE io)
1846 {
1847 rb_io_t *fptr;
1848
1849 io = GetWriteIO(io);
1850 GetOpenFile(io, fptr);
1851
1852 if (io_fflush(fptr) < 0)
1853 rb_sys_fail(0);
1854
1855 if ((int)rb_thread_io_blocking_region(nogvl_fdatasync, fptr, fptr->fd) == 0)
1856 return INT2FIX(0);
1857
1858 /* fall back */
1859 return rb_io_fsync(io);
1860 }
1861 #else
1862 #define rb_io_fdatasync rb_io_fsync
1863 #endif
1864
1865 /*
1866 * call-seq:
1867 * ios.fileno -> fixnum
1868 * ios.to_i -> fixnum
1869 *
1870 * Returns an integer representing the numeric file descriptor for
1871 * <em>ios</em>.
1872 *
1873 * $stdin.fileno #=> 0
1874 * $stdout.fileno #=> 1
1875 */
1876
1877 static VALUE
1878 rb_io_fileno(VALUE io)
1879 {
1880 rb_io_t *fptr;
1881 int fd;
1882
1883 GetOpenFile(io, fptr);
1884 fd = fptr->fd;
1885 return INT2FIX(fd);
1886 }
1887
1888
1889 /*
1890 * call-seq:
1891 * ios.pid -> fixnum
1892 *
1893 * Returns the process ID of a child process associated with
1894 * <em>ios</em>. This will be set by <code>IO.popen</code>.
1895 *
1896 * pipe = IO.popen("-")
1897 * if pipe
1898 * $stderr.puts "In parent, child pid is #{pipe.pid}"
1899 * else
1900 * $stderr.puts "In child, pid is #{$$}"
1901 * end
1902 *
1903 * <em>produces:</em>
1904 *
1905 * In child, pid is 26209
1906 * In parent, child pid is 26209
1907 */
1908
1909 static VALUE
1910 rb_io_pid(VALUE io)
1911 {
1912 rb_io_t *fptr;
1913
1914 GetOpenFile(io, fptr);
1915 if (!fptr->pid)
1916 return Qnil;
1917 return PIDT2NUM(fptr->pid);
1918 }
1919
1920
1921 /*
1922 * call-seq:
1923 * ios.inspect -> string
1924 *
1925 * Return a string describing this IO object.
1926 */
1927
1928 static VALUE
1929 rb_io_inspect(VALUE obj)
1930 {
1931 rb_io_t *fptr;
1932 VALUE result;
1933 static const char closed[] = " (closed)";
1934
1935 fptr = RFILE(rb_io_taint_check(obj))->fptr;
1936 if (!fptr) return rb_any_to_s(obj);
1937 result = rb_str_new_cstr("#<");
1938 rb_str_append(result, rb_class_name(CLASS_OF(obj)));
1939 rb_str_cat2(result, ":");
1940 if (NIL_P(fptr->pathv)) {
1941 if (fptr->fd < 0) {
1942 rb_str_cat(result, closed+1, strlen(closed)-1);
1943 }
1944 else {
1945 rb_str_catf(result, "fd %d", fptr->fd);
1946 }
1947 }
1948 else {
1949 rb_str_append(result, fptr->pathv);
1950 if (fptr->fd < 0) {
1951 rb_str_cat(result, closed, strlen(closed));
1952 }
1953 }
1954 return rb_str_cat2(result, ">");
1955 }
1956
1957 /*
1958 * call-seq:
1959 * ios.to_io -> ios
1960 *
1961 * Returns <em>ios</em>.
1962 */
1963
1964 static VALUE
1965 rb_io_to_io(VALUE io)
1966 {
1967 return io;
1968 }
1969
1970 /* reading functions */
1971 static long
1972 read_buffered_data(char *ptr, long len, rb_io_t *fptr)
1973 {
1974 int n;
1975
1976 n = READ_DATA_PENDING_COUNT(fptr);
1977 if (n <= 0) return 0;
1978 if (n > len) n = (int)len;
1979 MEMMOVE(ptr, fptr->rbuf.ptr+fptr->rbuf.off, char, n);
1980 fptr->rbuf.off += n;
1981 fptr->rbuf.len -= n;
1982 return n;
1983 }
1984
1985 static long
1986 io_bufread(char *ptr, long len, rb_io_t *fptr)
1987 {
1988 long offset = 0;
1989 long n = len;
1990 long c;
1991
1992 if (READ_DATA_PENDING(fptr) == 0) {
1993 while (n > 0) {
1994 again:
1995 c = rb_read_internal(fptr->fd, ptr+offset, n);
1996 if (c == 0) break;
1997 if (c < 0) {
1998 if (rb_io_wait_readable(fptr->fd))
1999 goto again;
2000 return -1;
2001 }
2002 offset += c;
2003 if ((n -= c) <= 0) break;
2004 }
2005 return len - n;
2006 }
2007
2008 while (n > 0) {
2009 c = read_buffered_data(ptr+offset, n, fptr);
2010 if (c > 0) {
2011 offset += c;
2012 if ((n -= c) <= 0) break;
2013 }
2014 rb_io_check_closed(fptr);
2015 if (io_fillbuf(fptr) < 0) {
2016 break;
2017 }
2018 }
2019 return len - n;
2020 }
2021
2022 static void io_setstrbuf(VALUE *str, long len);
2023
2024 struct bufread_arg {
2025 char *str_ptr;
2026 long len;
2027 rb_io_t *fptr;
2028 };
2029
2030 static VALUE
2031 bufread_call(VALUE arg)
2032 {
2033 struct bufread_arg *p = (struct bufread_arg *)arg;
2034 p->len = io_bufread(p->str_ptr, p->len, p->fptr);
2035 return Qundef;
2036 }
2037
2038 static long
2039 io_fread(VALUE str, long offset, long size, rb_io_t *fptr)
2040 {
2041 long len;
2042 struct bufread_arg arg;
2043
2044 io_setstrbuf(&str, offset + size);
2045 arg.str_ptr = RSTRING_PTR(str) + offset;
2046 arg.len = size;
2047 arg.fptr = fptr;
2048 rb_str_locktmp_ensure(str, bufread_call, (VALUE)&arg);
2049 len = arg.len;
2050 if (len < 0) rb_sys_fail_path(fptr->pathv);
2051 return len;
2052 }
2053
2054 ssize_t
2055 rb_io_bufread(VALUE io, void *buf, size_t size)
2056 {
2057 rb_io_t *fptr;
2058
2059 GetOpenFile(io, fptr);
2060 rb_io_check_readable(fptr);
2061 return (ssize_t)io_bufread(buf, (long)size, fptr);
2062 }
2063
2064 #define SMALLBUF 100
2065
2066 static long
2067 remain_size(rb_io_t *fptr)
2068 {
2069 struct stat st;
2070 off_t siz = READ_DATA_PENDING_COUNT(fptr);
2071 off_t pos;
2072
2073 if (fstat(fptr->fd, &st) == 0 && S_ISREG(st.st_mode)
2074 #if defined(__BEOS__) || defined(__HAIKU__)
2075 && (st.st_dev > 3)
2076 #endif
2077 )
2078 {
2079 if (io_fflush(fptr) < 0)
2080 rb_sys_fail(0);
2081 pos = lseek(fptr->fd, 0, SEEK_CUR);
2082 if (st.st_size >= pos && pos >= 0) {
2083 siz += st.st_size - pos;
2084 if (siz > LONG_MAX) {
2085 rb_raise(rb_eIOError, "file too big for single read");
2086 }
2087 }
2088 }
2089 else {
2090 siz += BUFSIZ;
2091 }
2092 return (long)siz;
2093 }
2094
2095 static VALUE
2096 io_enc_str(VALUE str, rb_io_t *fptr)
2097 {
2098 OBJ_TAINT(str);
2099 rb_enc_associate(str, io_read_encoding(fptr));
2100 return str;
2101 }
2102
2103 static void
2104 make_readconv(rb_io_t *fptr, int size)
2105 {
2106 if (!fptr->readconv) {
2107 int ecflags;
2108 VALUE ecopts;
2109 const char *sname, *dname;
2110 ecflags = fptr->encs.ecflags & ~ECONV_NEWLINE_DECORATOR_WRITE_MASK;
2111 ecopts = fptr->encs.ecopts;
2112 if (fptr->encs.enc2) {
2113 sname = rb_enc_name(fptr->encs.enc2);
2114 dname = rb_enc_name(fptr->encs.enc);
2115 }
2116 else {
2117 sname = dname = "";
2118 }
2119 fptr->readconv = rb_econv_open_opts(sname, dname, ecflags, ecopts);
2120 if (!fptr->readconv)
2121 rb_exc_raise(rb_econv_open_exc(sname, dname, ecflags));
2122 fptr->cbuf.off = 0;
2123 fptr->cbuf.len = 0;
2124 if (size < IO_CBUF_CAPA_MIN) size = IO_CBUF_CAPA_MIN;
2125 fptr->cbuf.capa = size;
2126 fptr->cbuf.ptr = ALLOC_N(char, fptr->cbuf.capa);
2127 }
2128 }
2129
2130 #define MORE_CHAR_SUSPENDED Qtrue
2131 #define MORE_CHAR_FINISHED Qnil
2132 static VALUE
2133 fill_cbuf(rb_io_t *fptr, int ec_flags)
2134 {
2135 const unsigned char *ss, *sp, *se;
2136 unsigned char *ds, *dp, *de;
2137 rb_econv_result_t res;
2138 int putbackable;
2139 int cbuf_len0;
2140 VALUE exc;
2141
2142 ec_flags |= ECONV_PARTIAL_INPUT;
2143
2144 if (fptr->cbuf.len == fptr->cbuf.capa)
2145 return MORE_CHAR_SUSPENDED; /* cbuf full */
2146 if (fptr->cbuf.len == 0)
2147 fptr->cbuf.off = 0;
2148 else if (fptr->cbuf.off + fptr->cbuf.len == fptr->cbuf.capa) {
2149 memmove(fptr->cbuf.ptr, fptr->cbuf.ptr+fptr->cbuf.off, fptr->cbuf.len);
2150 fptr->cbuf.off = 0;
2151 }
2152
2153 cbuf_len0 = fptr->cbuf.len;
2154
2155 while (1) {
2156 ss = sp = (const unsigned char *)fptr->rbuf.ptr + fptr->rbuf.off;
2157 se = sp + fptr->rbuf.len;
2158 ds = dp = (unsigned char *)fptr->cbuf.ptr + fptr->cbuf.off + fptr->cbuf.len;
2159 de = (unsigned char *)fptr->cbuf.ptr + fptr->cbuf.capa;
2160 res = rb_econv_convert(fptr->readconv, &sp, se, &dp, de, ec_flags);
2161 fptr->rbuf.off += (int)(sp - ss);
2162 fptr->rbuf.len -= (int)(sp - ss);
2163 fptr->cbuf.len += (int)(dp - ds);
2164
2165 putbackable = rb_econv_putbackable(fptr->readconv);
2166 if (putbackable) {
2167 rb_econv_putback(fptr->readconv, (unsigned char *)fptr->rbuf.ptr + fptr->rbuf.off - putbackable, putbackable);
2168 fptr->rbuf.off -= putbackable;
2169 fptr->rbuf.len += putbackable;
2170 }
2171
2172 exc = rb_econv_make_exception(fptr->readconv);
2173 if (!NIL_P(exc))
2174 return exc;
2175
2176 if (cbuf_len0 != fptr->cbuf.len)
2177 return MORE_CHAR_SUSPENDED;
2178
2179 if (res == econv_finished) {
2180 return MORE_CHAR_FINISHED;
2181 }
2182
2183 if (res == econv_source_buffer_empty) {
2184 if (fptr->rbuf.len == 0) {
2185 READ_CHECK(fptr);
2186 if (io_fillbuf(fptr) == -1) {
2187 if (!fptr->readconv) {
2188 return MORE_CHAR_FINISHED;
2189 }
2190 ds = dp = (unsigned char *)fptr->cbuf.ptr + fptr->cbuf.off + fptr->cbuf.len;
2191 de = (unsigned char *)fptr->cbuf.ptr + fptr->cbuf.capa;
2192 res = rb_econv_convert(fptr->readconv, NULL, NULL, &dp, de, 0);
2193 fptr->cbuf.len += (int)(dp - ds);
2194 rb_econv_check_error(fptr->readconv);
2195 break;
2196 }
2197 }
2198 }
2199 }
2200 if (cbuf_len0 != fptr->cbuf.len)
2201 return MORE_CHAR_SUSPENDED;
2202
2203 return MORE_CHAR_FINISHED;
2204 }
2205
2206 static VALUE
2207 more_char(rb_io_t *fptr)
2208 {
2209 VALUE v;
2210 v = fill_cbuf(fptr, ECONV_AFTER_OUTPUT);
2211 if (v != MORE_CHAR_SUSPENDED && v != MORE_CHAR_FINISHED)
2212 rb_exc_raise(v);
2213 return v;
2214 }
2215
2216 static VALUE
2217 io_shift_cbuf(rb_io_t *fptr, int len, VALUE *strp)
2218 {
2219 VALUE str = Qnil;
2220 if (strp) {
2221 str = *strp;
2222 if (NIL_P(str)) {
2223 *strp = str = rb_str_new(fptr->cbuf.ptr+fptr->cbuf.off, len);
2224 }
2225 else {
2226 rb_str_cat(str, fptr->cbuf.ptr+fptr->cbuf.off, len);
2227 }
2228 OBJ_TAINT(str);
2229 rb_enc_associate(str, fptr->encs.enc);
2230 }
2231 fptr->cbuf.off += len;
2232 fptr->cbuf.len -= len;
2233 /* xxx: set coderange */
2234 if (fptr->cbuf.len == 0)
2235 fptr->cbuf.off = 0;
2236 else if (fptr->cbuf.capa/2 < fptr->cbuf.off) {
2237 memmove(fptr->cbuf.ptr, fptr->cbuf.ptr+fptr->cbuf.off, fptr->cbuf.len);
2238 fptr->cbuf.off = 0;
2239 }
2240 return str;
2241 }
2242
2243 static void
2244 io_setstrbuf(VALUE *str, long len)
2245 {
2246 #ifdef _WIN32
2247 len = (len + 1) & ~1L; /* round up for wide char */
2248 #endif
2249 if (NIL_P(*str)) {
2250 *str = rb_str_new(0, 0);
2251 }
2252 else {
2253 VALUE s = StringValue(*str);
2254 long clen = RSTRING_LEN(s);
2255 if (clen >= len) {
2256 if (clen != len) {
2257 rb_str_modify(s);
2258 rb_str_set_len(s, len);
2259 }
2260 return;
2261 }
2262 len -= clen;
2263 }
2264 rb_str_modify_expand(*str, len);
2265 }
2266
2267 static void
2268 io_set_read_length(VALUE str, long n)
2269 {
2270 if (RSTRING_LEN(str) != n) {
2271 rb_str_modify(str);
2272 rb_str_set_len(str, n);
2273 }
2274 }
2275
2276 static VALUE
2277 read_all(rb_io_t *fptr, long siz, VALUE str)
2278 {
2279 long bytes;
2280 long n;
2281 long pos;
2282 rb_encoding *enc;
2283 int cr;
2284
2285 if (NEED_READCONV(fptr)) {
2286 SET_BINARY_MODE(fptr);
2287 io_setstrbuf(&str,0);
2288 make_readconv(fptr, 0);
2289 while (1) {
2290 VALUE v;
2291 if (fptr->cbuf.len) {
2292 io_shift_cbuf(fptr, fptr->cbuf.len, &str);
2293 }
2294 v = fill_cbuf(fptr, 0);
2295 if (v != MORE_CHAR_SUSPENDED && v != MORE_CHAR_FINISHED) {
2296 if (fptr->cbuf.len) {
2297 io_shift_cbuf(fptr, fptr->cbuf.len, &str);
2298 }
2299 rb_exc_raise(v);
2300 }
2301 if (v == MORE_CHAR_FINISHED) {
2302 clear_readconv(fptr);
2303 return io_enc_str(str, fptr);
2304 }
2305 }
2306 }
2307
2308 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
2309 bytes = 0;
2310 pos = 0;
2311
2312 enc = io_read_encoding(fptr);
2313 cr = 0;
2314
2315 if (siz == 0) siz = BUFSIZ;
2316 io_setstrbuf(&str,siz);
2317 for (;;) {
2318 READ_CHECK(fptr);
2319 n = io_fread(str, bytes, siz - bytes, fptr);
2320 if (n == 0 && bytes == 0) {
2321 rb_str_set_len(str, 0);
2322 break;
2323 }
2324 bytes += n;
2325 rb_str_set_len(str, bytes);
2326 if (cr != ENC_CODERANGE_BROKEN)
2327 pos += rb_str_coderange_scan_restartable(RSTRING_PTR(str) + pos, RSTRING_PTR(str) + bytes, enc, &cr);
2328 if (bytes < siz) break;
2329 siz += BUFSIZ;
2330 rb_str_modify_expand(str, BUFSIZ);
2331 }
2332 str = io_enc_str(str, fptr);
2333 ENC_CODERANGE_SET(str, cr);
2334 return str;
2335 }
2336
2337 void
2338 rb_io_set_nonblock(rb_io_t *fptr)
2339 {
2340 int oflags;
2341 #ifdef F_GETFL
2342 oflags = fcntl(fptr->fd, F_GETFL);
2343 if (oflags == -1) {
2344 rb_sys_fail_path(fptr->pathv);
2345 }
2346 #else
2347 oflags = 0;
2348 #endif
2349 if ((oflags & O_NONBLOCK) == 0) {
2350 oflags |= O_NONBLOCK;
2351 if (fcntl(fptr->fd, F_SETFL, oflags) == -1) {
2352 rb_sys_fail_path(fptr->pathv);
2353 }
2354 }
2355 }
2356
2357 struct read_internal_arg {
2358 int fd;
2359 char *str_ptr;
2360 long len;
2361 };
2362
2363 static VALUE
2364 read_internal_call(VALUE arg)
2365 {
2366 struct read_internal_arg *p = (struct read_internal_arg *)arg;
2367 p->len = rb_read_internal(p->fd, p->str_ptr, p->len);
2368 return Qundef;
2369 }
2370
2371 static VALUE
2372 io_getpartial(int argc, VALUE *argv, VALUE io, int nonblock)
2373 {
2374 rb_io_t *fptr;
2375 VALUE length, str;
2376 long n, len;
2377 struct read_internal_arg arg;
2378
2379 rb_scan_args(argc, argv, "11", &length, &str);
2380
2381 if ((len = NUM2LONG(length)) < 0) {
2382 rb_raise(rb_eArgError, "negative length %ld given", len);
2383 }
2384
2385 io_setstrbuf(&str,len);
2386 OBJ_TAINT(str);
2387
2388 GetOpenFile(io, fptr);
2389 rb_io_check_byte_readable(fptr);
2390
2391 if (len == 0)
2392 return str;
2393
2394 if (!nonblock)
2395 READ_CHECK(fptr);
2396 n = read_buffered_data(RSTRING_PTR(str), len, fptr);
2397 if (n <= 0) {
2398 again:
2399 if (nonblock) {
2400 rb_io_set_nonblock(fptr);
2401 }
2402 io_setstrbuf(&str, len);
2403 arg.fd = fptr->fd;
2404 arg.str_ptr = RSTRING_PTR(str);
2405 arg.len = len;
2406 rb_str_locktmp_ensure(str, read_internal_call, (VALUE)&arg);
2407 n = arg.len;
2408 if (n < 0) {
2409 if (!nonblock && rb_io_wait_readable(fptr->fd))
2410 goto again;
2411 if (nonblock && (errno == EWOULDBLOCK || errno == EAGAIN))
2412 rb_mod_sys_fail(rb_mWaitReadable, "read would block");
2413 rb_sys_fail_path(fptr->pathv);
2414 }
2415 }
2416 io_set_read_length(str, n);
2417
2418 if (n == 0)
2419 return Qnil;
2420 else
2421 return str;
2422 }
2423
2424 /*
2425 * call-seq:
2426 * ios.readpartial(maxlen) -> string
2427 * ios.readpartial(maxlen, outbuf) -> outbuf
2428 *
2429 * Reads at most <i>maxlen</i> bytes from the I/O stream.
2430 * It blocks only if <em>ios</em> has no data immediately available.
2431 * It doesn't block if some data available.
2432 * If the optional <i>outbuf</i> argument is present,
2433 * it must reference a String, which will receive the data.
2434 * The <i>outbuf</i> will contain only the received data after the method call
2435 * even if it is not empty at the beginning.
2436 * It raises <code>EOFError</code> on end of file.
2437 *
2438 * readpartial is designed for streams such as pipe, socket, tty, etc.
2439 * It blocks only when no data immediately available.
2440 * This means that it blocks only when following all conditions hold.
2441 * * the byte buffer in the IO object is empty.
2442 * * the content of the stream is empty.
2443 * * the stream is not reached to EOF.
2444 *
2445 * When readpartial blocks, it waits data or EOF on the stream.
2446 * If some data is reached, readpartial returns with the data.
2447 * If EOF is reached, readpartial raises EOFError.
2448 *
2449 * When readpartial doesn't blocks, it returns or raises immediately.
2450 * If the byte buffer is not empty, it returns the data in the buffer.
2451 * Otherwise if the stream has some content,
2452 * it returns the data in the stream.
2453 * Otherwise if the stream is reached to EOF, it raises EOFError.
2454 *
2455 * r, w = IO.pipe # buffer pipe content
2456 * w << "abc" # "" "abc".
2457 * r.readpartial(4096) #=> "abc" "" ""
2458 * r.readpartial(4096) # blocks because buffer and pipe is empty.
2459 *
2460 * r, w = IO.pipe # buffer pipe content
2461 * w << "abc" # "" "abc"
2462 * w.close # "" "abc" EOF
2463 * r.readpartial(4096) #=> "abc" "" EOF
2464 * r.readpartial(4096) # raises EOFError
2465 *
2466 * r, w = IO.pipe # buffer pipe content
2467 * w << "abc\ndef\n" # "" "abc\ndef\n"
2468 * r.gets #=> "abc\n" "def\n" ""
2469 * w << "ghi\n" # "def\n" "ghi\n"
2470 * r.readpartial(4096) #=> "def\n" "" "ghi\n"
2471 * r.readpartial(4096) #=> "ghi\n" "" ""
2472 *
2473 * Note that readpartial behaves similar to sysread.
2474 * The differences are:
2475 * * If the byte buffer is not empty, read from the byte buffer instead of "sysread for buffered IO (IOError)".
2476 * * It doesn't cause Errno::EWOULDBLOCK and Errno::EINTR. When readpartial meets EWOULDBLOCK and EINTR by read system call, readpartial retry the system call.
2477 *
2478 * The later means that readpartial is nonblocking-flag insensitive.
2479 * It blocks on the situation IO#sysread causes Errno::EWOULDBLOCK as if the fd is blocking mode.
2480 *
2481 */
2482
2483 static VALUE
2484 io_readpartial(int argc, VALUE *argv, VALUE io)
2485 {
2486 VALUE ret;
2487
2488 ret = io_getpartial(argc, argv, io, 0);
2489 if (NIL_P(ret))
2490 rb_eof_error();
2491 return ret;
2492 }
2493
2494 /*
2495 * call-seq:
2496 * ios.read_nonblock(maxlen) -> string
2497 * ios.read_nonblock(maxlen, outbuf) -> outbuf
2498 *
2499 * Reads at most <i>maxlen</i> bytes from <em>ios</em> using
2500 * the read(2) system call after O_NONBLOCK is set for
2501 * the underlying file descriptor.
2502 *
2503 * If the optional <i>outbuf</i> argument is present,
2504 * it must reference a String, which will receive the data.
2505 * The <i>outbuf</i> will contain only the received data after the method call
2506 * even if it is not empty at the beginning.
2507 *
2508 * read_nonblock just calls the read(2) system call.
2509 * It causes all errors the read(2) system call causes: Errno::EWOULDBLOCK, Errno::EINTR, etc.
2510 * The caller should care such errors.
2511 *
2512 * If the exception is Errno::EWOULDBLOCK or Errno::AGAIN,
2513 * it is extended by IO::WaitReadable.
2514 * So IO::WaitReadable can be used to rescue the exceptions for retrying read_nonblock.
2515 *
2516 * read_nonblock causes EOFError on EOF.
2517 *
2518 * If the read byte buffer is not empty,
2519 * read_nonblock reads from the buffer like readpartial.
2520 * In this case, the read(2) system call is not called.
2521 *
2522 * When read_nonblock raises an exception kind of IO::WaitReadable,
2523 * read_nonblock should not be called
2524 * until io is readable for avoiding busy loop.
2525 * This can be done as follows.
2526 *
2527 * # emulates blocking read (readpartial).
2528 * begin
2529 * result = io.read_nonblock(maxlen)
2530 * rescue IO::WaitReadable
2531 * IO.select([io])
2532 * retry
2533 * end
2534 *
2535 * Although IO#read_nonblock doesn't raise IO::WaitWritable.
2536 * OpenSSL::Buffering#read_nonblock can raise IO::WaitWritable.
2537 * If IO and SSL should be used polymorphically,
2538 * IO::WaitWritable should be rescued too.
2539 * See the document of OpenSSL::Buffering#read_nonblock for sample code.
2540 *
2541 * Note that this method is identical to readpartial
2542 * except the non-blocking flag is set.
2543 */
2544
2545 static VALUE
2546 io_read_nonblock(int argc, VALUE *argv, VALUE io)
2547 {
2548 VALUE ret;
2549
2550 ret = io_getpartial(argc, argv, io, 1);
2551 if (NIL_P(ret))
2552 rb_eof_error();
2553 return ret;
2554 }
2555
2556 /*
2557 * call-seq:
2558 * ios.write_nonblock(string) -> integer
2559 *
2560 * Writes the given string to <em>ios</em> using
2561 * the write(2) system call after O_NONBLOCK is set for
2562 * the underlying file descriptor.
2563 *
2564 * It returns the number of bytes written.
2565 *
2566 * write_nonblock just calls the write(2) system call.
2567 * It causes all errors the write(2) system call causes: Errno::EWOULDBLOCK, Errno::EINTR, etc.
2568 * The result may also be smaller than string.length (partial write).
2569 * The caller should care such errors and partial write.
2570 *
2571 * If the exception is Errno::EWOULDBLOCK or Errno::AGAIN,
2572 * it is extended by IO::WaitWritable.
2573 * So IO::WaitWritable can be used to rescue the exceptions for retrying write_nonblock.
2574 *
2575 * # Creates a pipe.
2576 * r, w = IO.pipe
2577 *
2578 * # write_nonblock writes only 65536 bytes and return 65536.
2579 * # (The pipe size is 65536 bytes on this environment.)
2580 * s = "a" * 100000
2581 * p w.write_nonblock(s) #=> 65536
2582 *
2583 * # write_nonblock cannot write a byte and raise EWOULDBLOCK (EAGAIN).
2584 * p w.write_nonblock("b") # Resource temporarily unavailable (Errno::EAGAIN)
2585 *
2586 * If the write buffer is not empty, it is flushed at first.
2587 *
2588 * When write_nonblock raises an exception kind of IO::WaitWritable,
2589 * write_nonblock should not be called
2590 * until io is writable for avoiding busy loop.
2591 * This can be done as follows.
2592 *
2593 * begin
2594 * result = io.write_nonblock(string)
2595 * rescue IO::WaitWritable, Errno::EINTR
2596 * IO.select(nil, [io])
2597 * retry
2598 * end
2599 *
2600 * Note that this doesn't guarantee to write all data in string.
2601 * The length written is reported as result and it should be checked later.
2602 *
2603 * On some platforms such as Windows, write_nonblock is not supported
2604 * according to the kind of the IO object.
2605 * In such cases, write_nonblock raises <code>Errno::EBADF</code>.
2606 *
2607 */
2608
2609 static VALUE
2610 rb_io_write_nonblock(VALUE io, VALUE str)
2611 {
2612 rb_io_t *fptr;
2613 long n;
2614
2615 rb_secure(4);
2616 if (!RB_TYPE_P(str, T_STRING))
2617 str = rb_obj_as_string(str);
2618
2619 io = GetWriteIO(io);
2620 GetOpenFile(io, fptr);
2621 rb_io_check_writable(fptr);
2622
2623 if (io_fflush(fptr) < 0)
2624 rb_sys_fail(0);
2625
2626 rb_io_set_nonblock(fptr);
2627 n = write(fptr->fd, RSTRING_PTR(str), RSTRING_LEN(str));
2628
2629 if (n == -1) {
2630 if (errno == EWOULDBLOCK || errno == EAGAIN)
2631 rb_mod_sys_fail(rb_mWaitWritable, "write would block");
2632 rb_sys_fail_path(fptr->pathv);
2633 }
2634
2635 return LONG2FIX(n);
2636 }
2637
2638 /*
2639 * call-seq:
2640 * ios.read([length [, outbuf]]) -> string, outbuf, or nil
2641 *
2642 * Reads <i>length</i> bytes from the I/O stream.
2643 *
2644 * <i>length</i> must be a non-negative integer or <code>nil</code>.
2645 *
2646 * If <i>length</i> is a positive integer,
2647 * it try to read <i>length</i> bytes without any conversion (binary mode).
2648 * It returns <code>nil</code> or a string whose length is 1 to <i>length</i> bytes.
2649 * <code>nil</code> means it met EOF at beginning.
2650 * The 1 to <i>length</i>-1 bytes string means it met EOF after reading the result.
2651 * The <i>length</i> bytes string means it doesn't meet EOF.
2652 * The resulted string is always ASCII-8BIT encoding.
2653 *
2654 * If <i>length</i> is omitted or is <code>nil</code>,
2655 * it reads until EOF and the encoding conversion is applied.
2656 * It returns a string even if EOF is met at beginning.
2657 *
2658 * If <i>length</i> is zero, it returns <code>""</code>.
2659 *
2660 * If the optional <i>outbuf</i> argument is present, it must reference
2661 * a String, which will receive the data.
2662 * The <i>outbuf</i> will contain only the received data after the method call
2663 * even if it is not empty at the beginning.
2664 *
2665 * At end of file, it returns <code>nil</code> or <code>""</code>
2666 * depend on <i>length</i>.
2667 * <code><i>ios</i>.read()</code> and
2668 * <code><i>ios</i>.read(nil)</code> returns <code>""</code>.
2669 * <code><i>ios</i>.read(<i>positive-integer</i>)</code> returns <code>nil</code>.
2670 *
2671 * f = File.new("testfile")
2672 * f.read(16) #=> "This is line one"
2673 *
2674 * # reads whole file
2675 * open("file") {|f|
2676 * data = f.read # This returns a string even if the file is empty.
2677 * ...
2678 * }
2679 *
2680 * # iterate over fixed length records.
2681 * open("fixed-record-file") {|f|
2682 * while record = f.read(256)
2683 * ...
2684 * end
2685 * }
2686 *
2687 * # iterate over variable length records.
2688 * # record is prefixed by 32-bit length.
2689 * open("variable-record-file") {|f|
2690 * while len = f.read(4)
2691 * len = len.unpack("N")[0] # 32-bit length
2692 * record = f.read(len) # This returns a string even if len is 0.
2693 * end
2694 * }
2695 *
2696 * Note that this method behaves like fread() function in C.
2697 * This means it retry to invoke read(2) system call to read data with the specified length (or until EOF).
2698 * This behavior is preserved even if <i>ios</i> is non-blocking mode.
2699 * (This method is non-blocking flag insensitive as other methods.)
2700 * If you need the behavior like single read(2) system call,
2701 * consider readpartial, read_nonblock and sysread.
2702 */
2703
2704 static VALUE
2705 io_read(int argc, VALUE *argv, VALUE io)
2706 {
2707 rb_io_t *fptr;
2708 long n, len;
2709 VALUE length, str;
2710 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
2711 int previous_mode;
2712 #endif
2713
2714 rb_scan_args(argc, argv, "02", &length, &str);
2715
2716 if (NIL_P(length)) {
2717 GetOpenFile(io, fptr);
2718 rb_io_check_char_readable(fptr);
2719 return read_all(fptr, remain_size(fptr), str);
2720 }
2721 len = NUM2LONG(length);
2722 if (len < 0) {
2723 rb_raise(rb_eArgError, "negative length %ld given", len);
2724 }
2725
2726 io_setstrbuf(&str,len);
2727
2728 GetOpenFile(io, fptr);
2729 rb_io_check_byte_readable(fptr);
2730 if (len == 0) return str;
2731
2732 READ_CHECK(fptr);
2733 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
2734 previous_mode = set_binary_mode_with_seek_cur(fptr);
2735 #endif
2736 n = io_fread(str, 0, len, fptr);
2737 io_set_read_length(str, n);
2738 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
2739 if (previous_mode == O_TEXT) {
2740 setmode(fptr->fd, O_TEXT);
2741 }
2742 #endif
2743 if (n == 0) return Qnil;
2744 OBJ_TAINT(str);
2745
2746 return str;
2747 }
2748
2749 static void
2750 rscheck(const char *rsptr, long rslen, VALUE rs)
2751 {
2752 if (!rs) return;
2753 if (RSTRING_PTR(rs) != rsptr && RSTRING_LEN(rs) != rslen)
2754 rb_raise(rb_eRuntimeError, "rs modified");
2755 }
2756
2757 static int
2758 appendline(rb_io_t *fptr, int delim, VALUE *strp, long *lp)
2759 {
2760 VALUE str = *strp;
2761 long limit = *lp;
2762
2763 if (NEED_READCONV(fptr)) {
2764 SET_BINARY_MODE(fptr);
2765 make_readconv(fptr, 0);
2766 do {
2767 const char *p, *e;
2768 int searchlen;
2769 if (fptr->cbuf.len) {
2770 p = fptr->cbuf.ptr+fptr->cbuf.off;
2771 searchlen = fptr->cbuf.len;
2772 if (0 < limit && limit < searchlen)
2773 searchlen = (int)limit;
2774 e = memchr(p, delim, searchlen);
2775 if (e) {
2776 int len = (int)(e-p+1);
2777 if (NIL_P(str))
2778 *strp = str = rb_str_new(p, len);
2779 else
2780 rb_str_buf_cat(str, p, len);
2781 fptr->cbuf.off += len;
2782 fptr->cbuf.len -= len;
2783 limit -= len;
2784 *lp = limit;
2785 return delim;
2786 }
2787
2788 if (NIL_P(str))
2789 *strp = str = rb_str_new(p, searchlen);
2790 else
2791 rb_str_buf_cat(str, p, searchlen);
2792 fptr->cbuf.off += searchlen;
2793 fptr->cbuf.len -= searchlen;
2794 limit -= searchlen;
2795
2796 if (limit == 0) {
2797 *lp = limit;
2798 return (unsigned char)RSTRING_PTR(str)[RSTRING_LEN(str)-1];
2799 }
2800 }
2801 } while (more_char(fptr) != MORE_CHAR_FINISHED);
2802 clear_readconv(fptr);
2803 *lp = limit;
2804 return EOF;
2805 }
2806
2807 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
2808 do {
2809 long pending = READ_DATA_PENDING_COUNT(fptr);
2810 if (pending > 0) {
2811 const char *p = READ_DATA_PENDING_PTR(fptr);
2812 const char *e;
2813 long last;
2814
2815 if (limit > 0 && pending > limit) pending = limit;
2816 e = memchr(p, delim, pending);
2817 if (e) pending = e - p + 1;
2818 if (!NIL_P(str)) {
2819 last = RSTRING_LEN(str);
2820 rb_str_resize(str, last + pending);
2821 }
2822 else {
2823 last = 0;
2824 *strp = str = rb_str_buf_new(pending);
2825 rb_str_set_len(str, pending);
2826 }
2827 read_buffered_data(RSTRING_PTR(str) + last, pending, fptr); /* must not fail */
2828 limit -= pending;
2829 *lp = limit;
2830 if (e) return delim;
2831 if (limit == 0)
2832 return (unsigned char)RSTRING_PTR(str)[RSTRING_LEN(str)-1];
2833 }
2834 READ_CHECK(fptr);
2835 } while (io_fillbuf(fptr) >= 0);
2836 *lp = limit;
2837 return EOF;
2838 }
2839
2840 static inline int
2841 swallow(rb_io_t *fptr, int term)
2842 {
2843 if (NEED_READCONV(fptr)) {
2844 rb_encoding *enc = io_read_encoding(fptr);
2845 int needconv = rb_enc_mbminlen(enc) != 1;
2846 SET_BINARY_MODE(fptr);
2847 make_readconv(fptr, 0);
2848 do {
2849 size_t cnt;
2850 while ((cnt = READ_CHAR_PENDING_COUNT(fptr)) > 0) {
2851 const char *p = READ_CHAR_PENDING_PTR(fptr);
2852 int i;
2853 if (!needconv) {
2854 if (*p != term) return TRUE;
2855 i = (int)cnt;
2856 while (--i && *++p == term);
2857 }
2858 else {
2859 const char *e = p + cnt;
2860 if (rb_enc_ascget(p, e, &i, enc) != term) return TRUE;
2861 while ((p += i) < e && rb_enc_ascget(p, e, &i, enc) == term);
2862 i = (int)(e - p);
2863 }
2864 io_shift_cbuf(fptr, (int)cnt - i, NULL);
2865 }
2866 } while (more_char(fptr) != MORE_CHAR_FINISHED);
2867 return FALSE;
2868 }
2869
2870 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
2871 do {
2872 size_t cnt;
2873 while ((cnt = READ_DATA_PENDING_COUNT(fptr)) > 0) {
2874 char buf[1024];
2875 const char *p = READ_DATA_PENDING_PTR(fptr);
2876 int i;
2877 if (cnt > sizeof buf) cnt = sizeof buf;
2878 if (*p != term) return TRUE;
2879 i = (int)cnt;
2880 while (--i && *++p == term);
2881 if (!read_buffered_data(buf, cnt - i, fptr)) /* must not fail */
2882 rb_sys_fail_path(fptr->pathv);
2883 }
2884 READ_CHECK(fptr);
2885 } while (io_fillbuf(fptr) == 0);
2886 return FALSE;
2887 }
2888
2889 static VALUE
2890 rb_io_getline_fast(rb_io_t *fptr, rb_encoding *enc, VALUE io)
2891 {
2892 VALUE str = Qnil;
2893 int len = 0;
2894 long pos = 0;
2895 int cr = 0;
2896
2897 for (;;) {
2898 int pending = READ_DATA_PENDING_COUNT(fptr);
2899
2900 if (pending > 0) {
2901 const char *p = READ_DATA_PENDING_PTR(fptr);
2902 const char *e;
2903
2904 e = memchr(p, '\n', pending);
2905 if (e) {
2906 pending = (int)(e - p + 1);
2907 }
2908 if (NIL_P(str)) {
2909 str = rb_str_new(p, pending);
2910 fptr->rbuf.off += pending;
2911 fptr->rbuf.len -= pending;
2912 }
2913 else {
2914 rb_str_resize(str, len + pending);
2915 read_buffered_data(RSTRING_PTR(str)+len, pending, fptr);
2916 }
2917 len += pending;
2918 if (cr != ENC_CODERANGE_BROKEN)
2919 pos += rb_str_coderange_scan_restartable(RSTRING_PTR(str) + pos, RSTRING_PTR(str) + len, enc, &cr);
2920 if (e) break;
2921 }
2922 READ_CHECK(fptr);
2923 if (io_fillbuf(fptr) < 0) {
2924 if (NIL_P(str)) return Qnil;
2925 break;
2926 }
2927 }
2928
2929 str = io_enc_str(str, fptr);
2930 ENC_CODERANGE_SET(str, cr);
2931 fptr->lineno++;
2932 if (io == ARGF.current_file) {
2933 ARGF.lineno++;
2934 ARGF.last_lineno = ARGF.lineno;
2935 }
2936 else {
2937 ARGF.last_lineno = fptr->lineno;
2938 }
2939
2940 return str;
2941 }
2942
2943 static void
2944 prepare_getline_args(int argc, VALUE *argv, VALUE *rsp, long *limit, VALUE io)
2945 {
2946 VALUE rs = rb_rs, lim = Qnil;
2947 rb_io_t *fptr;
2948
2949 if (argc == 1) {
2950 VALUE tmp = Qnil;
2951
2952 if (NIL_P(argv[0]) || !NIL_P(tmp = rb_check_string_type(argv[0]))) {
2953 rs = tmp;
2954 }
2955 else {
2956 lim = argv[0];
2957 }
2958 }
2959 else if (2 <= argc) {
2960 rb_scan_args(argc, argv, "2", &rs, &lim);
2961 if (!NIL_P(rs))
2962 StringValue(rs);
2963 }
2964 if (!NIL_P(rs)) {
2965 rb_encoding *enc_rs, *enc_io;
2966
2967 GetOpenFile(io, fptr);
2968 enc_rs = rb_enc_get(rs);
2969 enc_io = io_read_encoding(fptr);
2970 if (enc_io != enc_rs &&
2971 (rb_enc_str_coderange(rs) != ENC_CODERANGE_7BIT ||
2972 (RSTRING_LEN(rs) > 0 && !rb_enc_asciicompat(enc_io)))) {
2973 if (rs == rb_default_rs) {
2974 rs = rb_enc_str_new(0, 0, enc_io);
2975 rb_str_buf_cat_ascii(rs, "\n");
2976 }
2977 else {
2978 rb_raise(rb_eArgError, "encoding mismatch: %s IO with %s RS",
2979 rb_enc_name(enc_io),
2980 rb_enc_name(enc_rs));
2981 }
2982 }
2983 }
2984 *rsp = rs;
2985 *limit = NIL_P(lim) ? -1L : NUM2LONG(lim);
2986 }
2987
2988 static VALUE
2989 rb_io_getline_1(VALUE rs, long limit, VALUE io)
2990 {
2991 VALUE str = Qnil;
2992 rb_io_t *fptr;
2993 int nolimit = 0;
2994 rb_encoding *enc;
2995
2996 GetOpenFile(io, fptr);
2997 rb_io_check_char_readable(fptr);
2998 if (NIL_P(rs) && limit < 0) {
2999 str = read_all(fptr, 0, Qnil);
3000 if (RSTRING_LEN(str) == 0) return Qnil;
3001 }
3002 else if (limit == 0) {
3003 return rb_enc_str_new(0, 0, io_read_encoding(fptr));
3004 }
3005 else if (rs == rb_default_rs && limit < 0 && !NEED_READCONV(fptr) &&
3006 rb_enc_asciicompat(enc = io_read_encoding(fptr))) {
3007 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
3008 return rb_io_getline_fast(fptr, enc, io);
3009 }
3010 else {
3011 int c, newline = -1;
3012 const char *rsptr = 0;
3013 long rslen = 0;
3014 int rspara = 0;
3015 int extra_limit = 16;
3016
3017 SET_BINARY_MODE(fptr);
3018 enc = io_read_encoding(fptr);
3019
3020 if (!NIL_P(rs)) {
3021 rslen = RSTRING_LEN(rs);
3022 if (rslen == 0) {
3023 rsptr = "\n\n";
3024 rslen = 2;
3025 rspara = 1;
3026 swallow(fptr, '\n');
3027 rs = 0;
3028 if (!rb_enc_asciicompat(enc)) {
3029 rs = rb_usascii_str_new(rsptr, rslen);
3030 rs = rb_str_encode(rs, rb_enc_from_encoding(enc), 0, Qnil);
3031 OBJ_FREEZE(rs);
3032 rsptr = RSTRING_PTR(rs);
3033 rslen = RSTRING_LEN(rs);
3034 }
3035 }
3036 else {
3037 rsptr = RSTRING_PTR(rs);
3038 }
3039 newline = (unsigned char)rsptr[rslen - 1];
3040 }
3041
3042 /* MS - Optimisation */
3043 while ((c = appendline(fptr, newline, &str, &limit)) != EOF) {
3044 const char *s, *p, *pp, *e;
3045
3046 if (c == newline) {
3047 if (RSTRING_LEN(str) < rslen) continue;
3048 s = RSTRING_PTR(str);
3049 e = s + RSTRING_LEN(str);
3050 p = e - rslen;
3051 pp = rb_enc_left_char_head(s, p, e, enc);
3052 if (pp != p) continue;
3053 if (!rspara) rscheck(rsptr, rslen, rs);
3054 if (memcmp(p, rsptr, rslen) == 0) break;
3055 }
3056 if (limit == 0) {
3057 s = RSTRING_PTR(str);
3058 p = s + RSTRING_LEN(str);
3059 pp = rb_enc_left_char_head(s, p-1, p, enc);
3060 if (extra_limit &&
3061 MBCLEN_NEEDMORE_P(rb_enc_precise_mbclen(pp, p, enc))) {
3062 /* relax the limit while incomplete character.
3063 * extra_limit limits the relax length */
3064 limit = 1;
3065 extra_limit--;
3066 }
3067 else {
3068 nolimit = 1;
3069 break;
3070 }
3071 }
3072 }
3073
3074 if (rspara) {
3075 if (c != EOF) {
3076 swallow(fptr, '\n');
3077 }
3078 }
3079 if (!NIL_P(str))
3080 str = io_enc_str(str, fptr);
3081 }
3082
3083 if (!NIL_P(str)) {
3084 if (!nolimit) {
3085 fptr->lineno++;
3086 if (io == ARGF.current_file) {
3087 ARGF.lineno++;
3088 ARGF.last_lineno = ARGF.lineno;
3089 }
3090 else {
3091 ARGF.last_lineno = fptr->lineno;
3092 }
3093 }
3094 }
3095
3096 return str;
3097 }
3098
3099 static VALUE
3100 rb_io_getline(int argc, VALUE *argv, VALUE io)
3101 {
3102 VALUE rs;
3103 long limit;
3104
3105 prepare_getline_args(argc, argv, &rs, &limit, io);
3106 return rb_io_getline_1(rs, limit, io);
3107 }
3108
3109 VALUE
3110 rb_io_gets(VALUE io)
3111 {
3112 return rb_io_getline_1(rb_default_rs, -1, io);
3113 }
3114
3115 /*
3116 * call-seq:
3117 * ios.gets(sep=$/) -> string or nil
3118 * ios.gets(limit) -> string or nil
3119 * ios.gets(sep, limit) -> string or nil
3120 *
3121 * Reads the next ``line'' from the I/O stream; lines are separated by
3122 * <i>sep</i>. A separator of <code>nil</code> reads the entire
3123 * contents, and a zero-length separator reads the input a paragraph at
3124 * a time (two successive newlines in the input separate paragraphs).
3125 * The stream must be opened for reading or an <code>IOError</code>
3126 * will be raised. The line read in will be returned and also assigned
3127 * to <code>$_</code>. Returns <code>nil</code> if called at end of
3128 * file. If the first argument is an integer, or optional second
3129 * argument is given, the returning string would not be longer than the
3130 * given value in bytes.
3131 *
3132 * File.new("testfile").gets #=> "This is line one\n"
3133 * $_ #=> "This is line one\n"
3134 */
3135
3136 static VALUE
3137 rb_io_gets_m(int argc, VALUE *argv, VALUE io)
3138 {
3139 VALUE str;
3140
3141 str = rb_io_getline(argc, argv, io);
3142 rb_lastline_set(str);
3143
3144 return str;
3145 }
3146
3147 /*
3148 * call-seq:
3149 * ios.lineno -> integer
3150 *
3151 * Returns the current line number in <em>ios</em>. The stream must be
3152 * opened for reading. <code>lineno</code> counts the number of times
3153 * #gets is called rather than the number of newlines encountered. The two
3154 * values will differ if #gets is called with a separator other than newline.
3155 *
3156 * Methods that use <code>$/</code> like #each, #lines and #readline will
3157 * also increment <code>lineno</code>.
3158 *
3159 * See also the <code>$.</code> variable.
3160 *
3161 * f = File.new("testfile")
3162 * f.lineno #=> 0
3163 * f.gets #=> "This is line one\n"
3164 * f.lineno #=> 1
3165 * f.gets #=> "This is line two\n"
3166 * f.lineno #=> 2
3167 */
3168
3169 static VALUE
3170 rb_io_lineno(VALUE io)
3171 {
3172 rb_io_t *fptr;
3173
3174 GetOpenFile(io, fptr);
3175 rb_io_check_char_readable(fptr);
3176 return INT2NUM(fptr->lineno);
3177 }
3178
3179 /*
3180 * call-seq:
3181 * ios.lineno = integer -> integer
3182 *
3183 * Manually sets the current line number to the given value.
3184 * <code>$.</code> is updated only on the next read.
3185 *
3186 * f = File.new("testfile")
3187 * f.gets #=> "This is line one\n"
3188 * $. #=> 1
3189 * f.lineno = 1000
3190 * f.lineno #=> 1000
3191 * $. #=> 1 # lineno of last read
3192 * f.gets #=> "This is line two\n"
3193 * $. #=> 1001 # lineno of last read
3194 */
3195
3196 static VALUE
3197 rb_io_set_lineno(VALUE io, VALUE lineno)
3198 {
3199 rb_io_t *fptr;
3200
3201 GetOpenFile(io, fptr);
3202 rb_io_check_char_readable(fptr);
3203 fptr->lineno = NUM2INT(lineno);
3204 return lineno;
3205 }
3206
3207 /*
3208 * call-seq:
3209 * ios.readline(sep=$/) -> string
3210 * ios.readline(limit) -> string
3211 * ios.readline(sep, limit) -> string
3212 *
3213 * Reads a line as with <code>IO#gets</code>, but raises an
3214 * <code>EOFError</code> on end of file.
3215 */
3216
3217 static VALUE
3218 rb_io_readline(int argc, VALUE *argv, VALUE io)
3219 {
3220 VALUE line = rb_io_gets_m(argc, argv, io);
3221
3222 if (NIL_P(line)) {
3223 rb_eof_error();
3224 }
3225 return line;
3226 }
3227
3228 /*
3229 * call-seq:
3230 * ios.readlines(sep=$/) -> array
3231 * ios.readlines(limit) -> array
3232 * ios.readlines(sep, limit) -> array
3233 *
3234 * Reads all of the lines in <em>ios</em>, and returns them in
3235 * <i>anArray</i>. Lines are separated by the optional <i>sep</i>. If
3236 * <i>sep</i> is <code>nil</code>, the rest of the stream is returned
3237 * as a single record. If the first argument is an integer, or
3238 * optional second argument is given, the returning string would not be
3239 * longer than the given value in bytes. The stream must be opened for
3240 * reading or an <code>IOError</code> will be raised.
3241 *
3242 * f = File.new("testfile")
3243 * f.readlines[0] #=> "This is line one\n"
3244 */
3245
3246 static VALUE
3247 rb_io_readlines(int argc, VALUE *argv, VALUE io)
3248 {
3249 VALUE line, ary, rs;
3250 long limit;
3251
3252 prepare_getline_args(argc, argv, &rs, &limit, io);
3253 if (limit == 0)
3254 rb_raise(rb_eArgError, "invalid limit: 0 for readlines");
3255 ary = rb_ary_new();
3256 while (!NIL_P(line = rb_io_getline_1(rs, limit, io))) {
3257 rb_ary_push(ary, line);
3258 }
3259 return ary;
3260 }
3261
3262 /*
3263 * call-seq:
3264 * ios.each(sep=$/) {|line| block } -> ios
3265 * ios.each(limit) {|line| block } -> ios
3266 * ios.each(sep,limit) {|line| block } -> ios
3267 * ios.each(...) -> an_enumerator
3268 *
3269 * ios.each_line(sep=$/) {|line| block } -> ios
3270 * ios.each_line(limit) {|line| block } -> ios
3271 * ios.each_line(sep,limit) {|line| block } -> ios
3272 * ios.each_line(...) -> an_enumerator
3273 *
3274 * Executes the block for every line in <em>ios</em>, where lines are
3275 * separated by <i>sep</i>. <em>ios</em> must be opened for
3276 * reading or an <code>IOError</code> will be raised.
3277 *
3278 * If no block is given, an enumerator is returned instead.
3279 *
3280 * f = File.new("testfile")
3281 * f.each {|line| puts "#{f.lineno}: #{line}" }
3282 *
3283 * <em>produces:</em>
3284 *
3285 * 1: This is line one
3286 * 2: This is line two
3287 * 3: This is line three
3288 * 4: And so on...
3289 */
3290
3291 static VALUE
3292 rb_io_each_line(int argc, VALUE *argv, VALUE io)
3293 {
3294 VALUE str, rs;
3295 long limit;
3296
3297 RETURN_ENUMERATOR(io, argc, argv);
3298 prepare_getline_args(argc, argv, &rs, &limit, io);
3299 if (limit == 0)
3300 rb_raise(rb_eArgError, "invalid limit: 0 for each_line");
3301 while (!NIL_P(str = rb_io_getline_1(rs, limit, io))) {
3302 rb_yield(str);
3303 }
3304 return io;
3305 }
3306
3307 /*
3308 * This is a deprecated alias for <code>each_line</code>.
3309 */
3310
3311 static VALUE
3312 rb_io_lines(int argc, VALUE *argv, VALUE io)
3313 {
3314 rb_warn("IO#lines is deprecated; use #each_line instead");
3315 if (!rb_block_given_p())
3316 return rb_enumeratorize(io, ID2SYM(rb_intern("each_line")), argc, argv);
3317 return rb_io_each_line(argc, argv, io);
3318 }
3319
3320 /*
3321 * call-seq:
3322 * ios.each_byte {|byte| block } -> ios
3323 * ios.each_byte -> an_enumerator
3324 *
3325 * Calls the given block once for each byte (0..255) in <em>ios</em>,
3326 * passing the byte as an argument. The stream must be opened for
3327 * reading or an <code>IOError</code> will be raised.
3328 *
3329 * If no block is given, an enumerator is returned instead.
3330 *
3331 * f = File.new("testfile")
3332 * checksum = 0
3333 * f.each_byte {|x| checksum ^= x } #=> #<File:testfile>
3334 * checksum #=> 12
3335 */
3336
3337 static VALUE
3338 rb_io_each_byte(VALUE io)
3339 {
3340 rb_io_t *fptr;
3341
3342 RETURN_ENUMERATOR(io, 0, 0);
3343 GetOpenFile(io, fptr);
3344
3345 for (;;) {
3346 while (fptr->rbuf.len > 0) {
3347 char *p = fptr->rbuf.ptr + fptr->rbuf.off++;
3348 fptr->rbuf.len--;
3349 rb_yield(INT2FIX(*p & 0xff));
3350 errno = 0;
3351 }
3352 rb_io_check_byte_readable(fptr);
3353 READ_CHECK(fptr);
3354 if (io_fillbuf(fptr) < 0) {
3355 break;
3356 }
3357 }
3358 return io;
3359 }
3360
3361 /*
3362 * This is a deprecated alias for <code>each_byte</code>.
3363 */
3364
3365 static VALUE
3366 rb_io_bytes(VALUE io)
3367 {
3368 rb_warn("IO#bytes is deprecated; use #each_byte instead");
3369 if (!rb_block_given_p())
3370 return rb_enumeratorize(io, ID2SYM(rb_intern("each_byte")), 0, 0);
3371 return rb_io_each_byte(io);
3372 }
3373
3374 static VALUE
3375 io_getc(rb_io_t *fptr, rb_encoding *enc)
3376 {
3377 int r, n, cr = 0;
3378 VALUE str;
3379
3380 if (NEED_READCONV(fptr)) {
3381 VALUE str = Qnil;
3382 rb_encoding *read_enc = io_read_encoding(fptr);
3383
3384 SET_BINARY_MODE(fptr);
3385 make_readconv(fptr, 0);
3386
3387 while (1) {
3388 if (fptr->cbuf.len) {
3389 r = rb_enc_precise_mbclen(fptr->cbuf.ptr+fptr->cbuf.off,
3390 fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
3391 read_enc);
3392 if (!MBCLEN_NEEDMORE_P(r))
3393 break;
3394 if (fptr->cbuf.len == fptr->cbuf.capa) {
3395 rb_raise(rb_eIOError, "too long character");
3396 }
3397 }
3398
3399 if (more_char(fptr) == MORE_CHAR_FINISHED) {
3400 if (fptr->cbuf.len == 0) {
3401 clear_readconv(fptr);
3402 return Qnil;
3403 }
3404 /* return an unit of an incomplete character just before EOF */
3405 str = rb_enc_str_new(fptr->cbuf.ptr+fptr->cbuf.off, 1, read_enc);
3406 fptr->cbuf.off += 1;
3407 fptr->cbuf.len -= 1;
3408 if (fptr->cbuf.len == 0) clear_readconv(fptr);
3409 ENC_CODERANGE_SET(str, ENC_CODERANGE_BROKEN);
3410 return str;
3411 }
3412 }
3413 if (MBCLEN_INVALID_P(r)) {
3414 r = rb_enc_mbclen(fptr->cbuf.ptr+fptr->cbuf.off,
3415 fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
3416 read_enc);
3417 io_shift_cbuf(fptr, r, &str);
3418 cr = ENC_CODERANGE_BROKEN;
3419 }
3420 else {
3421 io_shift_cbuf(fptr, MBCLEN_CHARFOUND_LEN(r), &str);
3422 cr = ENC_CODERANGE_VALID;
3423 if (MBCLEN_CHARFOUND_LEN(r) == 1 && rb_enc_asciicompat(read_enc) &&
3424 ISASCII(RSTRING_PTR(str)[0])) {
3425 cr = ENC_CODERANGE_7BIT;
3426 }
3427 }
3428 str = io_enc_str(str, fptr);
3429 ENC_CODERANGE_SET(str, cr);
3430 return str;
3431 }
3432
3433 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
3434 if (io_fillbuf(fptr) < 0) {
3435 return Qnil;
3436 }
3437 if (rb_enc_asciicompat(enc) && ISASCII(fptr->rbuf.ptr[fptr->rbuf.off])) {
3438 str = rb_str_new(fptr->rbuf.ptr+fptr->rbuf.off, 1);
3439 fptr->rbuf.off += 1;
3440 fptr->rbuf.len -= 1;
3441 cr = ENC_CODERANGE_7BIT;
3442 }
3443 else {
3444 r = rb_enc_precise_mbclen(fptr->rbuf.ptr+fptr->rbuf.off, fptr->rbuf.ptr+fptr->rbuf.off+fptr->rbuf.len, enc);
3445 if (MBCLEN_CHARFOUND_P(r) &&
3446 (n = MBCLEN_CHARFOUND_LEN(r)) <= fptr->rbuf.len) {
3447 str = rb_str_new(fptr->rbuf.ptr+fptr->rbuf.off, n);
3448 fptr->rbuf.off += n;
3449 fptr->rbuf.len -= n;
3450 cr = ENC_CODERANGE_VALID;
3451 }
3452 else if (MBCLEN_NEEDMORE_P(r)) {
3453 str = rb_str_new(fptr->rbuf.ptr+fptr->rbuf.off, fptr->rbuf.len);
3454 fptr->rbuf.len = 0;
3455 getc_needmore:
3456 if (io_fillbuf(fptr) != -1) {
3457 rb_str_cat(str, fptr->rbuf.ptr+fptr->rbuf.off, 1);
3458 fptr->rbuf.off++;
3459 fptr->rbuf.len--;
3460 r = rb_enc_precise_mbclen(RSTRING_PTR(str), RSTRING_PTR(str)+RSTRING_LEN(str), enc);
3461 if (MBCLEN_NEEDMORE_P(r)) {
3462 goto getc_needmore;
3463 }
3464 else if (MBCLEN_CHARFOUND_P(r)) {
3465 cr = ENC_CODERANGE_VALID;
3466 }
3467 }
3468 }
3469 else {
3470 str = rb_str_new(fptr->rbuf.ptr+fptr->rbuf.off, 1);
3471 fptr->rbuf.off++;
3472 fptr->rbuf.len--;
3473 }
3474 }
3475 if (!cr) cr = ENC_CODERANGE_BROKEN;
3476 str = io_enc_str(str, fptr);
3477 ENC_CODERANGE_SET(str, cr);
3478 return str;
3479 }
3480
3481 /*
3482 * call-seq:
3483 * ios.each_char {|c| block } -> ios
3484 * ios.each_char -> an_enumerator
3485 *
3486 * Calls the given block once for each character in <em>ios</em>,
3487 * passing the character as an argument. The stream must be opened for
3488 * reading or an <code>IOError</code> will be raised.
3489 *
3490 * If no block is given, an enumerator is returned instead.
3491 *
3492 * f = File.new("testfile")
3493 * f.each_char {|c| print c, ' ' } #=> #<File:testfile>
3494 */
3495
3496 static VALUE
3497 rb_io_each_char(VALUE io)
3498 {
3499 rb_io_t *fptr;
3500 rb_encoding *enc;
3501 VALUE c;
3502
3503 RETURN_ENUMERATOR(io, 0, 0);
3504 GetOpenFile(io, fptr);
3505 rb_io_check_char_readable(fptr);
3506
3507 enc = io_input_encoding(fptr);
3508 READ_CHECK(fptr);
3509 while (!NIL_P(c = io_getc(fptr, enc))) {
3510 rb_yield(c);
3511 }
3512 return io;
3513 }
3514
3515 /*
3516 * This is a deprecated alias for <code>each_char</code>.
3517 */
3518
3519 static VALUE
3520 rb_io_chars(VALUE io)
3521 {
3522 rb_warn("IO#chars is deprecated; use #each_char instead");
3523 if (!rb_block_given_p())
3524 return rb_enumeratorize(io, ID2SYM(rb_intern("each_char")), 0, 0);
3525 return rb_io_each_char(io);
3526 }
3527
3528
3529 /*
3530 * call-seq:
3531 * ios.each_codepoint {|c| block } -> ios
3532 * ios.codepoints {|c| block } -> ios
3533 * ios.each_codepoint -> an_enumerator
3534 * ios.codepoints -> an_enumerator
3535 *
3536 * Passes the <code>Integer</code> ordinal of each character in <i>ios</i>,
3537 * passing the codepoint as an argument. The stream must be opened for
3538 * reading or an <code>IOError</code> will be raised.
3539 *
3540 * If no block is given, an enumerator is returned instead.
3541 *
3542 */
3543
3544 static VALUE
3545 rb_io_each_codepoint(VALUE io)
3546 {
3547 rb_io_t *fptr;
3548 rb_encoding *enc;
3549 unsigned int c;
3550 int r, n;
3551
3552 RETURN_ENUMERATOR(io, 0, 0);
3553 GetOpenFile(io, fptr);
3554 rb_io_check_char_readable(fptr);
3555
3556 READ_CHECK(fptr);
3557 if (NEED_READCONV(fptr)) {
3558 SET_BINARY_MODE(fptr);
3559 for (;;) {
3560 make_readconv(fptr, 0);
3561 for (;;) {
3562 if (fptr->cbuf.len) {
3563 if (fptr->encs.enc)
3564 r = rb_enc_precise_mbclen(fptr->cbuf.ptr+fptr->cbuf.off,
3565 fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
3566 fptr->encs.enc);
3567 else
3568 r = ONIGENC_CONSTRUCT_MBCLEN_CHARFOUND(1);
3569 if (!MBCLEN_NEEDMORE_P(r))
3570 break;
3571 if (fptr->cbuf.len == fptr->cbuf.capa) {
3572 rb_raise(rb_eIOError, "too long character");
3573 }
3574 }
3575 if (more_char(fptr) == MORE_CHAR_FINISHED) {
3576 clear_readconv(fptr);
3577 /* ignore an incomplete character before EOF */
3578 return io;
3579 }
3580 }
3581 if (MBCLEN_INVALID_P(r)) {
3582 rb_raise(rb_eArgError, "invalid byte sequence in %s",
3583 rb_enc_name(fptr->encs.enc));
3584 }
3585 n = MBCLEN_CHARFOUND_LEN(r);
3586 if (fptr->encs.enc) {
3587 c = rb_enc_codepoint(fptr->cbuf.ptr+fptr->cbuf.off,
3588 fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
3589 fptr->encs.enc);
3590 }
3591 else {
3592 c = (unsigned char)fptr->cbuf.ptr[fptr->cbuf.off];
3593 }
3594 fptr->cbuf.off += n;
3595 fptr->cbuf.len -= n;
3596 rb_yield(UINT2NUM(c));
3597 }
3598 }
3599 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
3600 enc = io_input_encoding(fptr);
3601 for (;;) {
3602 if (io_fillbuf(fptr) < 0) {
3603 return io;
3604 }
3605 r = rb_enc_precise_mbclen(fptr->rbuf.ptr+fptr->rbuf.off,
3606 fptr->rbuf.ptr+fptr->rbuf.off+fptr->rbuf.len, enc);
3607 if (MBCLEN_CHARFOUND_P(r) &&
3608 (n = MBCLEN_CHARFOUND_LEN(r)) <= fptr->rbuf.len) {
3609 c = rb_enc_codepoint(fptr->rbuf.ptr+fptr->rbuf.off,
3610 fptr->rbuf.ptr+fptr->rbuf.off+fptr->rbuf.len, enc);
3611 fptr->rbuf.off += n;
3612 fptr->rbuf.len -= n;
3613 rb_yield(UINT2NUM(c));
3614 }
3615 else if (MBCLEN_INVALID_P(r)) {
3616 rb_raise(rb_eArgError, "invalid byte sequence in %s", rb_enc_name(enc));
3617 }
3618 else {
3619 continue;
3620 }
3621 }
3622 return io;
3623 }
3624
3625 /*
3626 * This is a deprecated alias for <code>each_codepoint</code>.
3627 */
3628
3629 static VALUE
3630 rb_io_codepoints(VALUE io)
3631 {
3632 rb_warn("IO#codepoints is deprecated; use #each_codepoint instead");
3633 if (!rb_block_given_p())
3634 return rb_enumeratorize(io, ID2SYM(rb_intern("each_codepoint")), 0, 0);
3635 return rb_io_each_codepoint(io);
3636 }
3637
3638
3639 /*
3640 * call-seq:
3641 * ios.getc -> string or nil
3642 *
3643 * Reads a one-character string from <em>ios</em>. Returns
3644 * <code>nil</code> if called at end of file.
3645 *
3646 * f = File.new("testfile")
3647 * f.getc #=> "h"
3648 * f.getc #=> "e"
3649 */
3650
3651 static VALUE
3652 rb_io_getc(VALUE io)
3653 {
3654 rb_io_t *fptr;
3655 rb_encoding *enc;
3656
3657 GetOpenFile(io, fptr);
3658 rb_io_check_char_readable(fptr);
3659
3660 enc = io_input_encoding(fptr);
3661 READ_CHECK(fptr);
3662 return io_getc(fptr, enc);
3663 }
3664
3665 /*
3666 * call-seq:
3667 * ios.readchar -> string
3668 *
3669 * Reads a one-character string from <em>ios</em>. Raises an
3670 * <code>EOFError</code> on end of file.
3671 *
3672 * f = File.new("testfile")
3673 * f.readchar #=> "h"
3674 * f.readchar #=> "e"
3675 */
3676
3677 static VALUE
3678 rb_io_readchar(VALUE io)
3679 {
3680 VALUE c = rb_io_getc(io);
3681
3682 if (NIL_P(c)) {
3683 rb_eof_error();
3684 }
3685 return c;
3686 }
3687
3688 /*
3689 * call-seq:
3690 * ios.getbyte -> fixnum or nil
3691 *
3692 * Gets the next 8-bit byte (0..255) from <em>ios</em>. Returns
3693 * <code>nil</code> if called at end of file.
3694 *
3695 * f = File.new("testfile")
3696 * f.getbyte #=> 84
3697 * f.getbyte #=> 104
3698 */
3699
3700 VALUE
3701 rb_io_getbyte(VALUE io)
3702 {
3703 rb_io_t *fptr;
3704 int c;
3705
3706 GetOpenFile(io, fptr);
3707 rb_io_check_byte_readable(fptr);
3708 READ_CHECK(fptr);
3709 if (fptr->fd == 0 && (fptr->mode & FMODE_TTY) && RB_TYPE_P(rb_stdout, T_FILE)) {
3710 rb_io_t *ofp;
3711 GetOpenFile(rb_stdout, ofp);
3712 if (ofp->mode & FMODE_TTY) {
3713 rb_io_flush(rb_stdout);
3714 }
3715 }
3716 if (io_fillbuf(fptr) < 0) {
3717 return Qnil;
3718 }
3719 fptr->rbuf.off++;
3720 fptr->rbuf.len--;
3721 c = (unsigned char)fptr->rbuf.ptr[fptr->rbuf.off-1];
3722 return INT2FIX(c & 0xff);
3723 }
3724
3725 /*
3726 * call-seq:
3727 * ios.readbyte -> fixnum
3728 *
3729 * Reads a byte as with <code>IO#getbyte</code>, but raises an
3730 * <code>EOFError</code> on end of file.
3731 */
3732
3733 static VALUE
3734 rb_io_readbyte(VALUE io)
3735 {
3736 VALUE c = rb_io_getbyte(io);
3737
3738 if (NIL_P(c)) {
3739 rb_eof_error();
3740 }
3741 return c;
3742 }
3743
3744 /*
3745 * call-seq:
3746 * ios.ungetbyte(string) -> nil
3747 * ios.ungetbyte(integer) -> nil
3748 *
3749 * Pushes back bytes (passed as a parameter) onto <em>ios</em>,
3750 * such that a subsequent buffered read will return it. Only one byte
3751 * may be pushed back before a subsequent read operation (that is,
3752 * you will be able to read only the last of several bytes that have been pushed
3753 * back). Has no effect with unbuffered reads (such as <code>IO#sysread</code>).
3754 *
3755 * f = File.new("testfile") #=> #<File:testfile>
3756 * b = f.getbyte #=> 0x38
3757 * f.ungetbyte(b) #=> nil
3758 * f.getbyte #=> 0x38
3759 */
3760
3761 VALUE
3762 rb_io_ungetbyte(VALUE io, VALUE b)
3763 {
3764 rb_io_t *fptr;
3765
3766 GetOpenFile(io, fptr);
3767 rb_io_check_byte_readable(fptr);
3768 if (NIL_P(b)) return Qnil;
3769 if (FIXNUM_P(b)) {
3770 char cc = FIX2INT(b);
3771 b = rb_str_new(&cc, 1);
3772 }
3773 else {
3774 SafeStringValue(b);
3775 }
3776 io_ungetbyte(b, fptr);
3777 return Qnil;
3778 }
3779
3780 /*
3781 * call-seq:
3782 * ios.ungetc(string) -> nil
3783 *
3784 * Pushes back one character (passed as a parameter) onto <em>ios</em>,
3785 * such that a subsequent buffered character read will return it. Only one character
3786 * may be pushed back before a subsequent read operation (that is,
3787 * you will be able to read only the last of several characters that have been pushed
3788 * back). Has no effect with unbuffered reads (such as <code>IO#sysread</code>).
3789 *
3790 * f = File.new("testfile") #=> #<File:testfile>
3791 * c = f.getc #=> "8"
3792 * f.ungetc(c) #=> nil
3793 * f.getc #=> "8"
3794 */
3795
3796 VALUE
3797 rb_io_ungetc(VALUE io, VALUE c)
3798 {
3799 rb_io_t *fptr;
3800 long len;
3801
3802 GetOpenFile(io, fptr);
3803 rb_io_check_char_readable(fptr);
3804 if (NIL_P(c)) return Qnil;
3805 if (FIXNUM_P(c)) {
3806 c = rb_enc_uint_chr(FIX2UINT(c), io_read_encoding(fptr));
3807 }
3808 else if (RB_TYPE_P(c, T_BIGNUM)) {
3809 c = rb_enc_uint_chr(NUM2UINT(c), io_read_encoding(fptr));
3810 }
3811 else {
3812 SafeStringValue(c);
3813 }
3814 if (NEED_READCONV(fptr)) {
3815 SET_BINARY_MODE(fptr);
3816 len = RSTRING_LEN(c);
3817 #if SIZEOF_LONG > SIZEOF_INT
3818 if (len > INT_MAX)
3819 rb_raise(rb_eIOError, "ungetc failed");
3820 #endif
3821 make_readconv(fptr, (int)len);
3822 if (fptr->cbuf.capa - fptr->cbuf.len < len)
3823 rb_raise(rb_eIOError, "ungetc failed");
3824 if (fptr->cbuf.off < len) {
3825 MEMMOVE(fptr->cbuf.ptr+fptr->cbuf.capa-fptr->cbuf.len,
3826 fptr->cbuf.ptr+fptr->cbuf.off,
3827 char, fptr->cbuf.len);
3828 fptr->cbuf.off = fptr->cbuf.capa-fptr->cbuf.len;
3829 }
3830 fptr->cbuf.off -= (int)len;
3831 fptr->cbuf.len += (int)len;
3832 MEMMOVE(fptr->cbuf.ptr+fptr->cbuf.off, RSTRING_PTR(c), char, len);
3833 }
3834 else {
3835 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
3836 io_ungetbyte(c, fptr);
3837 }
3838 return Qnil;
3839 }
3840
3841 /*
3842 * call-seq:
3843 * ios.isatty -> true or false
3844 * ios.tty? -> true or false
3845 *
3846 * Returns <code>true</code> if <em>ios</em> is associated with a
3847 * terminal device (tty), <code>false</code> otherwise.
3848 *
3849 * File.new("testfile").isatty #=> false
3850 * File.new("/dev/tty").isatty #=> true
3851 */
3852
3853 static VALUE
3854 rb_io_isatty(VALUE io)
3855 {
3856 rb_io_t *fptr;
3857
3858 GetOpenFile(io, fptr);
3859 if (isatty(fptr->fd) == 0)
3860 return Qfalse;
3861 return Qtrue;
3862 }
3863
3864 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
3865 /*
3866 * call-seq:
3867 * ios.close_on_exec? -> true or false
3868 *
3869 * Returns <code>true</code> if <em>ios</em> will be closed on exec.
3870 *
3871 * f = open("/dev/null")
3872 * f.close_on_exec? #=> false
3873 * f.close_on_exec = true
3874 * f.close_on_exec? #=> true
3875 * f.close_on_exec = false
3876 * f.close_on_exec? #=> false
3877 */
3878
3879 static VALUE
3880 rb_io_close_on_exec_p(VALUE io)
3881 {
3882 rb_io_t *fptr;
3883 VALUE write_io;
3884 int fd, ret;
3885
3886 write_io = GetWriteIO(io);
3887 if (io != write_io) {
3888 GetOpenFile(write_io, fptr);
3889 if (fptr && 0 <= (fd = fptr->fd)) {
3890 if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
3891 if (!(ret & FD_CLOEXEC)) return Qfalse;
3892 }
3893 }
3894
3895 GetOpenFile(io, fptr);
3896 if (fptr && 0 <= (fd = fptr->fd)) {
3897 if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
3898 if (!(ret & FD_CLOEXEC)) return Qfalse;
3899 }
3900 return Qtrue;
3901 }
3902 #else
3903 #define rb_io_close_on_exec_p rb_f_notimplement
3904 #endif
3905
3906 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
3907 /*
3908 * call-seq:
3909 * ios.close_on_exec = bool -> true or false
3910 *
3911 * Sets a close-on-exec flag.
3912 *
3913 * f = open("/dev/null")
3914 * f.close_on_exec = true
3915 * system("cat", "/proc/self/fd/#{f.fileno}") # cat: /proc/self/fd/3: No such file or directory
3916 * f.closed? #=> false
3917 *
3918 * Ruby sets close-on-exec flags of all file descriptors by default
3919 * since Ruby 2.0.0.
3920 * So you don't need to set by yourself.
3921 * Also, unsetting a close-on-exec flag can cause file descriptor leak
3922 * if another thread use fork() and exec() (via system() method for example).
3923 * If you really needs file descriptor inheritance to child process,
3924 * use spawn()'s argument such as fd=>fd.
3925 */
3926
3927 static VALUE
3928 rb_io_set_close_on_exec(VALUE io, VALUE arg)
3929 {
3930 int flag = RTEST(arg) ? FD_CLOEXEC : 0;
3931 rb_io_t *fptr;
3932 VALUE write_io;
3933 int fd, ret;
3934
3935 write_io = GetWriteIO(io);
3936 if (io != write_io) {
3937 GetOpenFile(write_io, fptr);
3938 if (fptr && 0 <= (fd = fptr->fd)) {
3939 if ((ret = fcntl(fptr->fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
3940 if ((ret & FD_CLOEXEC) != flag) {
3941 ret = (ret & ~FD_CLOEXEC) | flag;
3942 ret = fcntl(fd, F_SETFD, ret);
3943 if (ret == -1) rb_sys_fail_path(fptr->pathv);
3944 }
3945 }
3946
3947 }
3948
3949 GetOpenFile(io, fptr);
3950 if (fptr && 0 <= (fd = fptr->fd)) {
3951 if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
3952 if ((ret & FD_CLOEXEC) != flag) {
3953 ret = (ret & ~FD_CLOEXEC) | flag;
3954 ret = fcntl(fd, F_SETFD, ret);
3955 if (ret == -1) rb_sys_fail_path(fptr->pathv);
3956 }
3957 }
3958 return Qnil;
3959 }
3960 #else
3961 #define rb_io_set_close_on_exec rb_f_notimplement
3962 #endif
3963
3964 #define FMODE_PREP (1<<16)
3965 #define IS_PREP_STDIO(f) ((f)->mode & FMODE_PREP)
3966 #define PREP_STDIO_NAME(f) (RSTRING_PTR((f)->pathv))
3967
3968 static VALUE
3969 finish_writeconv(rb_io_t *fptr, int noalloc)
3970 {
3971 unsigned char *ds, *dp, *de;
3972 rb_econv_result_t res;
3973
3974 if (!fptr->wbuf.ptr) {
3975 unsigned char buf[1024];
3976 long r;
3977
3978 res = econv_destination_buffer_full;
3979 while (res == econv_destination_buffer_full) {
3980 ds = dp = buf;
3981 de = buf + sizeof(buf);
3982 res = rb_econv_convert(fptr->writeconv, NULL, NULL, &dp, de, 0);
3983 while (dp-ds) {
3984 retry:
3985 if (fptr->write_lock && rb_mutex_owned_p(fptr->write_lock))
3986 r = rb_write_internal2(fptr->fd, ds, dp-ds);
3987 else
3988 r = rb_write_internal(fptr->fd, ds, dp-ds);
3989 if (r == dp-ds)
3990 break;
3991 if (0 <= r) {
3992 ds += r;
3993 }
3994 if (rb_io_wait_writable(fptr->fd)) {
3995 if (fptr->fd < 0)
3996 return noalloc ? Qtrue : rb_exc_new3(rb_eIOError, rb_str_new_cstr("closed stream"));
3997 goto retry;
3998 }
3999 return noalloc ? Qtrue : INT2NUM(errno);
4000 }
4001 if (res == econv_invalid_byte_sequence ||
4002 res == econv_incomplete_input ||
4003 res == econv_undefined_conversion) {
4004 return noalloc ? Qtrue : rb_econv_make_exception(fptr->writeconv);
4005 }
4006 }
4007
4008 return Qnil;
4009 }
4010
4011 res = econv_destination_buffer_full;
4012 while (res == econv_destination_buffer_full) {
4013 if (fptr->wbuf.len == fptr->wbuf.capa) {
4014 if (io_fflush(fptr) < 0)
4015 return noalloc ? Qtrue : INT2NUM(errno);
4016 }
4017
4018 ds = dp = (unsigned char *)fptr->wbuf.ptr + fptr->wbuf.off + fptr->wbuf.len;
4019 de = (unsigned char *)fptr->wbuf.ptr + fptr->wbuf.capa;
4020 res = rb_econv_convert(fptr->writeconv, NULL, NULL, &dp, de, 0);
4021 fptr->wbuf.len += (int)(dp - ds);
4022 if (res == econv_invalid_byte_sequence ||
4023 res == econv_incomplete_input ||
4024 res == econv_undefined_conversion) {
4025 return noalloc ? Qtrue : rb_econv_make_exception(fptr->writeconv);
4026 }
4027 }
4028 return Qnil;
4029 }
4030
4031 struct finish_writeconv_arg {
4032 rb_io_t *fptr;
4033 int noalloc;
4034 };
4035
4036 static VALUE
4037 finish_writeconv_sync(VALUE arg)
4038 {
4039 struct finish_writeconv_arg *p = (struct finish_writeconv_arg *)arg;
4040 return finish_writeconv(p->fptr, p->noalloc);
4041 }
4042
4043 static void*
4044 nogvl_close(void *ptr)
4045 {
4046 int *fd = ptr;
4047
4048 return (void*)(intptr_t)close(*fd);
4049 }
4050
4051 static int
4052 maygvl_close(int fd, int keepgvl)
4053 {
4054 if (keepgvl)
4055 return close(fd);
4056
4057 /*
4058 * close() may block for certain file types (NFS, SO_LINGER sockets,
4059 * inotify), so let other threads run.
4060 */
4061 return (int)(intptr_t)rb_thread_call_without_gvl(nogvl_close, &fd, RUBY_UBF_IO, 0);
4062 }
4063
4064 static void*
4065 nogvl_fclose(void *ptr)
4066 {
4067 FILE *file = ptr;
4068
4069 return (void*)(intptr_t)fclose(file);
4070 }
4071
4072 static int
4073 maygvl_fclose(FILE *file, int keepgvl)
4074 {
4075 if (keepgvl)
4076 return fclose(file);
4077
4078 return (int)(intptr_t)rb_thread_call_without_gvl(nogvl_fclose, file, RUBY_UBF_IO, 0);
4079 }
4080
4081 static void
4082 fptr_finalize(rb_io_t *fptr, int noraise)
4083 {
4084 VALUE err = Qnil;
4085 int fd = fptr->fd;
4086 FILE *stdio_file = fptr->stdio_file;
4087
4088 if (fptr->writeconv) {
4089 if (fptr->write_lock && !noraise) {
4090 struct finish_writeconv_arg arg;
4091 arg.fptr = fptr;
4092 arg.noalloc = noraise;
4093 err = rb_mutex_synchronize(fptr->write_lock, finish_writeconv_sync, (VALUE)&arg);
4094 }
4095 else {
4096 err = finish_writeconv(fptr, noraise);
4097 }
4098 }
4099 if (fptr->wbuf.len) {
4100 if (noraise) {
4101 if ((int)io_flush_buffer_sync(fptr) < 0 && NIL_P(err))
4102 err = Qtrue;
4103 }
4104 else {
4105 if (io_fflush(fptr) < 0 && NIL_P(err))
4106 err = INT2NUM(errno);
4107 }
4108 }
4109
4110 fptr->fd = -1;
4111 fptr->stdio_file = 0;
4112 fptr->mode &= ~(FMODE_READABLE|FMODE_WRITABLE);
4113
4114 if (IS_PREP_STDIO(fptr) || fd <= 2) {
4115 /* need to keep FILE objects of stdin, stdout and stderr */
4116 }
4117 else if (stdio_file) {
4118 /* stdio_file is deallocated anyway
4119 * even if fclose failed. */
4120 if ((maygvl_fclose(stdio_file, noraise) < 0) && NIL_P(err))
4121 err = noraise ? Qtrue : INT2NUM(errno);
4122 }
4123 else if (0 <= fd) {
4124 /* fptr->fd may be closed even if close fails.
4125 * POSIX doesn't specify it.
4126 * We assumes it is closed. */
4127 if ((maygvl_close(fd, noraise) < 0) && NIL_P(err))
4128 err = noraise ? Qtrue : INT2NUM(errno);
4129 }
4130
4131 if (!NIL_P(err) && !noraise) {
4132 switch (TYPE(err)) {
4133 case T_FIXNUM:
4134 case T_BIGNUM:
4135 errno = NUM2INT(err);
4136 rb_sys_fail_path(fptr->pathv);
4137
4138 default:
4139 rb_exc_raise(err);
4140 }
4141 }
4142 }
4143
4144 static void
4145 rb_io_fptr_cleanup(rb_io_t *fptr, int noraise)
4146 {
4147 if (fptr->finalize) {
4148 (*fptr->finalize)(fptr, noraise);
4149 }
4150 else {
4151 fptr_finalize(fptr, noraise);
4152 }
4153 }
4154
4155 static void
4156 clear_readconv(rb_io_t *fptr)
4157 {
4158 if (fptr->readconv) {
4159 rb_econv_close(fptr->readconv);
4160 fptr->readconv = NULL;
4161 }
4162 if (fptr->cbuf.ptr) {
4163 free(fptr->cbuf.ptr);
4164 fptr->cbuf.ptr = NULL;
4165 }
4166 }
4167
4168 static void
4169 clear_writeconv(rb_io_t *fptr)
4170 {
4171 if (fptr->writeconv) {
4172 rb_econv_close(fptr->writeconv);
4173 fptr->writeconv = NULL;
4174 }
4175 fptr->writeconv_initialized = 0;
4176 }
4177
4178 static void
4179 clear_codeconv(rb_io_t *fptr)
4180 {
4181 clear_readconv(fptr);
4182 clear_writeconv(fptr);
4183 }
4184
4185 int
4186 rb_io_fptr_finalize(rb_io_t *fptr)
4187 {
4188 if (!fptr) return 0;
4189 fptr->pathv = Qnil;
4190 if (0 <= fptr->fd)
4191 rb_io_fptr_cleanup(fptr, TRUE);
4192 fptr->write_lock = 0;
4193 if (fptr->rbuf.ptr) {
4194 free(fptr->rbuf.ptr);
4195 fptr->rbuf.ptr = 0;
4196 }
4197 if (fptr->wbuf.ptr) {
4198 free(fptr->wbuf.ptr);
4199 fptr->wbuf.ptr = 0;
4200 }
4201 clear_codeconv(fptr);
4202 free(fptr);
4203 return 1;
4204 }
4205
4206 size_t rb_econv_memsize(rb_econv_t *);
4207
4208 RUBY_FUNC_EXPORTED size_t
4209 rb_io_memsize(const rb_io_t *fptr)
4210 {
4211 size_t size = sizeof(rb_io_t);
4212 size += fptr->rbuf.capa;
4213 size += fptr->wbuf.capa;
4214 size += fptr->cbuf.capa;
4215 if (fptr->readconv) size += rb_econv_memsize(fptr->readconv);
4216 if (fptr->writeconv) size += rb_econv_memsize(fptr->writeconv);
4217 return size;
4218 }
4219
4220 VALUE
4221 rb_io_close(VALUE io)
4222 {
4223 rb_io_t *fptr;
4224 int fd;
4225 VALUE write_io;
4226 rb_io_t *write_fptr;
4227
4228 write_io = GetWriteIO(io);
4229 if (io != write_io) {
4230 write_fptr = RFILE(write_io)->fptr;
4231 if (write_fptr && 0 <= write_fptr->fd) {
4232 rb_io_fptr_cleanup(write_fptr, TRUE);
4233 }
4234 }
4235
4236 fptr = RFILE(io)->fptr;
4237 if (!fptr) return Qnil;
4238 if (fptr->fd < 0) return Qnil;
4239
4240 fd = fptr->fd;
4241 rb_thread_fd_close(fd);
4242 rb_io_fptr_cleanup(fptr, FALSE);
4243
4244 if (fptr->pid) {
4245 rb_last_status_clear();
4246 rb_syswait(fptr->pid);
4247 fptr->pid = 0;
4248 }
4249
4250 return Qnil;
4251 }
4252
4253 /*
4254 * call-seq:
4255 * ios.close -> nil
4256 *
4257 * Closes <em>ios</em> and flushes any pending writes to the operating
4258 * system. The stream is unavailable for any further data operations;
4259 * an <code>IOError</code> is raised if such an attempt is made. I/O
4260 * streams are automatically closed when they are claimed by the
4261 * garbage collector.
4262 *
4263 * If <em>ios</em> is opened by <code>IO.popen</code>,
4264 * <code>close</code> sets <code>$?</code>.
4265 */
4266
4267 static VALUE
4268 rb_io_close_m(VALUE io)
4269 {
4270 if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(io)) {
4271 rb_raise(rb_eSecurityError, "Insecure: can't close");
4272 }
4273 rb_io_check_closed(RFILE(io)->fptr);
4274 rb_io_close(io);
4275 return Qnil;
4276 }
4277
4278 static VALUE
4279 io_call_close(VALUE io)
4280 {
4281 return rb_funcall(io, rb_intern("close"), 0, 0);
4282 }
4283
4284 static VALUE
4285 io_close(VALUE io)
4286 {
4287 return rb_rescue(io_call_close, io, 0, 0);
4288 }
4289
4290 /*
4291 * call-seq:
4292 * ios.closed? -> true or false
4293 *
4294 * Returns <code>true</code> if <em>ios</em> is completely closed (for
4295 * duplex streams, both reader and writer), <code>false</code>
4296 * otherwise.
4297 *
4298 * f = File.new("testfile")
4299 * f.close #=> nil
4300 * f.closed? #=> true
4301 * f = IO.popen("/bin/sh","r+")
4302 * f.close_write #=> nil
4303 * f.closed? #=> false
4304 * f.close_read #=> nil
4305 * f.closed? #=> true
4306 */
4307
4308
4309 static VALUE
4310 rb_io_closed(VALUE io)
4311 {
4312 rb_io_t *fptr;
4313 VALUE write_io;
4314 rb_io_t *write_fptr;
4315
4316 write_io = GetWriteIO(io);
4317 if (io != write_io) {
4318 write_fptr = RFILE(write_io)->fptr;
4319 if (write_fptr && 0 <= write_fptr->fd) {
4320 return Qfalse;
4321 }
4322 }
4323
4324 fptr = RFILE(io)->fptr;
4325 rb_io_check_initialized(fptr);
4326 return 0 <= fptr->fd ? Qfalse : Qtrue;
4327 }
4328
4329 /*
4330 * call-seq:
4331 * ios.close_read -> nil
4332 *
4333 * Closes the read end of a duplex I/O stream (i.e., one that contains
4334 * both a read and a write stream, such as a pipe). Will raise an
4335 * <code>IOError</code> if the stream is not duplexed.
4336 *
4337 * f = IO.popen("/bin/sh","r+")
4338 * f.close_read
4339 * f.readlines
4340 *
4341 * <em>produces:</em>
4342 *
4343 * prog.rb:3:in `readlines': not opened for reading (IOError)
4344 * from prog.rb:3
4345 */
4346
4347 static VALUE
4348 rb_io_close_read(VALUE io)
4349 {
4350 rb_io_t *fptr;
4351 VALUE write_io;
4352
4353 if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(io)) {
4354 rb_raise(rb_eSecurityError, "Insecure: can't close");
4355 }
4356 GetOpenFile(io, fptr);
4357 if (is_socket(fptr->fd, fptr->pathv)) {
4358 #ifndef SHUT_RD
4359 # define SHUT_RD 0
4360 #endif
4361 if (shutdown(fptr->fd, SHUT_RD) < 0)
4362 rb_sys_fail_path(fptr->pathv);
4363 fptr->mode &= ~FMODE_READABLE;
4364 if (!(fptr->mode & FMODE_WRITABLE))
4365 return rb_io_close(io);
4366 return Qnil;
4367 }
4368
4369 write_io = GetWriteIO(io);
4370 if (io != write_io) {
4371 rb_io_t *wfptr;
4372 GetOpenFile(write_io, wfptr);
4373 wfptr->pid = fptr->pid;
4374 fptr->pid = 0;
4375 RFILE(io)->fptr = wfptr;
4376 /* bind to write_io temporarily to get rid of memory/fd leak */
4377 fptr->tied_io_for_writing = 0;
4378 fptr->mode &= ~FMODE_DUPLEX;
4379 RFILE(write_io)->fptr = fptr;
4380 rb_io_fptr_cleanup(fptr, FALSE);
4381 /* should not finalize fptr because another thread may be reading it */
4382 return Qnil;
4383 }
4384
4385 if (fptr->mode & FMODE_WRITABLE) {
4386 rb_raise(rb_eIOError, "closing non-duplex IO for reading");
4387 }
4388 return rb_io_close(io);
4389 }
4390
4391 /*
4392 * call-seq:
4393 * ios.close_write -> nil
4394 *
4395 * Closes the write end of a duplex I/O stream (i.e., one that contains
4396 * both a read and a write stream, such as a pipe). Will raise an
4397 * <code>IOError</code> if the stream is not duplexed.
4398 *
4399 * f = IO.popen("/bin/sh","r+")
4400 * f.close_write
4401 * f.print "nowhere"
4402 *
4403 * <em>produces:</em>
4404 *
4405 * prog.rb:3:in `write': not opened for writing (IOError)
4406 * from prog.rb:3:in `print'
4407 * from prog.rb:3
4408 */
4409
4410 static VALUE
4411 rb_io_close_write(VALUE io)
4412 {
4413 rb_io_t *fptr;
4414 VALUE write_io;
4415
4416 if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(io)) {
4417 rb_raise(rb_eSecurityError, "Insecure: can't close");
4418 }
4419 write_io = GetWriteIO(io);
4420 GetOpenFile(write_io, fptr);
4421 if (is_socket(fptr->fd, fptr->pathv)) {
4422 #ifndef SHUT_WR
4423 # define SHUT_WR 1
4424 #endif
4425 if (shutdown(fptr->fd, SHUT_WR) < 0)
4426 rb_sys_fail_path(fptr->pathv);
4427 fptr->mode &= ~FMODE_WRITABLE;
4428 if (!(fptr->mode & FMODE_READABLE))
4429 return rb_io_close(write_io);
4430 return Qnil;
4431 }
4432
4433 if (fptr->mode & FMODE_READABLE) {
4434 rb_raise(rb_eIOError, "closing non-duplex IO for writing");
4435 }
4436
4437 if (io != write_io) {
4438 GetOpenFile(io, fptr);
4439 fptr->tied_io_for_writing = 0;
4440 fptr->mode &= ~FMODE_DUPLEX;
4441 }
4442 rb_io_close(write_io);
4443 return Qnil;
4444 }
4445
4446 /*
4447 * call-seq:
4448 * ios.sysseek(offset, whence=IO::SEEK_SET) -> integer
4449 *
4450 * Seeks to a given <i>offset</i> in the stream according to the value
4451 * of <i>whence</i> (see <code>IO#seek</code> for values of
4452 * <i>whence</i>). Returns the new offset into the file.
4453 *
4454 * f = File.new("testfile")
4455 * f.sysseek(-13, IO::SEEK_END) #=> 53
4456 * f.sysread(10) #=> "And so on."
4457 */
4458
4459 static VALUE
4460 rb_io_sysseek(int argc, VALUE *argv, VALUE io)
4461 {
4462 VALUE offset, ptrname;
4463 int whence = SEEK_SET;
4464 rb_io_t *fptr;
4465 off_t pos;
4466
4467 if (rb_scan_args(argc, argv, "11", &offset, &ptrname) == 2) {
4468 whence = NUM2INT(ptrname);
4469 }
4470 pos = NUM2OFFT(offset);
4471 GetOpenFile(io, fptr);
4472 if ((fptr->mode & FMODE_READABLE) &&
4473 (READ_DATA_BUFFERED(fptr) || READ_CHAR_PENDING(fptr))) {
4474 rb_raise(rb_eIOError, "sysseek for buffered IO");
4475 }
4476 if ((fptr->mode & FMODE_WRITABLE) && fptr->wbuf.len) {
4477 rb_warn("sysseek for buffered IO");
4478 }
4479 errno = 0;
4480 pos = lseek(fptr->fd, pos, whence);
4481 if (pos == -1 && errno) rb_sys_fail_path(fptr->pathv);
4482
4483 return OFFT2NUM(pos);
4484 }
4485
4486 /*
4487 * call-seq:
4488 * ios.syswrite(string) -> integer
4489 *
4490 * Writes the given string to <em>ios</em> using a low-level write.
4491 * Returns the number of bytes written. Do not mix with other methods
4492 * that write to <em>ios</em> or you may get unpredictable results.
4493 * Raises <code>SystemCallError</code> on error.
4494 *
4495 * f = File.new("out", "w")
4496 * f.syswrite("ABCDEF") #=> 6
4497 */
4498
4499 static VALUE
4500 rb_io_syswrite(VALUE io, VALUE str)
4501 {
4502 rb_io_t *fptr;
4503 long n;
4504
4505 rb_secure(4);
4506 if (!RB_TYPE_P(str, T_STRING))
4507 str = rb_obj_as_string(str);
4508
4509 io = GetWriteIO(io);
4510 GetOpenFile(io, fptr);
4511 rb_io_check_writable(fptr);
4512
4513 str = rb_str_new_frozen(str);
4514
4515 if (fptr->wbuf.len) {
4516 rb_warn("syswrite for buffered IO");
4517 }
4518
4519 n = rb_write_internal(fptr->fd, RSTRING_PTR(str), RSTRING_LEN(str));
4520
4521 if (n == -1) rb_sys_fail_path(fptr->pathv);
4522
4523 return LONG2FIX(n);
4524 }
4525
4526 /*
4527 * call-seq:
4528 * ios.sysread(maxlen[, outbuf]) -> string
4529 *
4530 * Reads <i>maxlen</i> bytes from <em>ios</em> using a low-level
4531 * read and returns them as a string. Do not mix with other methods
4532 * that read from <em>ios</em> or you may get unpredictable results.
4533 * If the optional <i>outbuf</i> argument is present, it must reference
4534 * a String, which will receive the data.
4535 * The <i>outbuf</i> will contain only the received data after the method call
4536 * even if it is not empty at the beginning.
4537 * Raises <code>SystemCallError</code> on error and
4538 * <code>EOFError</code> at end of file.
4539 *
4540 * f = File.new("testfile")
4541 * f.sysread(16) #=> "This is line one"
4542 */
4543
4544 static VALUE
4545 rb_io_sysread(int argc, VALUE *argv, VALUE io)
4546 {
4547 VALUE len, str;
4548 rb_io_t *fptr;
4549 long n, ilen;
4550 struct read_internal_arg arg;
4551
4552 rb_scan_args(argc, argv, "11", &len, &str);
4553 ilen = NUM2LONG(len);
4554
4555 io_setstrbuf(&str,ilen);
4556 if (ilen == 0) return str;
4557
4558 GetOpenFile(io, fptr);
4559 rb_io_check_byte_readable(fptr);
4560
4561 if (READ_DATA_BUFFERED(fptr)) {
4562 rb_raise(rb_eIOError, "sysread for buffered IO");
4563 }
4564
4565 n = fptr->fd;
4566
4567 /*
4568 * FIXME: removing rb_thread_wait_fd() here changes sysread semantics
4569 * on non-blocking IOs. However, it's still currently possible
4570 * for sysread to raise Errno::EAGAIN if another thread read()s
4571 * the IO after we return from rb_thread_wait_fd() but before
4572 * we call read()
4573 */
4574 rb_thread_wait_fd(fptr->fd);
4575
4576 rb_io_check_closed(fptr);
4577
4578 io_setstrbuf(&str, ilen);
4579 rb_str_locktmp(str);
4580 arg.fd = fptr->fd;
4581 arg.str_ptr = RSTRING_PTR(str);
4582 arg.len = ilen;
4583 rb_ensure(read_internal_call, (VALUE)&arg, rb_str_unlocktmp, str);
4584 n = arg.len;
4585
4586 if (n == -1) {
4587 rb_sys_fail_path(fptr->pathv);
4588 }
4589 io_set_read_length(str, n);
4590 if (n == 0 && ilen > 0) {
4591 rb_eof_error();
4592 }
4593 OBJ_TAINT(str);
4594
4595 return str;
4596 }
4597
4598 VALUE
4599 rb_io_binmode(VALUE io)
4600 {
4601 rb_io_t *fptr;
4602
4603 GetOpenFile(io, fptr);
4604 if (fptr->readconv)
4605 rb_econv_binmode(fptr->readconv);
4606 if (fptr->writeconv)
4607 rb_econv_binmode(fptr->writeconv);
4608 fptr->mode |= FMODE_BINMODE;
4609 fptr->mode &= ~FMODE_TEXTMODE;
4610 fptr->writeconv_pre_ecflags &= ~ECONV_NEWLINE_DECORATOR_MASK;
4611 #ifdef O_BINARY
4612 if (!fptr->readconv) {
4613 SET_BINARY_MODE_WITH_SEEK_CUR(fptr);
4614 }
4615 else {
4616 setmode(fptr->fd, O_BINARY);
4617 }
4618 #endif
4619 return io;
4620 }
4621
4622 VALUE
4623 rb_io_ascii8bit_binmode(VALUE io)
4624 {
4625 rb_io_t *fptr;
4626
4627 GetOpenFile(io, fptr);
4628 if (fptr->readconv) {
4629 rb_econv_close(fptr->readconv);
4630 fptr->readconv = NULL;
4631 }
4632 if (fptr->writeconv) {
4633 rb_econv_close(fptr->writeconv);
4634 fptr->writeconv = NULL;
4635 }
4636 fptr->mode |= FMODE_BINMODE;
4637 fptr->mode &= ~FMODE_TEXTMODE;
4638 SET_BINARY_MODE_WITH_SEEK_CUR(fptr);
4639
4640 fptr->encs.enc = rb_ascii8bit_encoding();
4641 fptr->encs.enc2 = NULL;
4642 fptr->encs.ecflags = 0;
4643 fptr->encs.ecopts = Qnil;
4644 clear_codeconv(fptr);
4645
4646 return io;
4647 }
4648
4649 /*
4650 * call-seq:
4651 * ios.binmode -> ios
4652 *
4653 * Puts <em>ios</em> into binary mode.
4654 * Once a stream is in binary mode, it cannot be reset to nonbinary mode.
4655 *
4656 * - newline conversion disabled
4657 * - encoding conversion disabled
4658 * - content is treated as ASCII-8BIT
4659 *
4660 */
4661
4662 static VALUE
4663 rb_io_binmode_m(VALUE io)
4664 {
4665 VALUE write_io;
4666
4667 rb_io_ascii8bit_binmode(io);
4668
4669 write_io = GetWriteIO(io);
4670 if (write_io != io)
4671 rb_io_ascii8bit_binmode(write_io);
4672 return io;
4673 }
4674
4675 /*
4676 * call-seq:
4677 * ios.binmode? -> true or false
4678 *
4679 * Returns <code>true</code> if <em>ios</em> is binmode.
4680 */
4681 static VALUE
4682 rb_io_binmode_p(VALUE io)
4683 {
4684 rb_io_t *fptr;
4685 GetOpenFile(io, fptr);
4686 return fptr->mode & FMODE_BINMODE ? Qtrue : Qfalse;
4687 }
4688
4689 static const char*
4690 rb_io_fmode_modestr(int fmode)
4691 {
4692 if (fmode & FMODE_APPEND) {
4693 if ((fmode & FMODE_READWRITE) == FMODE_READWRITE) {
4694 return MODE_BTMODE("a+", "ab+", "at+");
4695 }
4696 return MODE_BTMODE("a", "ab", "at");
4697 }
4698 switch (fmode & FMODE_READWRITE) {
4699 default:
4700 rb_raise(rb_eArgError, "invalid access fmode 0x%x", fmode);
4701 case FMODE_READABLE:
4702 return MODE_BTMODE("r", "rb", "rt");
4703 case FMODE_WRITABLE:
4704 return MODE_BTMODE("w", "wb", "wt");
4705 case FMODE_READWRITE:
4706 if (fmode & FMODE_CREATE) {
4707 return MODE_BTMODE("w+", "wb+", "wt+");
4708 }
4709 return MODE_BTMODE("r+", "rb+", "rt+");
4710 }
4711 }
4712
4713 static int
4714 io_encname_bom_p(const char *name, long len)
4715 {
4716 static const char bom_prefix[] = "bom|utf-";
4717 enum {bom_prefix_len = (int)sizeof(bom_prefix) - 1};
4718 if (!len) {
4719 const char *p = strchr(name, ':');
4720 len = p ? (long)(p - name) : (long)strlen(name);
4721 }
4722 return len > bom_prefix_len && STRNCASECMP(name, bom_prefix, bom_prefix_len) == 0;
4723 }
4724
4725 int
4726 rb_io_modestr_fmode(const char *modestr)
4727 {
4728 int fmode = 0;
4729 const char *m = modestr, *p = NULL;
4730
4731 switch (*m++) {
4732 case 'r':
4733 fmode |= FMODE_READABLE;
4734 break;
4735 case 'w':
4736 fmode |= FMODE_WRITABLE | FMODE_TRUNC | FMODE_CREATE;
4737 break;
4738 case 'a':
4739 fmode |= FMODE_WRITABLE | FMODE_APPEND | FMODE_CREATE;
4740 break;
4741 default:
4742 error:
4743 rb_raise(rb_eArgError, "invalid access mode %s", modestr);
4744 }
4745
4746 while (*m) {
4747 switch (*m++) {
4748 case 'b':
4749 fmode |= FMODE_BINMODE;
4750 break;
4751 case 't':
4752 fmode |= FMODE_TEXTMODE;
4753 break;
4754 case '+':
4755 fmode |= FMODE_READWRITE;
4756 break;
4757 default:
4758 goto error;
4759 case ':':
4760 p = m;
4761 goto finished;
4762 }
4763 }
4764
4765 finished:
4766 if ((fmode & FMODE_BINMODE) && (fmode & FMODE_TEXTMODE))
4767 goto error;
4768 if (p && io_encname_bom_p(p, 0))
4769 fmode |= FMODE_SETENC_BY_BOM;
4770
4771 return fmode;
4772 }
4773
4774 int
4775 rb_io_oflags_fmode(int oflags)
4776 {
4777 int fmode = 0;
4778
4779 switch (oflags & (O_RDONLY|O_WRONLY|O_RDWR)) {
4780 case O_RDONLY:
4781 fmode = FMODE_READABLE;
4782 break;
4783 case O_WRONLY:
4784 fmode = FMODE_WRITABLE;
4785 break;
4786 case O_RDWR:
4787 fmode = FMODE_READWRITE;
4788 break;
4789 }
4790
4791 if (oflags & O_APPEND) {
4792 fmode |= FMODE_APPEND;
4793 }
4794 if (oflags & O_TRUNC) {
4795 fmode |= FMODE_TRUNC;
4796 }
4797 if (oflags & O_CREAT) {
4798 fmode |= FMODE_CREATE;
4799 }
4800 #ifdef O_BINARY
4801 if (oflags & O_BINARY) {
4802 fmode |= FMODE_BINMODE;
4803 }
4804 #endif
4805
4806 return fmode;
4807 }
4808
4809 static int
4810 rb_io_fmode_oflags(int fmode)
4811 {
4812 int oflags = 0;
4813
4814 switch (fmode & FMODE_READWRITE) {
4815 case FMODE_READABLE:
4816 oflags |= O_RDONLY;
4817 break;
4818 case FMODE_WRITABLE:
4819 oflags |= O_WRONLY;
4820 break;
4821 case FMODE_READWRITE:
4822 oflags |= O_RDWR;
4823 break;
4824 }
4825
4826 if (fmode & FMODE_APPEND) {
4827 oflags |= O_APPEND;
4828 }
4829 if (fmode & FMODE_TRUNC) {
4830 oflags |= O_TRUNC;
4831 }
4832 if (fmode & FMODE_CREATE) {
4833 oflags |= O_CREAT;
4834 }
4835 #ifdef O_BINARY
4836 if (fmode & FMODE_BINMODE) {
4837 oflags |= O_BINARY;
4838 }
4839 #endif
4840
4841 return oflags;
4842 }
4843
4844 int
4845 rb_io_modestr_oflags(const char *modestr)
4846 {
4847 return rb_io_fmode_oflags(rb_io_modestr_fmode(modestr));
4848 }
4849
4850 static const char*
4851 rb_io_oflags_modestr(int oflags)
4852 {
4853 #ifdef O_BINARY
4854 # define MODE_BINARY(a,b) ((oflags & O_BINARY) ? (b) : (a))
4855 #else
4856 # define MODE_BINARY(a,b) (a)
4857 #endif
4858 int accmode = oflags & (O_RDONLY|O_WRONLY|O_RDWR);
4859 if (oflags & O_APPEND) {
4860 if (accmode == O_WRONLY) {
4861 return MODE_BINARY("a", "ab");
4862 }
4863 if (accmode == O_RDWR) {
4864 return MODE_BINARY("a+", "ab+");
4865 }
4866 }
4867 switch (oflags & (O_RDONLY|O_WRONLY|O_RDWR)) {
4868 default:
4869 rb_raise(rb_eArgError, "invalid access oflags 0x%x", oflags);
4870 case O_RDONLY:
4871 return MODE_BINARY("r", "rb");
4872 case O_WRONLY:
4873 return MODE_BINARY("w", "wb");
4874 case O_RDWR:
4875 return MODE_BINARY("r+", "rb+");
4876 }
4877 }
4878
4879 /*
4880 * Convert external/internal encodings to enc/enc2
4881 * NULL => use default encoding
4882 * Qnil => no encoding specified (internal only)
4883 */
4884 static void
4885 rb_io_ext_int_to_encs(rb_encoding *ext, rb_encoding *intern, rb_encoding **enc, rb_encoding **enc2, int fmode)
4886 {
4887 int default_ext = 0;
4888
4889 if (ext == NULL) {
4890 ext = rb_default_external_encoding();
4891 default_ext = 1;
4892 }
4893 if (intern == NULL && ext != rb_ascii8bit_encoding())
4894 /* If external is ASCII-8BIT, no default transcoding */
4895 intern = rb_default_internal_encoding();
4896 if (intern == NULL || intern == (rb_encoding *)Qnil ||
4897 (!(fmode & FMODE_SETENC_BY_BOM) && (intern == ext))) {
4898 /* No internal encoding => use external + no transcoding */
4899 *enc = (default_ext && intern != ext) ? NULL : ext;
4900 *enc2 = NULL;
4901 }
4902 else {
4903 *enc = intern;
4904 *enc2 = ext;
4905 }
4906 }
4907
4908 static void
4909 unsupported_encoding(const char *name)
4910 {
4911 rb_warn("Unsupported encoding %s ignored", name);
4912 }
4913
4914 static void
4915 parse_mode_enc(const char *estr, rb_encoding **enc_p, rb_encoding **enc2_p, int *fmode_p)
4916 {
4917 const char *p;
4918 char encname[ENCODING_MAXNAMELEN+1];
4919 int idx, idx2;
4920 int fmode = fmode_p ? *fmode_p : 0;
4921 rb_encoding *ext_enc, *int_enc;
4922
4923 /* parse estr as "enc" or "enc2:enc" or "enc:-" */
4924
4925 p = strrchr(estr, ':');
4926 if (p) {
4927 long len = (p++) - estr;
4928 if (len == 0 || len > ENCODING_MAXNAMELEN)
4929 idx = -1;
4930 else {
4931 if (io_encname_bom_p(estr, len)) {
4932 fmode |= FMODE_SETENC_BY_BOM;
4933 estr += 4;
4934 len -= 4;
4935 }
4936 memcpy(encname, estr, len);
4937 encname[len] = '\0';
4938 estr = encname;
4939 idx = rb_enc_find_index(encname);
4940 }
4941 }
4942 else {
4943 long len = strlen(estr);
4944 if (io_encname_bom_p(estr, len)) {
4945 fmode |= FMODE_SETENC_BY_BOM;
4946 estr += 4;
4947 len -= 4;
4948 memcpy(encname, estr, len);
4949 encname[len] = '\0';
4950 estr = encname;
4951 }
4952 idx = rb_enc_find_index(estr);
4953 }
4954 if (fmode_p) *fmode_p = fmode;
4955
4956 if (idx >= 0)
4957 ext_enc = rb_enc_from_index(idx);
4958 else {
4959 if (idx != -2)
4960 unsupported_encoding(estr);
4961 ext_enc = NULL;
4962 }
4963
4964 int_enc = NULL;
4965 if (p) {
4966 if (*p == '-' && *(p+1) == '\0') {
4967 /* Special case - "-" => no transcoding */
4968 int_enc = (rb_encoding *)Qnil;
4969 }
4970 else {
4971 idx2 = rb_enc_find_index(p);
4972 if (idx2 < 0)
4973 unsupported_encoding(p);
4974 else if (!(fmode & FMODE_SETENC_BY_BOM) && (idx2 == idx)) {
4975 int_enc = (rb_encoding *)Qnil;
4976 }
4977 else
4978 int_enc = rb_enc_from_index(idx2);
4979 }
4980 }
4981
4982 rb_io_ext_int_to_encs(ext_enc, int_enc, enc_p, enc2_p, fmode);
4983 }
4984
4985 int
4986 rb_io_extract_encoding_option(VALUE opt, rb_encoding **enc_p, rb_encoding **enc2_p, int *fmode_p)
4987 {
4988 VALUE encoding=Qnil, extenc=Qundef, intenc=Qundef, tmp;
4989 int extracted = 0;
4990 rb_encoding *extencoding = NULL;
4991 rb_encoding *intencoding = NULL;
4992
4993 if (!NIL_P(opt)) {
4994 VALUE v;
4995 v = rb_hash_lookup2(opt, sym_encoding, Qnil);
4996 if (v != Qnil) encoding = v;
4997 v = rb_hash_lookup2(opt, sym_extenc, Qundef);
4998 if (v != Qnil) extenc = v;
4999 v = rb_hash_lookup2(opt, sym_intenc, Qundef);
5000 if (v != Qundef) intenc = v;
5001 }
5002 if ((extenc != Qundef || intenc != Qundef) && !NIL_P(encoding)) {
5003 if (!NIL_P(ruby_verbose)) {
5004 int idx = rb_to_encoding_index(encoding);
5005 rb_warn("Ignoring encoding parameter '%s': %s_encoding is used",
5006 idx < 0 ? StringValueCStr(encoding) : rb_enc_name(rb_enc_from_index(idx)),
5007 extenc == Qundef ? "internal" : "external");
5008 }
5009 encoding = Qnil;
5010 }
5011 if (extenc != Qundef && !NIL_P(extenc)) {
5012 extencoding = rb_to_encoding(extenc);
5013 }
5014 if (intenc != Qundef) {
5015 if (NIL_P(intenc)) {
5016 /* internal_encoding: nil => no transcoding */
5017 intencoding = (rb_encoding *)Qnil;
5018 }
5019 else if (!NIL_P(tmp = rb_check_string_type(intenc))) {
5020 char *p = StringValueCStr(tmp);
5021
5022 if (*p == '-' && *(p+1) == '\0') {
5023 /* Special case - "-" => no transcoding */
5024 intencoding = (rb_encoding *)Qnil;
5025 }
5026 else {
5027 intencoding = rb_to_encoding(intenc);
5028 }
5029 }
5030 else {
5031 intencoding = rb_to_encoding(intenc);
5032 }
5033 if (extencoding == intencoding) {
5034 intencoding = (rb_encoding *)Qnil;
5035 }
5036 }
5037 if (!NIL_P(encoding)) {
5038 extracted = 1;
5039 if (!NIL_P(tmp = rb_check_string_type(encoding))) {
5040 parse_mode_enc(StringValueCStr(tmp), enc_p, enc2_p, fmode_p);
5041 }
5042 else {
5043 rb_io_ext_int_to_encs(rb_to_encoding(encoding), NULL, enc_p, enc2_p, 0);
5044 }
5045 }
5046 else if (extenc != Qundef || intenc != Qundef) {
5047 extracted = 1;
5048 rb_io_ext_int_to_encs(extencoding, intencoding, enc_p, enc2_p, 0);
5049 }
5050 return extracted;
5051 }
5052
5053 typedef struct rb_io_enc_t convconfig_t;
5054
5055 static void
5056 validate_enc_binmode(int *fmode_p, int ecflags, rb_encoding *enc, rb_encoding *enc2)
5057 {
5058 int fmode = *fmode_p;
5059
5060 if ((fmode & FMODE_READABLE) &&
5061 !enc2 &&
5062 !(fmode & FMODE_BINMODE) &&
5063 !rb_enc_asciicompat(enc ? enc : rb_default_external_encoding()))
5064 rb_raise(rb_eArgError, "ASCII incompatible encoding needs binmode");
5065
5066 if (!(fmode & FMODE_BINMODE) &&
5067 (DEFAULT_TEXTMODE || (ecflags & ECONV_NEWLINE_DECORATOR_MASK))) {
5068 fmode |= DEFAULT_TEXTMODE;
5069 *fmode_p = fmode;
5070 }
5071 #if !DEFAULT_TEXTMODE
5072 else if (!(ecflags & ECONV_NEWLINE_DECORATOR_MASK)) {
5073 fmode &= ~FMODE_TEXTMODE;
5074 *fmode_p = fmode;
5075 }
5076 #endif
5077 }
5078
5079 static void
5080 extract_binmode(VALUE opthash, int *fmode)
5081 {
5082 if (!NIL_P(opthash)) {
5083 VALUE v;
5084 v = rb_hash_aref(opthash, sym_textmode);
5085 if (!NIL_P(v)) {
5086 if (*fmode & FMODE_TEXTMODE)
5087 rb_raise(rb_eArgError, "textmode specified twice");
5088 if (RTEST(v))
5089 *fmode |= FMODE_TEXTMODE;
5090 }
5091 v = rb_hash_aref(opthash, sym_binmode);
5092 if (!NIL_P(v)) {
5093 if (*fmode & FMODE_BINMODE)
5094 rb_raise(rb_eArgError, "binmode specified twice");
5095 if (RTEST(v))
5096 *fmode |= FMODE_BINMODE;
5097 }
5098
5099 if ((*fmode & FMODE_BINMODE) && (*fmode & FMODE_TEXTMODE))
5100 rb_raise(rb_eArgError, "both textmode and binmode specified");
5101 }
5102 }
5103
5104 static void
5105 rb_io_extract_modeenc(VALUE *vmode_p, VALUE *vperm_p, VALUE opthash,
5106 int *oflags_p, int *fmode_p, convconfig_t *convconfig_p)
5107 {
5108 VALUE vmode;
5109 int oflags, fmode;
5110 rb_encoding *enc, *enc2;
5111 int ecflags;
5112 VALUE ecopts;
5113 int has_enc = 0, has_vmode = 0;
5114 VALUE intmode;
5115
5116 vmode = *vmode_p;
5117
5118 /* Set to defaults */
5119 rb_io_ext_int_to_encs(NULL, NULL, &enc, &enc2, 0);
5120
5121 vmode_handle:
5122 if (NIL_P(vmode)) {
5123 fmode = FMODE_READABLE;
5124 oflags = O_RDONLY;
5125 }
5126 else if (!NIL_P(intmode = rb_check_to_integer(vmode, "to_int"))) {
5127 vmode = intmode;
5128 oflags = NUM2INT(intmode);
5129 fmode = rb_io_oflags_fmode(oflags);
5130 }
5131 else {
5132 const char *p;
5133
5134 SafeStringValue(vmode);
5135 p = StringValueCStr(vmode);
5136 fmode = rb_io_modestr_fmode(p);
5137 oflags = rb_io_fmode_oflags(fmode);
5138 p = strchr(p, ':');
5139 if (p) {
5140 has_enc = 1;
5141 parse_mode_enc(p+1, &enc, &enc2, &fmode);
5142 }
5143 else {
5144 rb_encoding *e;
5145
5146 e = (fmode & FMODE_BINMODE) ? rb_ascii8bit_encoding() : NULL;
5147 rb_io_ext_int_to_encs(e, NULL, &enc, &enc2, fmode);
5148 }
5149 }
5150
5151 if (NIL_P(opthash)) {
5152 ecflags = (fmode & FMODE_READABLE) ?
5153 MODE_BTMODE(ECONV_DEFAULT_NEWLINE_DECORATOR,
5154 0, ECONV_UNIVERSAL_NEWLINE_DECORATOR) : 0;
5155 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
5156 ecflags |= (fmode & FMODE_WRITABLE) ?
5157 MODE_BTMODE(TEXTMODE_NEWLINE_DECORATOR_ON_WRITE,
5158 0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE) : 0;
5159 #endif
5160 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
5161 ecopts = Qnil;
5162 }
5163 else {
5164 VALUE v;
5165 extract_binmode(opthash, &fmode);
5166 if (fmode & FMODE_BINMODE) {
5167 #ifdef O_BINARY
5168 oflags |= O_BINARY;
5169 #endif
5170 if (!has_enc)
5171 rb_io_ext_int_to_encs(rb_ascii8bit_encoding(), NULL, &enc, &enc2, fmode);
5172 }
5173 #if DEFAULT_TEXTMODE
5174 else if (NIL_P(vmode)) {
5175 fmode |= DEFAULT_TEXTMODE;
5176 }
5177 #endif
5178 if (!has_vmode) {
5179 v = rb_hash_aref(opthash, sym_mode);
5180 if (!NIL_P(v)) {
5181 if (!NIL_P(vmode)) {
5182 rb_raise(rb_eArgError, "mode specified twice");
5183 }
5184 has_vmode = 1;
5185 vmode = v;
5186 goto vmode_handle;
5187 }
5188 }
5189 v = rb_hash_aref(opthash, sym_perm);
5190 if (!NIL_P(v)) {
5191 if (vperm_p) {
5192 if (!NIL_P(*vperm_p)) {
5193 rb_raise(rb_eArgError, "perm specified twice");
5194 }
5195 *vperm_p = v;
5196 }
5197 else {
5198 /* perm no use, just ignore */
5199 }
5200 }
5201 ecflags = (fmode & FMODE_READABLE) ?
5202 MODE_BTMODE(ECONV_DEFAULT_NEWLINE_DECORATOR,
5203 0, ECONV_UNIVERSAL_NEWLINE_DECORATOR) : 0;
5204 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
5205 ecflags |= (fmode & FMODE_WRITABLE) ?
5206 MODE_BTMODE(TEXTMODE_NEWLINE_DECORATOR_ON_WRITE,
5207 0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE) : 0;
5208 #endif
5209
5210 if (rb_io_extract_encoding_option(opthash, &enc, &enc2, &fmode)) {
5211 if (has_enc) {
5212 rb_raise(rb_eArgError, "encoding specified twice");
5213 }
5214 }
5215 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
5216 ecflags = rb_econv_prepare_options(opthash, &ecopts, ecflags);
5217 }
5218
5219 validate_enc_binmode(&fmode, ecflags, enc, enc2);
5220
5221 *vmode_p = vmode;
5222
5223 *oflags_p = oflags;
5224 *fmode_p = fmode;
5225 convconfig_p->enc = enc;
5226 convconfig_p->enc2 = enc2;
5227 convconfig_p->ecflags = ecflags;
5228 convconfig_p->ecopts = ecopts;
5229 }
5230
5231 struct sysopen_struct {
5232 VALUE fname;
5233 int oflags;
5234 mode_t perm;
5235 };
5236
5237 static void *
5238 sysopen_func(void *ptr)
5239 {
5240 const struct sysopen_struct *data = ptr;
5241 const char *fname = RSTRING_PTR(data->fname);
5242 return (void *)(VALUE)rb_cloexec_open(fname, data->oflags, data->perm);
5243 }
5244
5245 static inline int
5246 rb_sysopen_internal(struct sysopen_struct *data)
5247 {
5248 int fd;
5249 fd = (int)(VALUE)rb_thread_call_without_gvl(sysopen_func, data, RUBY_UBF_IO, 0);
5250 if (0 <= fd)
5251 rb_update_max_fd(fd);
5252 return fd;
5253 }
5254
5255 static int
5256 rb_sysopen(VALUE fname, int oflags, mode_t perm)
5257 {
5258 int fd;
5259 struct sysopen_struct data;
5260
5261 data.fname = rb_str_encode_ospath(fname);
5262 data.oflags = oflags;
5263 data.perm = perm;
5264
5265 fd = rb_sysopen_internal(&data);
5266 if (fd < 0) {
5267 if (errno == EMFILE || errno == ENFILE) {
5268 rb_gc();
5269 fd = rb_sysopen_internal(&data);
5270 }
5271 if (fd < 0) {
5272 rb_sys_fail_path(fname);
5273 }
5274 }
5275 return fd;
5276 }
5277
5278 FILE *
5279 rb_fdopen(int fd, const char *modestr)
5280 {
5281 FILE *file;
5282
5283 #if defined(__sun)
5284 errno = 0;
5285 #endif
5286 file = fdopen(fd, modestr);
5287 if (!file) {
5288 if (
5289 #if defined(__sun)
5290 errno == 0 ||
5291 #endif
5292 errno == EMFILE || errno == ENFILE) {
5293 rb_gc();
5294 #if defined(__sun)
5295 errno = 0;
5296 #endif
5297 file = fdopen(fd, modestr);
5298 }
5299 if (!file) {
5300 #ifdef _WIN32
5301 if (errno == 0) errno = EINVAL;
5302 #elif defined(__sun)
5303 if (errno == 0) errno = EMFILE;
5304 #endif
5305 rb_sys_fail(0);
5306 }
5307 }
5308
5309 /* xxx: should be _IONBF? A buffer in FILE may have trouble. */
5310 #ifdef USE_SETVBUF
5311 if (setvbuf(file, NULL, _IOFBF, 0) != 0)
5312 rb_warn("setvbuf() can't be honoured (fd=%d)", fd);
5313 #endif
5314 return file;
5315 }
5316
5317 static void
5318 io_check_tty(rb_io_t *fptr)
5319 {
5320 if (isatty(fptr->fd))
5321 fptr->mode |= FMODE_TTY|FMODE_DUPLEX;
5322 }
5323
5324 static VALUE rb_io_internal_encoding(VALUE);
5325 static void io_encoding_set(rb_io_t *, VALUE, VALUE, VALUE);
5326
5327 static int
5328 io_strip_bom(VALUE io)
5329 {
5330 VALUE b1, b2, b3, b4;
5331
5332 if (NIL_P(b1 = rb_io_getbyte(io))) return 0;
5333 switch (b1) {
5334 case INT2FIX(0xEF):
5335 if (NIL_P(b2 = rb_io_getbyte(io))) break;
5336 if (b2 == INT2FIX(0xBB) && !NIL_P(b3 = rb_io_getbyte(io))) {
5337 if (b3 == INT2FIX(0xBF)) {
5338 return rb_utf8_encindex();
5339 }
5340 rb_io_ungetbyte(io, b3);
5341 }
5342 rb_io_ungetbyte(io, b2);
5343 break;
5344
5345 case INT2FIX(0xFE):
5346 if (NIL_P(b2 = rb_io_getbyte(io))) break;
5347 if (b2 == INT2FIX(0xFF)) {
5348 return rb_enc_find_index("UTF-16BE");
5349 }
5350 rb_io_ungetbyte(io, b2);
5351 break;
5352
5353 case INT2FIX(0xFF):
5354 if (NIL_P(b2 = rb_io_getbyte(io))) break;
5355 if (b2 == INT2FIX(0xFE)) {
5356 b3 = rb_io_getbyte(io);
5357 if (b3 == INT2FIX(0) && !NIL_P(b4 = rb_io_getbyte(io))) {
5358 if (b4 == INT2FIX(0)) {
5359 return rb_enc_find_index("UTF-32LE");
5360 }
5361 rb_io_ungetbyte(io, b4);
5362 rb_io_ungetbyte(io, b3);
5363 }
5364 else {
5365 rb_io_ungetbyte(io, b3);
5366 return rb_enc_find_index("UTF-16LE");
5367 }
5368 }
5369 rb_io_ungetbyte(io, b2);
5370 break;
5371
5372 case INT2FIX(0):
5373 if (NIL_P(b2 = rb_io_getbyte(io))) break;
5374 if (b2 == INT2FIX(0) && !NIL_P(b3 = rb_io_getbyte(io))) {
5375 if (b3 == INT2FIX(0xFE) && !NIL_P(b4 = rb_io_getbyte(io))) {
5376 if (b4 == INT2FIX(0xFF)) {
5377 return rb_enc_find_index("UTF-32BE");
5378 }
5379 rb_io_ungetbyte(io, b4);
5380 }
5381 rb_io_ungetbyte(io, b3);
5382 }
5383 rb_io_ungetbyte(io, b2);
5384 break;
5385 }
5386 rb_io_ungetbyte(io, b1);
5387 return 0;
5388 }
5389
5390 static void
5391 io_set_encoding_by_bom(VALUE io)
5392 {
5393 int idx = io_strip_bom(io);
5394 rb_io_t *fptr;
5395
5396 GetOpenFile(io, fptr);
5397 if (idx) {
5398 io_encoding_set(fptr, rb_enc_from_encoding(rb_enc_from_index(idx)),
5399 rb_io_internal_encoding(io), Qnil);
5400 }
5401 else {
5402 fptr->encs.enc2 = NULL;
5403 }
5404 }
5405
5406 static VALUE
5407 rb_file_open_generic(VALUE io, VALUE filename, int oflags, int fmode, convconfig_t *convconfig, mode_t perm)
5408 {
5409 rb_io_t *fptr;
5410 convconfig_t cc;
5411 if (!convconfig) {
5412 /* Set to default encodings */
5413 rb_io_ext_int_to_encs(NULL, NULL, &cc.enc, &cc.enc2, fmode);
5414 cc.ecflags = 0;
5415 cc.ecopts = Qnil;
5416 convconfig = &cc;
5417 }
5418 validate_enc_binmode(&fmode, convconfig->ecflags,
5419 convconfig->enc, convconfig->enc2);
5420
5421 MakeOpenFile(io, fptr);
5422 fptr->mode = fmode;
5423 fptr->encs = *convconfig;
5424 fptr->pathv = rb_str_new_frozen(filename);
5425 fptr->fd = rb_sysopen(fptr->pathv, oflags, perm);
5426 io_check_tty(fptr);
5427 if (fmode & FMODE_SETENC_BY_BOM) io_set_encoding_by_bom(io);
5428
5429 return io;
5430 }
5431
5432 static VALUE
5433 rb_file_open_internal(VALUE io, VALUE filename, const char *modestr)
5434 {
5435 int fmode = rb_io_modestr_fmode(modestr);
5436 const char *p = strchr(modestr, ':');
5437 convconfig_t convconfig;
5438
5439 if (p) {
5440 parse_mode_enc(p+1, &convconfig.enc, &convconfig.enc2, &fmode);
5441 }
5442 else {
5443 rb_encoding *e;
5444 /* Set to default encodings */
5445
5446 e = (fmode & FMODE_BINMODE) ? rb_ascii8bit_encoding() : NULL;
5447 rb_io_ext_int_to_encs(e, NULL, &convconfig.enc, &convconfig.enc2, fmode);
5448 convconfig.ecflags = 0;
5449 convconfig.ecopts = Qnil;
5450 }
5451
5452 return rb_file_open_generic(io, filename,
5453 rb_io_fmode_oflags(fmode),
5454 fmode,
5455 &convconfig,
5456 0666);
5457 }
5458
5459 VALUE
5460 rb_file_open_str(VALUE fname, const char *modestr)
5461 {
5462 FilePathValue(fname);
5463 return rb_file_open_internal(io_alloc(rb_cFile), fname, modestr);
5464 }
5465
5466 VALUE
5467 rb_file_open(const char *fname, const char *modestr)
5468 {
5469 return rb_file_open_internal(io_alloc(rb_cFile), rb_str_new_cstr(fname), modestr);
5470 }
5471
5472 #if defined(__CYGWIN__) || !defined(HAVE_FORK)
5473 static struct pipe_list {
5474 rb_io_t *fptr;
5475 struct pipe_list *next;
5476 } *pipe_list;
5477
5478 static void
5479 pipe_add_fptr(rb_io_t *fptr)
5480 {
5481 struct pipe_list *list;
5482
5483 list = ALLOC(struct pipe_list);
5484 list->fptr = fptr;
5485 list->next = pipe_list;
5486 pipe_list = list;
5487 }
5488
5489 static void
5490 pipe_del_fptr(rb_io_t *fptr)
5491 {
5492 struct pipe_list *list = pipe_list;
5493 struct pipe_list *tmp;
5494
5495 if (list->fptr == fptr) {
5496 pipe_list = list->next;
5497 free(list);
5498 return;
5499 }
5500
5501 while (list->next) {
5502 if (list->next->fptr == fptr) {
5503 tmp = list->next;
5504 list->next = list->next->next;
5505 free(tmp);
5506 return;
5507 }
5508 list = list->next;
5509 }
5510 }
5511
5512 static void
5513 pipe_atexit(void)
5514 {
5515 struct pipe_list *list = pipe_list;
5516 struct pipe_list *tmp;
5517
5518 while (list) {
5519 tmp = list->next;
5520 rb_io_fptr_finalize(list->fptr);
5521 list = tmp;
5522 }
5523 }
5524
5525 static void
5526 pipe_finalize(rb_io_t *fptr, int noraise)
5527 {
5528 #if !defined(HAVE_FORK) && !defined(_WIN32)
5529 int status = 0;
5530 if (fptr->stdio_file) {
5531 status = pclose(fptr->stdio_file);
5532 }
5533 fptr->fd = -1;
5534 fptr->stdio_file = 0;
5535 rb_last_status_set(status, fptr->pid);
5536 #else
5537 fptr_finalize(fptr, noraise);
5538 #endif
5539 pipe_del_fptr(fptr);
5540 }
5541 #endif
5542
5543 void
5544 rb_io_synchronized(rb_io_t *fptr)
5545 {
5546 rb_io_check_initialized(fptr);
5547 fptr->mode |= FMODE_SYNC;
5548 }
5549
5550 void
5551 rb_io_unbuffered(rb_io_t *fptr)
5552 {
5553 rb_io_synchronized(fptr);
5554 }
5555
5556 int
5557 rb_pipe(int *pipes)
5558 {
5559 int ret;
5560 ret = rb_cloexec_pipe(pipes);
5561 if (ret == -1) {
5562 if (errno == EMFILE || errno == ENFILE) {
5563 rb_gc();
5564 ret = rb_cloexec_pipe(pipes);
5565 }
5566 }
5567 if (ret == 0) {
5568 rb_update_max_fd(pipes[0]);
5569 rb_update_max_fd(pipes[1]);
5570 }
5571 return ret;
5572 }
5573
5574 #ifdef _WIN32
5575 #define HAVE_SPAWNV 1
5576 #define spawnv(mode, cmd, args) rb_w32_aspawn((mode), (cmd), (args))
5577 #define spawn(mode, cmd) rb_w32_spawn((mode), (cmd), 0)
5578 #endif
5579
5580 #if defined(HAVE_FORK) || defined(HAVE_SPAWNV)
5581 struct popen_arg {
5582 VALUE execarg_obj;
5583 struct rb_execarg *eargp;
5584 int modef;
5585 int pair[2];
5586 int write_pair[2];
5587 };
5588 #endif
5589
5590 #ifdef HAVE_FORK
5591 static void
5592 popen_redirect(struct popen_arg *p)
5593 {
5594 if ((p->modef & FMODE_READABLE) && (p->modef & FMODE_WRITABLE)) {
5595 close(p->write_pair[1]);
5596 if (p->write_pair[0] != 0) {
5597 dup2(p->write_pair[0], 0);
5598 close(p->write_pair[0]);
5599 }
5600 close(p->pair[0]);
5601 if (p->pair[1] != 1) {
5602 dup2(p->pair[1], 1);
5603 close(p->pair[1]);
5604 }
5605 }
5606 else if (p->modef & FMODE_READABLE) {
5607 close(p->pair[0]);
5608 if (p->pair[1] != 1) {
5609 dup2(p->pair[1], 1);
5610 close(p->pair[1]);
5611 }
5612 }
5613 else {
5614 close(p->pair[1]);
5615 if (p->pair[0] != 0) {
5616 dup2(p->pair[0], 0);
5617 close(p->pair[0]);
5618 }
5619 }
5620 }
5621
5622 #if defined(__linux__)
5623 /* Linux /proc/self/status contains a line: "FDSize:\t<nnn>\n"
5624 * Since /proc may not be available, linux_get_maxfd is just a hint.
5625 * This function, linux_get_maxfd, must be async-signal-safe.
5626 * I.e. opendir() is not usable.
5627 *
5628 * Note that memchr() and memcmp is *not* async-signal-safe in POSIX.
5629 * However they are easy to re-implement in async-signal-safe manner.
5630 * (Also note that there is missing/memcmp.c.)
5631 */
5632 static int
5633 linux_get_maxfd(void)
5634 {
5635 int fd;
5636 char buf[4096], *p, *np, *e;
5637 ssize_t ss;
5638 fd = rb_cloexec_open("/proc/self/status", O_RDONLY|O_NOCTTY, 0);
5639 if (fd == -1) return -1;
5640 ss = read(fd, buf, sizeof(buf));
5641 if (ss == -1) goto err;
5642 p = buf;
5643 e = buf + ss;
5644 while ((int)sizeof("FDSize:\t0\n")-1 <= e-p &&
5645 (np = memchr(p, '\n', e-p)) != NULL) {
5646 if (memcmp(p, "FDSize:", sizeof("FDSize:")-1) == 0) {
5647 int fdsize;
5648 p += sizeof("FDSize:")-1;
5649 *np = '\0';
5650 fdsize = (int)ruby_strtoul(p, (char **)NULL, 10);
5651 close(fd);
5652 return fdsize;
5653 }
5654 p = np+1;
5655 }
5656 /* fall through */
5657
5658 err:
5659 close(fd);
5660 return -1;
5661 }
5662 #endif
5663
5664 /* This function should be async-signal-safe. */
5665 void
5666 rb_close_before_exec(int lowfd, int maxhint, VALUE noclose_fds)
5667 {
5668 int fd, ret;
5669 int max = (int)max_file_descriptor;
5670 #ifdef F_MAXFD
5671 /* F_MAXFD is available since NetBSD 2.0. */
5672 ret = fcntl(0, F_MAXFD); /* async-signal-safe */
5673 if (ret != -1)
5674 maxhint = max = ret;
5675 #elif defined(__linux__)
5676 ret = linux_get_maxfd();
5677 if (maxhint < ret)
5678 maxhint = ret;
5679 /* maxhint = max = ret; if (ret == -1) abort(); // test */
5680 #endif
5681 if (max < maxhint)
5682 max = maxhint;
5683 for (fd = lowfd; fd <= max; fd++) {
5684 if (!NIL_P(noclose_fds) &&
5685 RTEST(rb_hash_lookup(noclose_fds, INT2FIX(fd)))) /* async-signal-safe */
5686 continue;
5687 ret = fcntl(fd, F_GETFD); /* async-signal-safe */
5688 if (ret != -1 && !(ret & FD_CLOEXEC)) {
5689 fcntl(fd, F_SETFD, ret|FD_CLOEXEC); /* async-signal-safe */
5690 }
5691 #define CONTIGUOUS_CLOSED_FDS 20
5692 if (ret != -1) {
5693 if (max < fd + CONTIGUOUS_CLOSED_FDS)
5694 max = fd + CONTIGUOUS_CLOSED_FDS;
5695 }
5696 }
5697 }
5698
5699 static int
5700 popen_exec(void *pp, char *errmsg, size_t errmsg_len)
5701 {
5702 struct popen_arg *p = (struct popen_arg*)pp;
5703
5704 return rb_exec_async_signal_safe(p->eargp, errmsg, errmsg_len);
5705 }
5706 #endif
5707
5708 static VALUE
5709 pipe_open(VALUE execarg_obj, const char *modestr, int fmode, convconfig_t *convconfig)
5710 {
5711 struct rb_execarg *eargp = NIL_P(execarg_obj) ? NULL : rb_execarg_get(execarg_obj);
5712 VALUE prog = eargp ? (eargp->use_shell ? eargp->invoke.sh.shell_script : eargp->invoke.cmd.command_name) : Qfalse ;
5713 rb_pid_t pid = 0;
5714 rb_io_t *fptr;
5715 VALUE port;
5716 rb_io_t *write_fptr;
5717 VALUE write_port;
5718 #if defined(HAVE_FORK)
5719 int status;
5720 char errmsg[80] = { '\0' };
5721 #endif
5722 #if defined(HAVE_FORK) || defined(HAVE_SPAWNV)
5723 struct popen_arg arg;
5724 int e = 0;
5725 #endif
5726 #if defined(HAVE_SPAWNV)
5727 # if defined(HAVE_SPAWNVE)
5728 # define DO_SPAWN(cmd, args, envp) ((args) ? \
5729 spawnve(P_NOWAIT, (cmd), (args), (envp)) : \
5730 spawne(P_NOWAIT, (cmd), (envp)))
5731 # else
5732 # define DO_SPAWN(cmd, args, envp) ((args) ? \
5733 spawnv(P_NOWAIT, (cmd), (args)) : \
5734 spawn(P_NOWAIT, (cmd)))
5735 # endif
5736 # if !defined(HAVE_FORK)
5737 char **args = NULL;
5738 # if defined(HAVE_SPAWNVE)
5739 char **envp = NULL;
5740 # endif
5741 # endif
5742 #endif
5743 #if !defined(HAVE_FORK)
5744 struct rb_execarg sarg, *sargp = &sarg;
5745 #endif
5746 FILE *fp = 0;
5747 int fd = -1;
5748 int write_fd = -1;
5749 #if !defined(HAVE_FORK)
5750 const char *cmd = 0;
5751 #if !defined(HAVE_SPAWNV)
5752 int argc;
5753 VALUE *argv;
5754 #endif
5755
5756 if (prog)
5757 cmd = StringValueCStr(prog);
5758 #endif
5759
5760 #if defined(HAVE_FORK) || defined(HAVE_SPAWNV)
5761 arg.execarg_obj = execarg_obj;
5762 arg.eargp = eargp;
5763 arg.modef = fmode;
5764 arg.pair[0] = arg.pair[1] = -1;
5765 arg.write_pair[0] = arg.write_pair[1] = -1;
5766 # if !defined(HAVE_FORK)
5767 if (eargp && !eargp->use_shell) {
5768 args = ARGVSTR2ARGV(eargp->invoke.cmd.argv_str);
5769 }
5770 # endif
5771 switch (fmode & (FMODE_READABLE|FMODE_WRITABLE)) {
5772 case FMODE_READABLE|FMODE_WRITABLE:
5773 if (rb_pipe(arg.write_pair) < 0)
5774 rb_sys_fail_str(prog);
5775 if (rb_pipe(arg.pair) < 0) {
5776 int e = errno;
5777 close(arg.write_pair[0]);
5778 close(arg.write_pair[1]);
5779 errno = e;
5780 rb_sys_fail_str(prog);
5781 }
5782 if (eargp) {
5783 rb_execarg_addopt(execarg_obj, INT2FIX(0), INT2FIX(arg.write_pair[0]));
5784 rb_execarg_addopt(execarg_obj, INT2FIX(1), INT2FIX(arg.pair[1]));
5785 }
5786 break;
5787 case FMODE_READABLE:
5788 if (rb_pipe(arg.pair) < 0)
5789 rb_sys_fail_str(prog);
5790 if (eargp)
5791 rb_execarg_addopt(execarg_obj, INT2FIX(1), INT2FIX(arg.pair[1]));
5792 break;
5793 case FMODE_WRITABLE:
5794 if (rb_pipe(arg.pair) < 0)
5795 rb_sys_fail_str(prog);
5796 if (eargp)
5797 rb_execarg_addopt(execarg_obj, INT2FIX(0), INT2FIX(arg.pair[0]));
5798 break;
5799 default:
5800 rb_sys_fail_str(prog);
5801 }
5802 if (!NIL_P(execarg_obj)) {
5803 rb_execarg_fixup(execarg_obj);
5804 # if defined(HAVE_FORK)
5805 pid = rb_fork_async_signal_safe(&status, popen_exec, &arg, arg.eargp->redirect_fds, errmsg, sizeof(errmsg));
5806 # else
5807 rb_execarg_run_options(eargp, sargp, NULL, 0);
5808 # if defined(HAVE_SPAWNVE)
5809 if (eargp->envp_str) envp = (char **)RSTRING_PTR(eargp->envp_str);
5810 # endif
5811 while ((pid = DO_SPAWN(cmd, args, envp)) == -1) {
5812 /* exec failed */
5813 switch (e = errno) {
5814 case EAGAIN:
5815 # if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
5816 case EWOULDBLOCK:
5817 # endif
5818 rb_thread_sleep(1);
5819 continue;
5820 }
5821 break;
5822 }
5823 if (eargp)
5824 rb_execarg_run_options(sargp, NULL, NULL, 0);
5825 # endif
5826 }
5827 else {
5828 # if defined(HAVE_FORK)
5829 pid = rb_fork_ruby(&status);
5830 if (pid == 0) { /* child */
5831 rb_thread_atfork();
5832 popen_redirect(&arg);
5833 rb_io_synchronized(RFILE(orig_stdout)->fptr);
5834 rb_io_synchronized(RFILE(orig_stderr)->fptr);
5835 return Qnil;
5836 }
5837 # else
5838 rb_notimplement();
5839 # endif
5840 }
5841
5842 /* parent */
5843 if (pid == -1) {
5844 # if defined(HAVE_FORK)
5845 e = errno;
5846 # endif
5847 close(arg.pair[0]);
5848 close(arg.pair[1]);
5849 if ((fmode & (FMODE_READABLE|FMODE_WRITABLE)) == (FMODE_READABLE|FMODE_WRITABLE)) {
5850 close(arg.write_pair[0]);
5851 close(arg.write_pair[1]);
5852 }
5853 errno = e;
5854 # if defined(HAVE_FORK)
5855 if (errmsg[0])
5856 rb_sys_fail(errmsg);
5857 # endif
5858 rb_sys_fail_str(prog);
5859 }
5860 if ((fmode & FMODE_READABLE) && (fmode & FMODE_WRITABLE)) {
5861 close(arg.pair[1]);
5862 fd = arg.pair[0];
5863 close(arg.write_pair[0]);
5864 write_fd = arg.write_pair[1];
5865 }
5866 else if (fmode & FMODE_READABLE) {
5867 close(arg.pair[1]);
5868 fd = arg.pair[0];
5869 }
5870 else {
5871 close(arg.pair[0]);
5872 fd = arg.pair[1];
5873 }
5874 #else
5875 if (argc) {
5876 prog = rb_ary_join(rb_ary_new4(argc, argv), rb_str_new2(" "));
5877 cmd = StringValueCStr(prog);
5878 }
5879 if (!NIL_P(execarg_obj)) {
5880 rb_execarg_fixup(execarg_obj);
5881 rb_execarg_run_options(eargp, sargp, NULL, 0);
5882 }
5883 fp = popen(cmd, modestr);
5884 if (eargp)
5885 rb_execarg_run_options(sargp, NULL, NULL, 0);
5886 if (!fp) rb_sys_fail_path(prog);
5887 fd = fileno(fp);
5888 #endif
5889
5890 port = io_alloc(rb_cIO);
5891 MakeOpenFile(port, fptr);
5892 fptr->fd = fd;
5893 fptr->stdio_file = fp;
5894 fptr->mode = fmode | FMODE_SYNC|FMODE_DUPLEX;
5895 if (convconfig) {
5896 fptr->encs = *convconfig;
5897 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
5898 if (fptr->encs.ecflags & ECONV_DEFAULT_NEWLINE_DECORATOR) {
5899 fptr->encs.ecflags |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;
5900 }
5901 #endif
5902 }
5903 else {
5904 if (NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {
5905 fptr->encs.ecflags |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;
5906 }
5907 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
5908 if (NEED_NEWLINE_DECORATOR_ON_WRITE(fptr)) {
5909 fptr->encs.ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
5910 }
5911 #endif
5912 }
5913 fptr->pid = pid;
5914
5915 if (0 <= write_fd) {
5916 write_port = io_alloc(rb_cIO);
5917 MakeOpenFile(write_port, write_fptr);
5918 write_fptr->fd = write_fd;
5919 write_fptr->mode = (fmode & ~FMODE_READABLE)| FMODE_SYNC|FMODE_DUPLEX;
5920 fptr->mode &= ~FMODE_WRITABLE;
5921 fptr->tied_io_for_writing = write_port;
5922 rb_ivar_set(port, rb_intern("@tied_io_for_writing"), write_port);
5923 }
5924
5925 #if defined (__CYGWIN__) || !defined(HAVE_FORK)
5926 fptr->finalize = pipe_finalize;
5927 pipe_add_fptr(fptr);
5928 #endif
5929 return port;
5930 }
5931
5932 static int
5933 is_popen_fork(VALUE prog)
5934 {
5935 if (RSTRING_LEN(prog) == 1 && RSTRING_PTR(prog)[0] == '-') {
5936 #if !defined(HAVE_FORK)
5937 rb_raise(rb_eNotImpError,
5938 "fork() function is unimplemented on this machine");
5939 #else
5940 return TRUE;
5941 #endif
5942 }
5943 return FALSE;
5944 }
5945
5946 static VALUE
5947 pipe_open_s(VALUE prog, const char *modestr, int fmode, convconfig_t *convconfig)
5948 {
5949 int argc = 1;
5950 VALUE *argv = &prog;
5951 VALUE execarg_obj = Qnil;
5952
5953 if (!is_popen_fork(prog))
5954 execarg_obj = rb_execarg_new(argc, argv, TRUE);
5955 return pipe_open(execarg_obj, modestr, fmode, convconfig);
5956 }
5957
5958 /*
5959 * call-seq:
5960 * IO.popen([env,] cmd, mode="r" [, opt]) -> io
5961 * IO.popen([env,] cmd, mode="r" [, opt]) {|io| block } -> obj
5962 *
5963 * Runs the specified command as a subprocess; the subprocess's
5964 * standard input and output will be connected to the returned
5965 * <code>IO</code> object.
5966 *
5967 * The PID of the started process can be obtained by IO#pid method.
5968 *
5969 * _cmd_ is a string or an array as follows.
5970 *
5971 * cmd:
5972 * "-" : fork
5973 * commandline : command line string which is passed to a shell
5974 * [env, cmdname, arg1, ..., opts] : command name and zero or more arguments (no shell)
5975 * [env, [cmdname, argv0], arg1, ..., opts] : command name, argv[0] and zero or more arguments (no shell)
5976 * (env and opts are optional.)
5977 *
5978 * If _cmd_ is a +String+ ``<code>-</code>'',
5979 * then a new instance of Ruby is started as the subprocess.
5980 *
5981 * If <i>cmd</i> is an +Array+ of +String+,
5982 * then it will be used as the subprocess's +argv+ bypassing a shell.
5983 * The array can contains a hash at first for environments and
5984 * a hash at last for options similar to <code>spawn</code>.
5985 *
5986 * The default mode for the new file object is ``r'',
5987 * but <i>mode</i> may be set to any of the modes listed in the description for class IO.
5988 * The last argument <i>opt</i> qualifies <i>mode</i>.
5989 *
5990 * # set IO encoding
5991 * IO.popen("nkf -e filename", :external_encoding=>"EUC-JP") {|nkf_io|
5992 * euc_jp_string = nkf_io.read
5993 * }
5994 *
5995 * # merge standard output and standard error using
5996 * # spawn option. See the document of Kernel.spawn.
5997 * IO.popen(["ls", "/", :err=>[:child, :out]]) {|ls_io|
5998 * ls_result_with_error = ls_io.read
5999 * }
6000 *
6001 * # spawn options can be mixed with IO options
6002 * IO.popen(["ls", "/"], :err=>[:child, :out]) {|ls_io|
6003 * ls_result_with_error = ls_io.read
6004 * }
6005 *
6006 * Raises exceptions which <code>IO.pipe</code> and
6007 * <code>Kernel.spawn</code> raise.
6008 *
6009 * If a block is given, Ruby will run the command as a child connected
6010 * to Ruby with a pipe. Ruby's end of the pipe will be passed as a
6011 * parameter to the block.
6012 * At the end of block, Ruby close the pipe and sets <code>$?</code>.
6013 * In this case <code>IO.popen</code> returns
6014 * the value of the block.
6015 *
6016 * If a block is given with a _cmd_ of ``<code>-</code>'',
6017 * the block will be run in two separate processes: once in the parent,
6018 * and once in a child. The parent process will be passed the pipe
6019 * object as a parameter to the block, the child version of the block
6020 * will be passed <code>nil</code>, and the child's standard in and
6021 * standard out will be connected to the parent through the pipe. Not
6022 * available on all platforms.
6023 *
6024 * f = IO.popen("uname")
6025 * p f.readlines
6026 * f.close
6027 * puts "Parent is #{Process.pid}"
6028 * IO.popen("date") { |f| puts f.gets }
6029 * IO.popen("-") {|f| $stderr.puts "#{Process.pid} is here, f is #{f.inspect}"}
6030 * p $?
6031 * IO.popen(%w"sed -e s|^|<foo>| -e s&$&;zot;&", "r+") {|f|
6032 * f.puts "bar"; f.close_write; puts f.gets
6033 * }
6034 *
6035 * <em>produces:</em>
6036 *
6037 * ["Linux\n"]
6038 * Parent is 21346
6039 * Thu Jan 15 22:41:19 JST 2009
6040 * 21346 is here, f is #<IO:fd 3>
6041 * 21352 is here, f is nil
6042 * #<Process::Status: pid 21352 exit 0>
6043 * <foo>bar;zot;
6044 */
6045
6046 static VALUE
6047 rb_io_s_popen(int argc, VALUE *argv, VALUE klass)
6048 {
6049 const char *modestr;
6050 VALUE pname, pmode = Qnil, port, tmp, opt = Qnil, env = Qnil, execarg_obj = Qnil;
6051 int oflags, fmode;
6052 convconfig_t convconfig;
6053
6054 if (argc > 1 && !NIL_P(opt = rb_check_hash_type(argv[argc-1]))) --argc;
6055 if (argc > 1 && !NIL_P(env = rb_check_hash_type(argv[0]))) --argc, ++argv;
6056 switch (argc) {
6057 case 2:
6058 pmode = argv[1];
6059 case 1:
6060 pname = argv[0];
6061 break;
6062 default:
6063 {
6064 int ex = !NIL_P(opt);
6065 rb_error_arity(argc + ex, 1 + ex, 2 + ex);
6066 }
6067 }
6068
6069 tmp = rb_check_array_type(pname);
6070 if (!NIL_P(tmp)) {
6071 long len = RARRAY_LEN(tmp);
6072 #if SIZEOF_LONG > SIZEOF_INT
6073 if (len > INT_MAX) {
6074 rb_raise(rb_eArgError, "too many arguments");
6075 }
6076 #endif
6077 tmp = rb_ary_dup(tmp);
6078 RBASIC(tmp)->klass = 0;
6079 execarg_obj = rb_execarg_new((int)len, RARRAY_PTR(tmp), FALSE);
6080 rb_ary_clear(tmp);
6081 }
6082 else {
6083 SafeStringValue(pname);
6084 execarg_obj = Qnil;
6085 if (!is_popen_fork(pname))
6086 execarg_obj = rb_execarg_new(1, &pname, TRUE);
6087 }
6088 if (!NIL_P(execarg_obj)) {
6089 if (!NIL_P(opt))
6090 opt = rb_execarg_extract_options(execarg_obj, opt);
6091 if (!NIL_P(env))
6092 rb_execarg_setenv(execarg_obj, env);
6093 }
6094 rb_io_extract_modeenc(&pmode, 0, opt, &oflags, &fmode, &convconfig);
6095 modestr = rb_io_oflags_modestr(oflags);
6096
6097 port = pipe_open(execarg_obj, modestr, fmode, &convconfig);
6098 if (NIL_P(port)) {
6099 /* child */
6100 if (rb_block_given_p()) {
6101 rb_yield(Qnil);
6102 rb_io_flush(rb_stdout);
6103 rb_io_flush(rb_stderr);
6104 _exit(0);
6105 }
6106 return Qnil;
6107 }
6108 RBASIC(port)->klass = klass;
6109 if (rb_block_given_p()) {
6110 return rb_ensure(rb_yield, port, io_close, port);
6111 }
6112 return port;
6113 }
6114
6115 static void
6116 rb_scan_open_args(int argc, VALUE *argv,
6117 VALUE *fname_p, int *oflags_p, int *fmode_p,
6118 convconfig_t *convconfig_p, mode_t *perm_p)
6119 {
6120 VALUE opt, fname, vmode, vperm;
6121 int oflags, fmode;
6122 mode_t perm;
6123
6124 argc = rb_scan_args(argc, argv, "12:", &fname, &vmode, &vperm, &opt);
6125 FilePathValue(fname);
6126
6127 rb_io_extract_modeenc(&vmode, &vperm, opt, &oflags, &fmode, convconfig_p);
6128
6129 perm = NIL_P(vperm) ? 0666 : NUM2MODET(vperm);
6130
6131 *fname_p = fname;
6132 *oflags_p = oflags;
6133 *fmode_p = fmode;
6134 *perm_p = perm;
6135 }
6136
6137 static VALUE
6138 rb_open_file(int argc, VALUE *argv, VALUE io)
6139 {
6140 VALUE fname;
6141 int oflags, fmode;
6142 convconfig_t convconfig;
6143 mode_t perm;
6144
6145 rb_scan_open_args(argc, argv, &fname, &oflags, &fmode, &convconfig, &perm);
6146 rb_file_open_generic(io, fname, oflags, fmode, &convconfig, perm);
6147
6148 return io;
6149 }
6150
6151
6152 /*
6153 * Document-method: File::open
6154 *
6155 * call-seq:
6156 * File.open(filename, mode="r" [, opt]) -> file
6157 * File.open(filename [, mode [, perm]] [, opt]) -> file
6158 * File.open(filename, mode="r" [, opt]) {|file| block } -> obj
6159 * File.open(filename [, mode [, perm]] [, opt]) {|file| block } -> obj
6160 *
6161 * With no associated block, <code>File.open</code> is a synonym for
6162 * File.new. If the optional code block is given, it will
6163 * be passed the opened +file+ as an argument and the File object will
6164 * automatically be closed when the block terminates. The value of the block
6165 * will be returned from <code>File.open</code>.
6166 *
6167 * If a file is being created, its initial permissions may be set using the
6168 * +perm+ parameter. See File.new for further discussion.
6169 *
6170 * See IO.new for a description of the +mode+ and +opt+ parameters.
6171 */
6172
6173 /*
6174 * Document-method: IO::open
6175 *
6176 * call-seq:
6177 * IO.open(fd, mode="r" [, opt]) -> io
6178 * IO.open(fd, mode="r" [, opt]) { |io| block } -> obj
6179 *
6180 * With no associated block, <code>IO.open</code> is a synonym for IO.new. If
6181 * the optional code block is given, it will be passed +io+ as an argument,
6182 * and the IO object will automatically be closed when the block terminates.
6183 * In this instance, IO.open returns the value of the block.
6184 *
6185 * See IO.new for a description of the +fd+, +mode+ and +opt+ parameters.
6186 */
6187
6188 static VALUE
6189 rb_io_s_open(int argc, VALUE *argv, VALUE klass)
6190 {
6191 VALUE io = rb_class_new_instance(argc, argv, klass);
6192
6193 if (rb_block_given_p()) {
6194 return rb_ensure(rb_yield, io, io_close, io);
6195 }
6196
6197 return io;
6198 }
6199
6200 /*
6201 * call-seq:
6202 * IO.sysopen(path, [mode, [perm]]) -> fixnum
6203 *
6204 * Opens the given path, returning the underlying file descriptor as a
6205 * <code>Fixnum</code>.
6206 *
6207 * IO.sysopen("testfile") #=> 3
6208 */
6209
6210 static VALUE
6211 rb_io_s_sysopen(int argc, VALUE *argv)
6212 {
6213 VALUE fname, vmode, vperm;
6214 VALUE intmode;
6215 int oflags, fd;
6216 mode_t perm;
6217
6218 rb_scan_args(argc, argv, "12", &fname, &vmode, &vperm);
6219 FilePathValue(fname);
6220
6221 if (NIL_P(vmode))
6222 oflags = O_RDONLY;
6223 else if (!NIL_P(intmode = rb_check_to_integer(vmode, "to_int")))
6224 oflags = NUM2INT(intmode);
6225 else {
6226 SafeStringValue(vmode);
6227 oflags = rb_io_modestr_oflags(StringValueCStr(vmode));
6228 }
6229 if (NIL_P(vperm)) perm = 0666;
6230 else perm = NUM2MODET(vperm);
6231
6232 RB_GC_GUARD(fname) = rb_str_new4(fname);
6233 fd = rb_sysopen(fname, oflags, perm);
6234 return INT2NUM(fd);
6235 }
6236
6237 static VALUE
6238 check_pipe_command(VALUE filename_or_command)
6239 {
6240 char *s = RSTRING_PTR(filename_or_command);
6241 long l = RSTRING_LEN(filename_or_command);
6242 char *e = s + l;
6243 int chlen;
6244
6245 if (rb_enc_ascget(s, e, &chlen, rb_enc_get(filename_or_command)) == '|') {
6246 VALUE cmd = rb_str_new(s+chlen, l-chlen);
6247 OBJ_INFECT(cmd, filename_or_command);
6248 return cmd;
6249 }
6250 return Qnil;
6251 }
6252
6253 /*
6254 * call-seq:
6255 * open(path [, mode [, perm]] [, opt]) -> io or nil
6256 * open(path [, mode [, perm]] [, opt]) {|io| block } -> obj
6257 *
6258 * Creates an IO object connected to the given stream, file, or subprocess.
6259 *
6260 * If +path+ does not start with a pipe character (<code>|</code>), treat it
6261 * as the name of a file to open using the specified mode (defaulting to
6262 * "r").
6263 *
6264 * The +mode+ is either a string or an integer. If it is an integer, it
6265 * must be bitwise-or of open(2) flags, such as File::RDWR or File::EXCL. If
6266 * it is a string, it is either "fmode", "fmode:ext_enc", or
6267 * "fmode:ext_enc:int_enc".
6268 *
6269 * See the documentation of IO.new for full documentation of the +mode+ string
6270 * directives.
6271 *
6272 * If a file is being created, its initial permissions may be set using the
6273 * +perm+ parameter. See File.new and the open(2) and chmod(2) man pages for
6274 * a description of permissions.
6275 *
6276 * If a block is specified, it will be invoked with the IO object as a
6277 * parameter, and the IO will be automatically closed when the block
6278 * terminates. The call returns the value of the block.
6279 *
6280 * If +path+ starts with a pipe character (<code>"|"</code>), a subprocess is
6281 * created, connected to the caller by a pair of pipes. The returned IO
6282 * object may be used to write to the standard input and read from the
6283 * standard output of this subprocess.
6284 *
6285 * If the command following the pipe is a single minus sign
6286 * (<code>"|-"</code>), Ruby forks, and this subprocess is connected to the
6287 * parent. If the command is not <code>"-"</code>, the subprocess runs the
6288 * command.
6289 *
6290 * When the subprocess is ruby (opened via <code>"|-"</code>), the +open+
6291 * call returns +nil+. If a block is associated with the open call, that
6292 * block will run twice --- once in the parent and once in the child.
6293 *
6294 * The block parameter will be an IO object in the parent and +nil+ in the
6295 * child. The parent's +IO+ object will be connected to the child's $stdin
6296 * and $stdout. The subprocess will be terminated at the end of the block.
6297 *
6298 * === Examples
6299 *
6300 * Reading from "testfile":
6301 *
6302 * open("testfile") do |f|
6303 * print f.gets
6304 * end
6305 *
6306 * Produces:
6307 *
6308 * This is line one
6309 *
6310 * Open a subprocess and read its output:
6311 *
6312 * cmd = open("|date")
6313 * print cmd.gets
6314 * cmd.close
6315 *
6316 * Produces:
6317 *
6318 * Wed Apr 9 08:56:31 CDT 2003
6319 *
6320 * Open a subprocess running the same Ruby program:
6321 *
6322 * f = open("|-", "w+")
6323 * if f == nil
6324 * puts "in Child"
6325 * exit
6326 * else
6327 * puts "Got: #{f.gets}"
6328 * end
6329 *
6330 * Produces:
6331 *
6332 * Got: in Child
6333 *
6334 * Open a subprocess using a block to receive the IO object:
6335 *
6336 * open "|-" do |f|
6337 * if f then
6338 * # parent process
6339 * puts "Got: #{f.gets}"
6340 * else
6341 * # child process
6342 * puts "in Child"
6343 * end
6344 * end
6345 *
6346 * Produces:
6347 *
6348 * Got: in Child
6349 */
6350
6351 static VALUE
6352 rb_f_open(int argc, VALUE *argv)
6353 {
6354 ID to_open = 0;
6355 int redirect = FALSE;
6356
6357 if (argc >= 1) {
6358 CONST_ID(to_open, "to_open");
6359 if (rb_respond_to(argv[0], to_open)) {
6360 redirect = TRUE;
6361 }
6362 else {
6363 VALUE tmp = argv[0];
6364 FilePathValue(tmp);
6365 if (NIL_P(tmp)) {
6366 redirect = TRUE;
6367 }
6368 else {
6369 VALUE cmd = check_pipe_command(tmp);
6370 if (!NIL_P(cmd)) {
6371 argv[0] = cmd;
6372 return rb_io_s_popen(argc, argv, rb_cIO);
6373 }
6374 }
6375 }
6376 }
6377 if (redirect) {
6378 VALUE io = rb_funcall2(argv[0], to_open, argc-1, argv+1);
6379
6380 if (rb_block_given_p()) {
6381 return rb_ensure(rb_yield, io, io_close, io);
6382 }
6383 return io;
6384 }
6385 return rb_io_s_open(argc, argv, rb_cFile);
6386 }
6387
6388 static VALUE
6389 rb_io_open(VALUE filename, VALUE vmode, VALUE vperm, VALUE opt)
6390 {
6391 VALUE cmd;
6392 int oflags, fmode;
6393 convconfig_t convconfig;
6394 mode_t perm;
6395
6396 rb_io_extract_modeenc(&vmode, &vperm, opt, &oflags, &fmode, &convconfig);
6397 perm = NIL_P(vperm) ? 0666 : NUM2MODET(vperm);
6398
6399 if (!NIL_P(cmd = check_pipe_command(filename))) {
6400 return pipe_open_s(cmd, rb_io_oflags_modestr(oflags), fmode, &convconfig);
6401 }
6402 else {
6403 return rb_file_open_generic(io_alloc(rb_cFile), filename,
6404 oflags, fmode, &convconfig, perm);
6405 }
6406 }
6407
6408 static VALUE
6409 rb_io_open_with_args(int argc, VALUE *argv)
6410 {
6411 VALUE io;
6412
6413 io = io_alloc(rb_cFile);
6414 rb_open_file(argc, argv, io);
6415 return io;
6416 }
6417
6418 static VALUE
6419 io_reopen(VALUE io, VALUE nfile)
6420 {
6421 rb_io_t *fptr, *orig;
6422 int fd, fd2;
6423 off_t pos = 0;
6424
6425 nfile = rb_io_get_io(nfile);
6426 if (rb_safe_level() >= 4 &&
6427 (!OBJ_UNTRUSTED(io) || !OBJ_UNTRUSTED(nfile))) {
6428 rb_raise(rb_eSecurityError, "Insecure: can't reopen");
6429 }
6430 GetOpenFile(io, fptr);
6431 GetOpenFile(nfile, orig);
6432
6433 if (fptr == orig) return io;
6434 if (IS_PREP_STDIO(fptr)) {
6435 if ((fptr->stdio_file == stdin && !(orig->mode & FMODE_READABLE)) ||
6436 (fptr->stdio_file == stdout && !(orig->mode & FMODE_WRITABLE)) ||
6437 (fptr->stdio_file == stderr && !(orig->mode & FMODE_WRITABLE))) {
6438 rb_raise(rb_eArgError,
6439 "%s can't change access mode from \"%s\" to \"%s\"",
6440 PREP_STDIO_NAME(fptr), rb_io_fmode_modestr(fptr->mode),
6441 rb_io_fmode_modestr(orig->mode));
6442 }
6443 }
6444 if (fptr->mode & FMODE_WRITABLE) {
6445 if (io_fflush(fptr) < 0)
6446 rb_sys_fail(0);
6447 }
6448 else {
6449 io_tell(fptr);
6450 }
6451 if (orig->mode & FMODE_READABLE) {
6452 pos = io_tell(orig);
6453 }
6454 if (orig->mode & FMODE_WRITABLE) {
6455 if (io_fflush(orig) < 0)
6456 rb_sys_fail(0);
6457 }
6458
6459 /* copy rb_io_t structure */
6460 fptr->mode = orig->mode | (fptr->mode & FMODE_PREP);
6461 fptr->pid = orig->pid;
6462 fptr->lineno = orig->lineno;
6463 if (RTEST(orig->pathv)) fptr->pathv = orig->pathv;
6464 else if (!IS_PREP_STDIO(fptr)) fptr->pathv = Qnil;
6465 fptr->finalize = orig->finalize;
6466 #if defined (__CYGWIN__) || !defined(HAVE_FORK)
6467 if (fptr->finalize == pipe_finalize)
6468 pipe_add_fptr(fptr);
6469 #endif
6470
6471 fd = fptr->fd;
6472 fd2 = orig->fd;
6473 if (fd != fd2) {
6474 if (IS_PREP_STDIO(fptr) || fd <= 2 || !fptr->stdio_file) {
6475 /* need to keep FILE objects of stdin, stdout and stderr */
6476 if (rb_cloexec_dup2(fd2, fd) < 0)
6477 rb_sys_fail_path(orig->pathv);
6478 rb_update_max_fd(fd);
6479 }
6480 else {
6481 fclose(fptr->stdio_file);
6482 fptr->stdio_file = 0;
6483 fptr->fd = -1;
6484 if (rb_cloexec_dup2(fd2, fd) < 0)
6485 rb_sys_fail_path(orig->pathv);
6486 rb_update_max_fd(fd);
6487 fptr->fd = fd;
6488 }
6489 rb_thread_fd_close(fd);
6490 if ((orig->mode & FMODE_READABLE) && pos >= 0) {
6491 if (io_seek(fptr, pos, SEEK_SET) < 0 && errno) {
6492 rb_sys_fail_path(fptr->pathv);
6493 }
6494 if (io_seek(orig, pos, SEEK_SET) < 0 && errno) {
6495 rb_sys_fail_path(orig->pathv);
6496 }
6497 }
6498 }
6499
6500 if (fptr->mode & FMODE_BINMODE) {
6501 rb_io_binmode(io);
6502 }
6503
6504 RBASIC(io)->klass = rb_obj_class(nfile);
6505 return io;
6506 }
6507
6508 /*
6509 * call-seq:
6510 * ios.reopen(other_IO) -> ios
6511 * ios.reopen(path, mode_str) -> ios
6512 *
6513 * Reassociates <em>ios</em> with the I/O stream given in
6514 * <i>other_IO</i> or to a new stream opened on <i>path</i>. This may
6515 * dynamically change the actual class of this stream.
6516 *
6517 * f1 = File.new("testfile")
6518 * f2 = File.new("testfile")
6519 * f2.readlines[0] #=> "This is line one\n"
6520 * f2.reopen(f1) #=> #<File:testfile>
6521 * f2.readlines[0] #=> "This is line one\n"
6522 */
6523
6524 static VALUE
6525 rb_io_reopen(int argc, VALUE *argv, VALUE file)
6526 {
6527 VALUE fname, nmode, opt;
6528 int oflags;
6529 rb_io_t *fptr;
6530
6531 rb_secure(4);
6532 if (rb_scan_args(argc, argv, "11:", &fname, &nmode, &opt) == 1) {
6533 VALUE tmp = rb_io_check_io(fname);
6534 if (!NIL_P(tmp)) {
6535 return io_reopen(file, tmp);
6536 }
6537 }
6538
6539 FilePathValue(fname);
6540 rb_io_taint_check(file);
6541 fptr = RFILE(file)->fptr;
6542 if (!fptr) {
6543 fptr = RFILE(file)->fptr = ALLOC(rb_io_t);
6544 MEMZERO(fptr, rb_io_t, 1);
6545 }
6546
6547 if (!NIL_P(nmode) || !NIL_P(opt)) {
6548 int fmode;
6549 convconfig_t convconfig;
6550
6551 rb_io_extract_modeenc(&nmode, 0, opt, &oflags, &fmode, &convconfig);
6552 if (IS_PREP_STDIO(fptr) &&
6553 ((fptr->mode & FMODE_READWRITE) & (fmode & FMODE_READWRITE)) !=
6554 (fptr->mode & FMODE_READWRITE)) {
6555 rb_raise(rb_eArgError,
6556 "%s can't change access mode from \"%s\" to \"%s\"",
6557 PREP_STDIO_NAME(fptr), rb_io_fmode_modestr(fptr->mode),
6558 rb_io_fmode_modestr(fmode));
6559 }
6560 fptr->mode = fmode;
6561 fptr->encs = convconfig;
6562 }
6563 else {
6564 oflags = rb_io_fmode_oflags(fptr->mode);
6565 }
6566
6567 fptr->pathv = rb_str_new_frozen(fname);
6568 if (fptr->fd < 0) {
6569 fptr->fd = rb_sysopen(fptr->pathv, oflags, 0666);
6570 fptr->stdio_file = 0;
6571 return file;
6572 }
6573
6574 if (fptr->mode & FMODE_WRITABLE) {
6575 if (io_fflush(fptr) < 0)
6576 rb_sys_fail(0);
6577 }
6578 fptr->rbuf.off = fptr->rbuf.len = 0;
6579
6580 if (fptr->stdio_file) {
6581 if (freopen(RSTRING_PTR(fptr->pathv), rb_io_oflags_modestr(oflags), fptr->stdio_file) == 0) {
6582 rb_sys_fail_path(fptr->pathv);
6583 }
6584 fptr->fd = fileno(fptr->stdio_file);
6585 rb_fd_fix_cloexec(fptr->fd);
6586 #ifdef USE_SETVBUF
6587 if (setvbuf(fptr->stdio_file, NULL, _IOFBF, 0) != 0)
6588 rb_warn("setvbuf() can't be honoured for %s", RSTRING_PTR(fptr->pathv));
6589 #endif
6590 if (fptr->stdio_file == stderr) {
6591 if (setvbuf(fptr->stdio_file, NULL, _IONBF, BUFSIZ) != 0)
6592 rb_warn("setvbuf() can't be honoured for %s", RSTRING_PTR(fptr->pathv));
6593 }
6594 else if (fptr->stdio_file == stdout && isatty(fptr->fd)) {
6595 if (setvbuf(fptr->stdio_file, NULL, _IOLBF, BUFSIZ) != 0)
6596 rb_warn("setvbuf() can't be honoured for %s", RSTRING_PTR(fptr->pathv));
6597 }
6598 }
6599 else {
6600 if (close(fptr->fd) < 0)
6601 rb_sys_fail_path(fptr->pathv);
6602 fptr->fd = -1;
6603 fptr->fd = rb_sysopen(fptr->pathv, oflags, 0666);
6604 }
6605
6606 return file;
6607 }
6608
6609 /* :nodoc: */
6610 static VALUE
6611 rb_io_init_copy(VALUE dest, VALUE io)
6612 {
6613 rb_io_t *fptr, *orig;
6614 int fd;
6615 VALUE write_io;
6616 off_t pos;
6617
6618 io = rb_io_get_io(io);
6619 if (!OBJ_INIT_COPY(dest, io)) return dest;
6620 GetOpenFile(io, orig);
6621 MakeOpenFile(dest, fptr);
6622
6623 rb_io_flush(io);
6624
6625 /* copy rb_io_t structure */
6626 fptr->mode = orig->mode & ~FMODE_PREP;
6627 fptr->encs = orig->encs;
6628 fptr->pid = orig->pid;
6629 fptr->lineno = orig->lineno;
6630 if (!NIL_P(orig->pathv)) fptr->pathv = orig->pathv;
6631 fptr->finalize = orig->finalize;
6632 #if defined (__CYGWIN__) || !defined(HAVE_FORK)
6633 if (fptr->finalize == pipe_finalize)
6634 pipe_add_fptr(fptr);
6635 #endif
6636
6637 fd = ruby_dup(orig->fd);
6638 fptr->fd = fd;
6639 pos = io_tell(orig);
6640 if (0 <= pos)
6641 io_seek(fptr, pos, SEEK_SET);
6642 if (fptr->mode & FMODE_BINMODE) {
6643 rb_io_binmode(dest);
6644 }
6645
6646 write_io = GetWriteIO(io);
6647 if (io != write_io) {
6648 write_io = rb_obj_dup(write_io);
6649 fptr->tied_io_for_writing = write_io;
6650 rb_ivar_set(dest, rb_intern("@tied_io_for_writing"), write_io);
6651 }
6652
6653 return dest;
6654 }
6655
6656 /*
6657 * call-seq:
6658 * ios.printf(format_string [, obj, ...]) -> nil
6659 *
6660 * Formats and writes to <em>ios</em>, converting parameters under
6661 * control of the format string. See <code>Kernel#sprintf</code>
6662 * for details.
6663 */
6664
6665 VALUE
6666 rb_io_printf(int argc, VALUE *argv, VALUE out)
6667 {
6668 rb_io_write(out, rb_f_sprintf(argc, argv));
6669 return Qnil;
6670 }
6671
6672 /*
6673 * call-seq:
6674 * printf(io, string [, obj ... ]) -> nil
6675 * printf(string [, obj ... ]) -> nil
6676 *
6677 * Equivalent to:
6678 * io.write(sprintf(string, obj, ...)
6679 * or
6680 * $stdout.write(sprintf(string, obj, ...)
6681 */
6682
6683 static VALUE
6684 rb_f_printf(int argc, VALUE *argv)
6685 {
6686 VALUE out;
6687
6688 if (argc == 0) return Qnil;
6689 if (RB_TYPE_P(argv[0], T_STRING)) {
6690 out = rb_stdout;
6691 }
6692 else {
6693 out = argv[0];
6694 argv++;
6695 argc--;
6696 }
6697 rb_io_write(out, rb_f_sprintf(argc, argv));
6698
6699 return Qnil;
6700 }
6701
6702 /*
6703 * call-seq:
6704 * ios.print() -> nil
6705 * ios.print(obj, ...) -> nil
6706 *
6707 * Writes the given object(s) to <em>ios</em>. The stream must be
6708 * opened for writing. If the output field separator (<code>$,</code>)
6709 * is not <code>nil</code>, it will be inserted between each object.
6710 * If the output record separator (<code>$\</code>)
6711 * is not <code>nil</code>, it will be appended to the output. If no
6712 * arguments are given, prints <code>$_</code>. Objects that aren't
6713 * strings will be converted by calling their <code>to_s</code> method.
6714 * With no argument, prints the contents of the variable <code>$_</code>.
6715 * Returns <code>nil</code>.
6716 *
6717 * $stdout.print("This is ", 100, " percent.\n")
6718 *
6719 * <em>produces:</em>
6720 *
6721 * This is 100 percent.
6722 */
6723
6724 VALUE
6725 rb_io_print(int argc, VALUE *argv, VALUE out)
6726 {
6727 int i;
6728 VALUE line;
6729
6730 /* if no argument given, print `$_' */
6731 if (argc == 0) {
6732 argc = 1;
6733 line = rb_lastline_get();
6734 argv = &line;
6735 }
6736 for (i=0; i<argc; i++) {
6737 if (!NIL_P(rb_output_fs) && i>0) {
6738 rb_io_write(out, rb_output_fs);
6739 }
6740 rb_io_write(out, argv[i]);
6741 }
6742 if (argc > 0 && !NIL_P(rb_output_rs)) {
6743 rb_io_write(out, rb_output_rs);
6744 }
6745
6746 return Qnil;
6747 }
6748
6749 /*
6750 * call-seq:
6751 * print(obj, ...) -> nil
6752 *
6753 * Prints each object in turn to <code>$stdout</code>. If the output
6754 * field separator (<code>$,</code>) is not +nil+, its
6755 * contents will appear between each field. If the output record
6756 * separator (<code>$\</code>) is not +nil+, it will be
6757 * appended to the output. If no arguments are given, prints
6758 * <code>$_</code>. Objects that aren't strings will be converted by
6759 * calling their <code>to_s</code> method.
6760 *
6761 * print "cat", [1,2,3], 99, "\n"
6762 * $, = ", "
6763 * $\ = "\n"
6764 * print "cat", [1,2,3], 99
6765 *
6766 * <em>produces:</em>
6767 *
6768 * cat12399
6769 * cat, 1, 2, 3, 99
6770 */
6771
6772 static VALUE
6773 rb_f_print(int argc, VALUE *argv)
6774 {
6775 rb_io_print(argc, argv, rb_stdout);
6776 return Qnil;
6777 }
6778
6779 /*
6780 * call-seq:
6781 * ios.putc(obj) -> obj
6782 *
6783 * If <i>obj</i> is <code>Numeric</code>, write the character whose code is
6784 * the least-significant byte of <i>obj</i>, otherwise write the first byte
6785 * of the string representation of <i>obj</i> to <em>ios</em>. Note: This
6786 * method is not safe for use with multi-byte characters as it will truncate
6787 * them.
6788 *
6789 * $stdout.putc "A"
6790 * $stdout.putc 65
6791 *
6792 * <em>produces:</em>
6793 *
6794 * AA
6795 */
6796
6797 static VALUE
6798 rb_io_putc(VALUE io, VALUE ch)
6799 {
6800 VALUE str;
6801 if (RB_TYPE_P(ch, T_STRING)) {
6802 str = rb_str_substr(ch, 0, 1);
6803 }
6804 else {
6805 char c = NUM2CHR(ch);
6806 str = rb_str_new(&c, 1);
6807 }
6808 rb_io_write(io, str);
6809 return ch;
6810 }
6811
6812 /*
6813 * call-seq:
6814 * putc(int) -> int
6815 *
6816 * Equivalent to:
6817 *
6818 * $stdout.putc(int)
6819 *
6820 * Refer to the documentation for IO#putc for important information regarding
6821 * multi-byte characters.
6822 */
6823
6824 static VALUE
6825 rb_f_putc(VALUE recv, VALUE ch)
6826 {
6827 if (recv == rb_stdout) {
6828 return rb_io_putc(recv, ch);
6829 }
6830 return rb_funcall2(rb_stdout, rb_intern("putc"), 1, &ch);
6831 }
6832
6833
6834 static int
6835 str_end_with_asciichar(VALUE str, int c)
6836 {
6837 long len = RSTRING_LEN(str);
6838 const char *ptr = RSTRING_PTR(str);
6839 rb_encoding *enc = rb_enc_from_index(ENCODING_GET(str));
6840 int n;
6841
6842 if (len == 0) return 0;
6843 if ((n = rb_enc_mbminlen(enc)) == 1) {
6844 return ptr[len - 1] == c;
6845 }
6846 return rb_enc_ascget(ptr + ((len - 1) / n) * n, ptr + len, &n, enc) == c;
6847 }
6848
6849 static VALUE
6850 io_puts_ary(VALUE ary, VALUE out, int recur)
6851 {
6852 VALUE tmp;
6853 long i;
6854
6855 if (recur) {
6856 tmp = rb_str_new2("[...]");
6857 rb_io_puts(1, &tmp, out);
6858 return Qtrue;
6859 }
6860 ary = rb_check_array_type(ary);
6861 if (NIL_P(ary)) return Qfalse;
6862 for (i=0; i<RARRAY_LEN(ary); i++) {
6863 tmp = RARRAY_PTR(ary)[i];
6864 rb_io_puts(1, &tmp, out);
6865 }
6866 return Qtrue;
6867 }
6868
6869 /*
6870 * call-seq:
6871 * ios.puts(obj, ...) -> nil
6872 *
6873 * Writes the given objects to <em>ios</em> as with
6874 * <code>IO#print</code>. Writes a record separator (typically a
6875 * newline) after any that do not already end with a newline sequence.
6876 * If called with an array argument, writes each element on a new line.
6877 * If called without arguments, outputs a single record separator.
6878 *
6879 * $stdout.puts("this", "is", "a", "test")
6880 *
6881 * <em>produces:</em>
6882 *
6883 * this
6884 * is
6885 * a
6886 * test
6887 */
6888
6889 VALUE
6890 rb_io_puts(int argc, VALUE *argv, VALUE out)
6891 {
6892 int i;
6893 VALUE line;
6894
6895 /* if no argument given, print newline. */
6896 if (argc == 0) {
6897 rb_io_write(out, rb_default_rs);
6898 return Qnil;
6899 }
6900 for (i=0; i<argc; i++) {
6901 if (RB_TYPE_P(argv[i], T_STRING)) {
6902 line = argv[i];
6903 goto string;
6904 }
6905 if (rb_exec_recursive(io_puts_ary, argv[i], out)) {
6906 continue;
6907 }
6908 line = rb_obj_as_string(argv[i]);
6909 string:
6910 rb_io_write(out, line);
6911 if (RSTRING_LEN(line) == 0 ||
6912 !str_end_with_asciichar(line, '\n')) {
6913 rb_io_write(out, rb_default_rs);
6914 }
6915 }
6916
6917 return Qnil;
6918 }
6919
6920 /*
6921 * call-seq:
6922 * puts(obj, ...) -> nil
6923 *
6924 * Equivalent to
6925 *
6926 * $stdout.puts(obj, ...)
6927 */
6928
6929 static VALUE
6930 rb_f_puts(int argc, VALUE *argv, VALUE recv)
6931 {
6932 if (recv == rb_stdout) {
6933 return rb_io_puts(argc, argv, recv);
6934 }
6935 return rb_funcall2(rb_stdout, rb_intern("puts"), argc, argv);
6936 }
6937
6938 void
6939 rb_p(VALUE obj) /* for debug print within C code */
6940 {
6941 VALUE str = rb_obj_as_string(rb_inspect(obj));
6942 if (RB_TYPE_P(rb_stdout, T_FILE) &&
6943 rb_method_basic_definition_p(CLASS_OF(rb_stdout), id_write)) {
6944 io_write(rb_stdout, str, 1);
6945 io_write(rb_stdout, rb_default_rs, 0);
6946 }
6947 else {
6948 rb_io_write(rb_stdout, str);
6949 rb_io_write(rb_stdout, rb_default_rs);
6950 }
6951 }
6952
6953 struct rb_f_p_arg {
6954 int argc;
6955 VALUE *argv;
6956 };
6957
6958 static VALUE
6959 rb_f_p_internal(VALUE arg)
6960 {
6961 struct rb_f_p_arg *arg1 = (struct rb_f_p_arg*)arg;
6962 int argc = arg1->argc;
6963 VALUE *argv = arg1->argv;
6964 int i;
6965 VALUE ret = Qnil;
6966
6967 for (i=0; i<argc; i++) {
6968 rb_p(argv[i]);
6969 }
6970 if (argc == 1) {
6971 ret = argv[0];
6972 }
6973 else if (argc > 1) {
6974 ret = rb_ary_new4(argc, argv);
6975 }
6976 if (RB_TYPE_P(rb_stdout, T_FILE)) {
6977 rb_io_flush(rb_stdout);
6978 }
6979 return ret;
6980 }
6981
6982 /*
6983 * call-seq:
6984 * p(obj) -> obj
6985 * p(obj1, obj2, ...) -> [obj, ...]
6986 * p() -> nil
6987 *
6988 * For each object, directly writes _obj_.+inspect+ followed by a
6989 * newline to the program's standard output.
6990 *
6991 * S = Struct.new(:name, :state)
6992 * s = S['dave', 'TX']
6993 * p s
6994 *
6995 * <em>produces:</em>
6996 *
6997 * #<S name="dave", state="TX">
6998 */
6999
7000 static VALUE
7001 rb_f_p(int argc, VALUE *argv, VALUE self)
7002 {
7003 struct rb_f_p_arg arg;
7004 arg.argc = argc;
7005 arg.argv = argv;
7006
7007 return rb_uninterruptible(rb_f_p_internal, (VALUE)&arg);
7008 }
7009
7010 /*
7011 * call-seq:
7012 * obj.display(port=$>) -> nil
7013 *
7014 * Prints <i>obj</i> on the given port (default <code>$></code>).
7015 * Equivalent to:
7016 *
7017 * def display(port=$>)
7018 * port.write self
7019 * end
7020 *
7021 * For example:
7022 *
7023 * 1.display
7024 * "cat".display
7025 * [ 4, 5, 6 ].display
7026 * puts
7027 *
7028 * <em>produces:</em>
7029 *
7030 * 1cat456
7031 */
7032
7033 static VALUE
7034 rb_obj_display(int argc, VALUE *argv, VALUE self)
7035 {
7036 VALUE out;
7037
7038 if (argc == 0) {
7039 out = rb_stdout;
7040 }
7041 else {
7042 rb_scan_args(argc, argv, "01", &out);
7043 }
7044 rb_io_write(out, self);
7045
7046 return Qnil;
7047 }
7048
7049 void
7050 rb_write_error2(const char *mesg, long len)
7051 {
7052 if (rb_stderr == orig_stderr || RFILE(orig_stderr)->fptr->fd < 0) {
7053 if (fwrite(mesg, sizeof(char), (size_t)len, stderr) < (size_t)len) {
7054 /* failed to write to stderr, what can we do? */
7055 return;
7056 }
7057 }
7058 else {
7059 rb_io_write(rb_stderr, rb_str_new(mesg, len));
7060 }
7061 }
7062
7063 void
7064 rb_write_error(const char *mesg)
7065 {
7066 rb_write_error2(mesg, strlen(mesg));
7067 }
7068
7069 void
7070 rb_write_error_str(VALUE mesg)
7071 {
7072 /* a stopgap measure for the time being */
7073 if (rb_stderr == orig_stderr || RFILE(orig_stderr)->fptr->fd < 0) {
7074 size_t len = (size_t)RSTRING_LEN(mesg);
7075 if (fwrite(RSTRING_PTR(mesg), sizeof(char), len, stderr) < len) {
7076 RB_GC_GUARD(mesg);
7077 return;
7078 }
7079 }
7080 else {
7081 /* may unlock GVL, and */
7082 rb_io_write(rb_stderr, mesg);
7083 }
7084 }
7085
7086 static void
7087 must_respond_to(ID mid, VALUE val, ID id)
7088 {
7089 if (!rb_respond_to(val, mid)) {
7090 rb_raise(rb_eTypeError, "%s must have %s method, %s given",
7091 rb_id2name(id), rb_id2name(mid),
7092 rb_obj_classname(val));
7093 }
7094 }
7095
7096 static void
7097 stdout_setter(VALUE val, ID id, VALUE *variable)
7098 {
7099 must_respond_to(id_write, val, id);
7100 *variable = val;
7101 }
7102
7103 static VALUE
7104 prep_io(int fd, int fmode, VALUE klass, const char *path)
7105 {
7106 rb_io_t *fp;
7107 VALUE io = io_alloc(klass);
7108
7109 MakeOpenFile(io, fp);
7110 fp->fd = fd;
7111 #ifdef __CYGWIN__
7112 if (!isatty(fd)) {
7113 fmode |= FMODE_BINMODE;
7114 setmode(fd, O_BINARY);
7115 }
7116 #endif
7117 fp->mode = fmode;
7118 io_check_tty(fp);
7119 if (path) fp->pathv = rb_obj_freeze(rb_str_new_cstr(path));
7120 rb_update_max_fd(fd);
7121
7122 return io;
7123 }
7124
7125 VALUE
7126 rb_io_fdopen(int fd, int oflags, const char *path)
7127 {
7128 VALUE klass = rb_cIO;
7129
7130 if (path && strcmp(path, "-")) klass = rb_cFile;
7131 return prep_io(fd, rb_io_oflags_fmode(oflags), klass, path);
7132 }
7133
7134 static VALUE
7135 prep_stdio(FILE *f, int fmode, VALUE klass, const char *path)
7136 {
7137 rb_io_t *fptr;
7138 VALUE io = prep_io(fileno(f), fmode|FMODE_PREP|DEFAULT_TEXTMODE, klass, path);
7139
7140 GetOpenFile(io, fptr);
7141 fptr->encs.ecflags |= ECONV_DEFAULT_NEWLINE_DECORATOR;
7142 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
7143 fptr->encs.ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
7144 if (fmode & FMODE_READABLE) {
7145 fptr->encs.ecflags |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;
7146 }
7147 #endif
7148 fptr->stdio_file = f;
7149
7150 return io;
7151 }
7152
7153 FILE *
7154 rb_io_stdio_file(rb_io_t *fptr)
7155 {
7156 if (!fptr->stdio_file) {
7157 int oflags = rb_io_fmode_oflags(fptr->mode);
7158 fptr->stdio_file = rb_fdopen(fptr->fd, rb_io_oflags_modestr(oflags));
7159 }
7160 return fptr->stdio_file;
7161 }
7162
7163 /*
7164 * call-seq:
7165 * IO.new(fd [, mode] [, opt]) -> io
7166 *
7167 * Returns a new IO object (a stream) for the given integer file descriptor
7168 * +fd+ and +mode+ string. +opt+ may be used to specify parts of +mode+ in a
7169 * more readable fashion. See also IO.sysopen and IO.for_fd.
7170 *
7171 * IO.new is called by various File and IO opening methods such as IO::open,
7172 * Kernel#open, and File::open.
7173 *
7174 * === Open Mode
7175 *
7176 * When +mode+ is an integer it must be combination of the modes defined in
7177 * File::Constants (+File::RDONLY+, +File::WRONLY | File::CREAT+). See the
7178 * open(2) man page for more information.
7179 *
7180 * When +mode+ is a string it must be in one of the following forms:
7181 *
7182 * fmode
7183 * fmode ":" ext_enc
7184 * fmode ":" ext_enc ":" int_enc
7185 * fmode ":" "BOM|UTF-*"
7186 *
7187 * +fmode+ is an IO open mode string, +ext_enc+ is the external encoding for
7188 * the IO and +int_enc+ is the internal encoding.
7189 *
7190 * ==== IO Open Mode
7191 *
7192 * Ruby allows the following open modes:
7193 *
7194 * "r" Read-only, starts at beginning of file (default mode).
7195 *
7196 * "r+" Read-write, starts at beginning of file.
7197 *
7198 * "w" Write-only, truncates existing file
7199 * to zero length or creates a new file for writing.
7200 *
7201 * "w+" Read-write, truncates existing file to zero length
7202 * or creates a new file for reading and writing.
7203 *
7204 * "a" Write-only, starts at end of file if file exists,
7205 * otherwise creates a new file for writing.
7206 *
7207 * "a+" Read-write, starts at end of file if file exists,
7208 * otherwise creates a new file for reading and
7209 * writing.
7210 *
7211 * The following modes must be used separately, and along with one or more of
7212 * the modes seen above.
7213 *
7214 * "b" Binary file mode
7215 * Suppresses EOL <-> CRLF conversion on Windows. And
7216 * sets external encoding to ASCII-8BIT unless explicitly
7217 * specified.
7218 *
7219 * "t" Text file mode
7220 *
7221 * When the open mode of original IO is read only, the mode cannot be
7222 * changed to be writable. Similarly, the open mode cannot be changed from
7223 * write only to readable.
7224 *
7225 * When such a change is attempted the error is raised in different locations
7226 * according to the platform.
7227 *
7228 * === IO Encoding
7229 *
7230 * When +ext_enc+ is specified, strings read will be tagged by the encoding
7231 * when reading, and strings output will be converted to the specified
7232 * encoding when writing.
7233 *
7234 * When +ext_enc+ and +int_enc+ are specified read strings will be converted
7235 * from +ext_enc+ to +int_enc+ upon input, and written strings will be
7236 * converted from +int_enc+ to +ext_enc+ upon output. See Encoding for
7237 * further details of transcoding on input and output.
7238 *
7239 * If "BOM|UTF-8", "BOM|UTF-16LE" or "BOM|UTF16-BE" are used, ruby checks for
7240 * a Unicode BOM in the input document to help determine the encoding. For
7241 * UTF-16 encodings the file open mode must be binary. When present, the BOM
7242 * is stripped and the external encoding from the BOM is used. When the BOM
7243 * is missing the given Unicode encoding is used as +ext_enc+. (The BOM-set
7244 * encoding option is case insensitive, so "bom|utf-8" is also valid.)
7245 *
7246 * === Options
7247 *
7248 * +opt+ can be used instead of +mode+ for improved readability. The
7249 * following keys are supported:
7250 *
7251 * :mode ::
7252 * Same as +mode+ parameter
7253 *
7254 * :\external_encoding ::
7255 * External encoding for the IO. "-" is a synonym for the default external
7256 * encoding.
7257 *
7258 * :\internal_encoding ::
7259 * Internal encoding for the IO. "-" is a synonym for the default internal
7260 * encoding.
7261 *
7262 * If the value is nil no conversion occurs.
7263 *
7264 * :encoding ::
7265 * Specifies external and internal encodings as "extern:intern".
7266 *
7267 * :textmode ::
7268 * If the value is truth value, same as "t" in argument +mode+.
7269 *
7270 * :binmode ::
7271 * If the value is truth value, same as "b" in argument +mode+.
7272 *
7273 * :autoclose ::
7274 * If the value is +false+, the +fd+ will be kept open after this IO
7275 * instance gets finalized.
7276 *
7277 * Also, +opt+ can have same keys in String#encode for controlling conversion
7278 * between the external encoding and the internal encoding.
7279 *
7280 * === Example 1
7281 *
7282 * fd = IO.sysopen("/dev/tty", "w")
7283 * a = IO.new(fd,"w")
7284 * $stderr.puts "Hello"
7285 * a.puts "World"
7286 *
7287 * Produces:
7288 *
7289 * Hello
7290 * World
7291 *
7292 * === Example 2
7293 *
7294 * require 'fcntl'
7295 *
7296 * fd = STDERR.fcntl(Fcntl::F_DUPFD)
7297 * io = IO.new(fd, mode: 'w:UTF-16LE', cr_newline: true)
7298 * io.puts "Hello, World!"
7299 *
7300 * fd = STDERR.fcntl(Fcntl::F_DUPFD)
7301 * io = IO.new(fd, mode: 'w', cr_newline: true,
7302 * external_encoding: Encoding::UTF_16LE)
7303 * io.puts "Hello, World!"
7304 *
7305 * Both of above print "Hello, World!" in UTF-16LE to standard error output
7306 * with converting EOL generated by <code>puts</code> to CR.
7307 */
7308
7309 static VALUE
7310 rb_io_initialize(int argc, VALUE *argv, VALUE io)
7311 {
7312 VALUE fnum, vmode;
7313 rb_io_t *fp;
7314 int fd, fmode, oflags = O_RDONLY;
7315 convconfig_t convconfig;
7316 VALUE opt;
7317 #if defined(HAVE_FCNTL) && defined(F_GETFL)
7318 int ofmode;
7319 #else
7320 struct stat st;
7321 #endif
7322
7323 rb_secure(4);
7324
7325 argc = rb_scan_args(argc, argv, "11:", &fnum, &vmode, &opt);
7326 rb_io_extract_modeenc(&vmode, 0, opt, &oflags, &fmode, &convconfig);
7327
7328 fd = NUM2INT(fnum);
7329 if (rb_reserved_fd_p(fd)) {
7330 rb_raise(rb_eArgError, "The given fd is not accessible because RubyVM reserves it");
7331 }
7332 #if defined(HAVE_FCNTL) && defined(F_GETFL)
7333 oflags = fcntl(fd, F_GETFL);
7334 if (oflags == -1) rb_sys_fail(0);
7335 #else
7336 if (fstat(fd, &st) == -1) rb_sys_fail(0);
7337 #endif
7338 rb_update_max_fd(fd);
7339 #if defined(HAVE_FCNTL) && defined(F_GETFL)
7340 ofmode = rb_io_oflags_fmode(oflags);
7341 if (NIL_P(vmode)) {
7342 fmode = ofmode;
7343 }
7344 else if ((~ofmode & fmode) & FMODE_READWRITE) {
7345 VALUE error = INT2FIX(EINVAL);
7346 rb_exc_raise(rb_class_new_instance(1, &error, rb_eSystemCallError));
7347 }
7348 #endif
7349 if (!NIL_P(opt) && rb_hash_aref(opt, sym_autoclose) == Qfalse) {
7350 fmode |= FMODE_PREP;
7351 }
7352 MakeOpenFile(io, fp);
7353 fp->fd = fd;
7354 fp->mode = fmode;
7355 fp->encs = convconfig;
7356 clear_codeconv(fp);
7357 io_check_tty(fp);
7358 if (fileno(stdin) == fd)
7359 fp->stdio_file = stdin;
7360 else if (fileno(stdout) == fd)
7361 fp->stdio_file = stdout;
7362 else if (fileno(stderr) == fd)
7363 fp->stdio_file = stderr;
7364
7365 if (fmode & FMODE_SETENC_BY_BOM) io_set_encoding_by_bom(io);
7366 return io;
7367 }
7368
7369 /*
7370 * call-seq:
7371 * File.new(filename, mode="r" [, opt]) -> file
7372 * File.new(filename [, mode [, perm]] [, opt]) -> file
7373 *
7374 * Opens the file named by +filename+ according to the given +mode+ and
7375 * returns a new File object.
7376 *
7377 * See IO.new for a description of +mode+ and +opt+.
7378 *
7379 * If a file is being created, permission bits may be given in +perm+. These
7380 * mode and permission bits are platform dependent; on Unix systems, see
7381 * open(2) and chmod(2) man pages for details.
7382 *
7383 * === Examples
7384 *
7385 * f = File.new("testfile", "r")
7386 * f = File.new("newfile", "w+")
7387 * f = File.new("newfile", File::CREAT|File::TRUNC|File::RDWR, 0644)
7388 */
7389
7390 static VALUE
7391 rb_file_initialize(int argc, VALUE *argv, VALUE io)
7392 {
7393 if (RFILE(io)->fptr) {
7394 rb_raise(rb_eRuntimeError, "reinitializing File");
7395 }
7396 if (0 < argc && argc < 3) {
7397 VALUE fd = rb_check_convert_type(argv[0], T_FIXNUM, "Fixnum", "to_int");
7398
7399 if (!NIL_P(fd)) {
7400 argv[0] = fd;
7401 return rb_io_initialize(argc, argv, io);
7402 }
7403 }
7404 rb_open_file(argc, argv, io);
7405
7406 return io;
7407 }
7408
7409 /* :nodoc: */
7410 static VALUE
7411 rb_io_s_new(int argc, VALUE *argv, VALUE klass)
7412 {
7413 if (rb_block_given_p()) {
7414 const char *cname = rb_class2name(klass);
7415
7416 rb_warn("%s::new() does not take block; use %s::open() instead",
7417 cname, cname);
7418 }
7419 return rb_class_new_instance(argc, argv, klass);
7420 }
7421
7422
7423 /*
7424 * call-seq:
7425 * IO.for_fd(fd, mode [, opt]) -> io
7426 *
7427 * Synonym for <code>IO.new</code>.
7428 *
7429 */
7430
7431 static VALUE
7432 rb_io_s_for_fd(int argc, VALUE *argv, VALUE klass)
7433 {
7434 VALUE io = rb_obj_alloc(klass);
7435 rb_io_initialize(argc, argv, io);
7436 return io;
7437 }
7438
7439 /*
7440 * call-seq:
7441 * ios.autoclose? -> true or false
7442 *
7443 * Returns +true+ if the underlying file descriptor of _ios_ will be
7444 * closed automatically at its finalization, otherwise +false+.
7445 */
7446
7447 static VALUE
7448 rb_io_autoclose_p(VALUE io)
7449 {
7450 rb_io_t *fptr;
7451 rb_secure(4);
7452 GetOpenFile(io, fptr);
7453 return (fptr->mode & FMODE_PREP) ? Qfalse : Qtrue;
7454 }
7455
7456 /*
7457 * call-seq:
7458 * io.autoclose = bool -> true or false
7459 *
7460 * Sets auto-close flag.
7461 *
7462 * f = open("/dev/null")
7463 * IO.for_fd(f.fileno)
7464 * # ...
7465 * f.gets # may cause IOError
7466 *
7467 * f = open("/dev/null")
7468 * IO.for_fd(f.fileno).autoclose = true
7469 * # ...
7470 * f.gets # won't cause IOError
7471 */
7472
7473 static VALUE
7474 rb_io_set_autoclose(VALUE io, VALUE autoclose)
7475 {
7476 rb_io_t *fptr;
7477 rb_secure(4);
7478 GetOpenFile(io, fptr);
7479 if (!RTEST(autoclose))
7480 fptr->mode |= FMODE_PREP;
7481 else
7482 fptr->mode &= ~FMODE_PREP;
7483 return io;
7484 }
7485
7486 static void
7487 argf_mark(void *ptr)
7488 {
7489 struct argf *p = ptr;
7490 rb_gc_mark(p->filename);
7491 rb_gc_mark(p->current_file);
7492 rb_gc_mark(p->argv);
7493 rb_gc_mark(p->encs.ecopts);
7494 }
7495
7496 static void
7497 argf_free(void *ptr)
7498 {
7499 struct argf *p = ptr;
7500 xfree(p->inplace);
7501 xfree(p);
7502 }
7503
7504 static size_t
7505 argf_memsize(const void *ptr)
7506 {
7507 const struct argf *p = ptr;
7508 size_t size = sizeof(*p);
7509 if (!ptr) return 0;
7510 if (p->inplace) size += strlen(p->inplace) + 1;
7511 return size;
7512 }
7513
7514 static const rb_data_type_t argf_type = {
7515 "ARGF",
7516 {argf_mark, argf_free, argf_memsize},
7517 };
7518
7519 static inline void
7520 argf_init(struct argf *p, VALUE v)
7521 {
7522 p->filename = Qnil;
7523 p->current_file = Qnil;
7524 p->lineno = 0;
7525 p->argv = v;
7526 }
7527
7528 static VALUE
7529 argf_alloc(VALUE klass)
7530 {
7531 struct argf *p;
7532 VALUE argf = TypedData_Make_Struct(klass, struct argf, &argf_type, p);
7533
7534 argf_init(p, Qnil);
7535 return argf;
7536 }
7537
7538 #undef rb_argv
7539
7540 /* :nodoc: */
7541 static VALUE
7542 argf_initialize(VALUE argf, VALUE argv)
7543 {
7544 memset(&ARGF, 0, sizeof(ARGF));
7545 argf_init(&ARGF, argv);
7546
7547 return argf;
7548 }
7549
7550 /* :nodoc: */
7551 static VALUE
7552 argf_initialize_copy(VALUE argf, VALUE orig)
7553 {
7554 if (!OBJ_INIT_COPY(argf, orig)) return argf;
7555 ARGF = argf_of(orig);
7556 ARGF.argv = rb_obj_dup(ARGF.argv);
7557 if (ARGF.inplace) {
7558 const char *inplace = ARGF.inplace;
7559 ARGF.inplace = 0;
7560 ARGF.inplace = ruby_strdup(inplace);
7561 }
7562 return argf;
7563 }
7564
7565 /*
7566 * call-seq:
7567 * ARGF.lineno = integer -> integer
7568 *
7569 * Sets the line number of +ARGF+ as a whole to the given +Integer+.
7570 *
7571 * +ARGF+ sets the line number automatically as you read data, so normally
7572 * you will not need to set it explicitly. To access the current line number
7573 * use +ARGF.lineno+.
7574 *
7575 * For example:
7576 *
7577 * ARGF.lineno #=> 0
7578 * ARGF.readline #=> "This is line 1\n"
7579 * ARGF.lineno #=> 1
7580 * ARGF.lineno = 0 #=> 0
7581 * ARGF.lineno #=> 0
7582 */
7583 static VALUE
7584 argf_set_lineno(VALUE argf, VALUE val)
7585 {
7586 ARGF.lineno = NUM2INT(val);
7587 ARGF.last_lineno = ARGF.lineno;
7588 return Qnil;
7589 }
7590
7591 /*
7592 * call-seq:
7593 * ARGF.lineno -> integer
7594 *
7595 * Returns the current line number of ARGF as a whole. This value
7596 * can be set manually with +ARGF.lineno=+.
7597 *
7598 * For example:
7599 *
7600 * ARGF.lineno #=> 0
7601 * ARGF.readline #=> "This is line 1\n"
7602 * ARGF.lineno #=> 1
7603 */
7604 static VALUE
7605 argf_lineno(VALUE argf)
7606 {
7607 return INT2FIX(ARGF.lineno);
7608 }
7609
7610 static VALUE
7611 argf_forward(int argc, VALUE *argv, VALUE argf)
7612 {
7613 return rb_funcall3(ARGF.current_file, rb_frame_this_func(), argc, argv);
7614 }
7615
7616 #define next_argv() argf_next_argv(argf)
7617 #define ARGF_GENERIC_INPUT_P() \
7618 (ARGF.current_file == rb_stdin && !RB_TYPE_P(ARGF.current_file, T_FILE))
7619 #define ARGF_FORWARD(argc, argv) do {\
7620 if (ARGF_GENERIC_INPUT_P())\
7621 return argf_forward((argc), (argv), argf);\
7622 } while (0)
7623 #define NEXT_ARGF_FORWARD(argc, argv) do {\
7624 if (!next_argv()) return Qnil;\
7625 ARGF_FORWARD((argc), (argv));\
7626 } while (0)
7627
7628 static void
7629 argf_close(VALUE file)
7630 {
7631 if (file == rb_stdin) return;
7632 if (RB_TYPE_P(file, T_FILE)) {
7633 rb_io_set_write_io(file, Qnil);
7634 }
7635 rb_funcall3(file, rb_intern("close"), 0, 0);
7636 }
7637
7638 static int
7639 argf_next_argv(VALUE argf)
7640 {
7641 char *fn;
7642 rb_io_t *fptr;
7643 int stdout_binmode = 0;
7644 int fmode;
7645
7646 if (RB_TYPE_P(rb_stdout, T_FILE)) {
7647 GetOpenFile(rb_stdout, fptr);
7648 if (fptr->mode & FMODE_BINMODE)
7649 stdout_binmode = 1;
7650 }
7651
7652 if (ARGF.init_p == 0) {
7653 if (!NIL_P(ARGF.argv) && RARRAY_LEN(ARGF.argv) > 0) {
7654 ARGF.next_p = 1;
7655 }
7656 else {
7657 ARGF.next_p = -1;
7658 }
7659 ARGF.init_p = 1;
7660 }
7661 else {
7662 if (NIL_P(ARGF.argv)) {
7663 ARGF.next_p = -1;
7664 }
7665 else if (ARGF.next_p == -1 && RARRAY_LEN(ARGF.argv) > 0) {
7666 ARGF.next_p = 1;
7667 }
7668 }
7669
7670 if (ARGF.next_p == 1) {
7671 retry:
7672 if (RARRAY_LEN(ARGF.argv) > 0) {
7673 ARGF.filename = rb_ary_shift(ARGF.argv);
7674 fn = StringValueCStr(ARGF.filename);
7675 if (strlen(fn) == 1 && fn[0] == '-') {
7676 ARGF.current_file = rb_stdin;
7677 if (ARGF.inplace) {
7678 rb_warn("Can't do inplace edit for stdio; skipping");
7679 goto retry;
7680 }
7681 }
7682 else {
7683 VALUE write_io = Qnil;
7684 int fr = rb_sysopen(ARGF.filename, O_RDONLY, 0);
7685
7686 if (ARGF.inplace) {
7687 struct stat st;
7688 #ifndef NO_SAFE_RENAME
7689 struct stat st2;
7690 #endif
7691 VALUE str;
7692 int fw;
7693
7694 if (RB_TYPE_P(rb_stdout, T_FILE) && rb_stdout != orig_stdout) {
7695 rb_io_close(rb_stdout);
7696 }
7697 fstat(fr, &st);
7698 if (*ARGF.inplace) {
7699 str = rb_str_new2(fn);
7700 rb_str_cat2(str, ARGF.inplace);
7701 #ifdef NO_SAFE_RENAME
7702 (void)close(fr);
7703 (void)unlink(RSTRING_PTR(str));
7704 if (rename(fn, RSTRING_PTR(str)) < 0) {
7705 rb_warn("Can't rename %s to %s: %s, skipping file",
7706 fn, RSTRING_PTR(str), strerror(errno));
7707 goto retry;
7708 }
7709 fr = rb_sysopen(str, O_RDONLY, 0);
7710 #else
7711 if (rename(fn, RSTRING_PTR(str)) < 0) {
7712 rb_warn("Can't rename %s to %s: %s, skipping file",
7713 fn, RSTRING_PTR(str), strerror(errno));
7714 close(fr);
7715 goto retry;
7716 }
7717 #endif
7718 }
7719 else {
7720 #ifdef NO_SAFE_RENAME
7721 rb_fatal("Can't do inplace edit without backup");
7722 #else
7723 if (unlink(fn) < 0) {
7724 rb_warn("Can't remove %s: %s, skipping file",
7725 fn, strerror(errno));
7726 close(fr);
7727 goto retry;
7728 }
7729 #endif
7730 }
7731 fw = rb_sysopen(ARGF.filename, O_WRONLY|O_CREAT|O_TRUNC, 0666);
7732 #ifndef NO_SAFE_RENAME
7733 fstat(fw, &st2);
7734 #ifdef HAVE_FCHMOD
7735 fchmod(fw, st.st_mode);
7736 #else
7737 chmod(fn, st.st_mode);
7738 #endif
7739 if (st.st_uid!=st2.st_uid || st.st_gid!=st2.st_gid) {
7740 int err;
7741 #ifdef HAVE_FCHOWN
7742 err = fchown(fw, st.st_uid, st.st_gid);
7743 #else
7744 err = chown(fn, st.st_uid, st.st_gid);
7745 #endif
7746 if (err && getuid() == 0 && st2.st_uid == 0) {
7747 const char *wkfn = RSTRING_PTR(ARGF.filename);
7748 rb_warn("Can't set owner/group of %s to same as %s: %s, skipping file",
7749 wkfn, fn, strerror(errno));
7750 (void)close(fr);
7751 (void)close(fw);
7752 (void)unlink(wkfn);
7753 goto retry;
7754 }
7755 }
7756 #endif
7757 write_io = prep_io(fw, FMODE_WRITABLE, rb_cFile, fn);
7758 rb_stdout = write_io;
7759 if (stdout_binmode) rb_io_binmode(rb_stdout);
7760 }
7761 fmode = FMODE_READABLE;
7762 if (!ARGF.binmode) {
7763 fmode |= DEFAULT_TEXTMODE;
7764 }
7765 ARGF.current_file = prep_io(fr, fmode, rb_cFile, fn);
7766 if (!NIL_P(write_io)) {
7767 rb_io_set_write_io(ARGF.current_file, write_io);
7768 }
7769 }
7770 if (ARGF.binmode) rb_io_ascii8bit_binmode(ARGF.current_file);
7771 GetOpenFile(ARGF.current_file, fptr);
7772 if (ARGF.encs.enc) {
7773 fptr->encs = ARGF.encs;
7774 clear_codeconv(fptr);
7775 }
7776 else {
7777 fptr->encs.ecflags &= ~ECONV_NEWLINE_DECORATOR_MASK;
7778 if (!ARGF.binmode) {
7779 fptr->encs.ecflags |= ECONV_DEFAULT_NEWLINE_DECORATOR;
7780 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
7781 fptr->encs.ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
7782 #endif
7783 }
7784 }
7785 ARGF.next_p = 0;
7786 }
7787 else {
7788 ARGF.next_p = 1;
7789 return FALSE;
7790 }
7791 }
7792 else if (ARGF.next_p == -1) {
7793 ARGF.current_file = rb_stdin;
7794 ARGF.filename = rb_str_new2("-");
7795 if (ARGF.inplace) {
7796 rb_warn("Can't do inplace edit for stdio");
7797 rb_stdout = orig_stdout;
7798 }
7799 }
7800 return TRUE;
7801 }
7802
7803 static VALUE
7804 argf_getline(int argc, VALUE *argv, VALUE argf)
7805 {
7806 VALUE line;
7807 long lineno = ARGF.lineno;
7808
7809 retry:
7810 if (!next_argv()) return Qnil;
7811 if (ARGF_GENERIC_INPUT_P()) {
7812 line = rb_funcall3(ARGF.current_file, idGets, argc, argv);
7813 }
7814 else {
7815 if (argc == 0 && rb_rs == rb_default_rs) {
7816 line = rb_io_gets(ARGF.current_file);
7817 }
7818 else {
7819 line = rb_io_getline(argc, argv, ARGF.current_file);
7820 }
7821 if (NIL_P(line) && ARGF.next_p != -1) {
7822 argf_close(ARGF.current_file);
7823 ARGF.next_p = 1;
7824 goto retry;
7825 }
7826 }
7827 if (!NIL_P(line)) {
7828 ARGF.lineno = ++lineno;
7829 ARGF.last_lineno = ARGF.lineno;
7830 }
7831 return line;
7832 }
7833
7834 static VALUE
7835 argf_lineno_getter(ID id, VALUE *var)
7836 {
7837 VALUE argf = *var;
7838 return INT2FIX(ARGF.last_lineno);
7839 }
7840
7841 static void
7842 argf_lineno_setter(VALUE val, ID id, VALUE *var)
7843 {
7844 VALUE argf = *var;
7845 int n = NUM2INT(val);
7846 ARGF.last_lineno = ARGF.lineno = n;
7847 }
7848
7849 static VALUE argf_gets(int, VALUE *, VALUE);
7850
7851 /*
7852 * call-seq:
7853 * gets(sep=$/) -> string or nil
7854 * gets(limit) -> string or nil
7855 * gets(sep,limit) -> string or nil
7856 *
7857 * Returns (and assigns to <code>$_</code>) the next line from the list
7858 * of files in +ARGV+ (or <code>$*</code>), or from standard input if
7859 * no files are present on the command line. Returns +nil+ at end of
7860 * file. The optional argument specifies the record separator. The
7861 * separator is included with the contents of each record. A separator
7862 * of +nil+ reads the entire contents, and a zero-length separator
7863 * reads the input one paragraph at a time, where paragraphs are
7864 * divided by two consecutive newlines. If the first argument is an
7865 * integer, or optional second argument is given, the returning string
7866 * would not be longer than the given value in bytes. If multiple
7867 * filenames are present in +ARGV+, +gets(nil)+ will read the contents
7868 * one file at a time.
7869 *
7870 * ARGV << "testfile"
7871 * print while gets
7872 *
7873 * <em>produces:</em>
7874 *
7875 * This is line one
7876 * This is line two
7877 * This is line three
7878 * And so on...
7879 *
7880 * The style of programming using <code>$_</code> as an implicit
7881 * parameter is gradually losing favor in the Ruby community.
7882 */
7883
7884 static VALUE
7885 rb_f_gets(int argc, VALUE *argv, VALUE recv)
7886 {
7887 if (recv == argf) {
7888 return argf_gets(argc, argv, argf);
7889 }
7890 return rb_funcall2(argf, idGets, argc, argv);
7891 }
7892
7893 /*
7894 * call-seq:
7895 * ARGF.gets(sep=$/) -> string
7896 * ARGF.gets(limit) -> string
7897 * ARGF.gets(sep, limit) -> string
7898 *
7899 * Returns the next line from the current file in +ARGF+.
7900 *
7901 * By default lines are assumed to be separated by +$/+; to use a different
7902 * character as a separator, supply it as a +String+ for the _sep_ argument.
7903 *
7904 * The optional _limit_ argument specifies how many characters of each line
7905 * to return. By default all characters are returned.
7906 *
7907 */
7908 static VALUE
7909 argf_gets(int argc, VALUE *argv, VALUE argf)
7910 {
7911 VALUE line;
7912
7913 line = argf_getline(argc, argv, argf);
7914 rb_lastline_set(line);
7915
7916 return line;
7917 }
7918
7919 VALUE
7920 rb_gets(void)
7921 {
7922 VALUE line;
7923
7924 if (rb_rs != rb_default_rs) {
7925 return rb_f_gets(0, 0, argf);
7926 }
7927
7928 retry:
7929 if (!next_argv()) return Qnil;
7930 line = rb_io_gets(ARGF.current_file);
7931 if (NIL_P(line) && ARGF.next_p != -1) {
7932 rb_io_close(ARGF.current_file);
7933 ARGF.next_p = 1;
7934 goto retry;
7935 }
7936 rb_lastline_set(line);
7937 if (!NIL_P(line)) {
7938 ARGF.lineno++;
7939 ARGF.last_lineno = ARGF.lineno;
7940 }
7941
7942 return line;
7943 }
7944
7945 static VALUE argf_readline(int, VALUE *, VALUE);
7946
7947 /*
7948 * call-seq:
7949 * readline(sep=$/) -> string
7950 * readline(limit) -> string
7951 * readline(sep, limit) -> string
7952 *
7953 * Equivalent to <code>Kernel::gets</code>, except
7954 * +readline+ raises +EOFError+ at end of file.
7955 */
7956
7957 static VALUE
7958 rb_f_readline(int argc, VALUE *argv, VALUE recv)
7959 {
7960 if (recv == argf) {
7961 return argf_readline(argc, argv, argf);
7962 }
7963 return rb_funcall2(argf, rb_intern("readline"), argc, argv);
7964 }
7965
7966
7967 /*
7968 * call-seq:
7969 * ARGF.readline(sep=$/) -> string
7970 * ARGF.readline(limit) -> string
7971 * ARGF.readline(sep, limit) -> string
7972 *
7973 * Returns the next line from the current file in +ARGF+.
7974 *
7975 * By default lines are assumed to be separated by +$/+; to use a different
7976 * character as a separator, supply it as a +String+ for the _sep_ argument.
7977 *
7978 * The optional _limit_ argument specifies how many characters of each line
7979 * to return. By default all characters are returned.
7980 *
7981 * An +EOFError+ is raised at the end of the file.
7982 */
7983 static VALUE
7984 argf_readline(int argc, VALUE *argv, VALUE argf)
7985 {
7986 VALUE line;
7987
7988 if (!next_argv()) rb_eof_error();
7989 ARGF_FORWARD(argc, argv);
7990 line = argf_gets(argc, argv, argf);
7991 if (NIL_P(line)) {
7992 rb_eof_error();
7993 }
7994
7995 return line;
7996 }
7997
7998 static VALUE argf_readlines(int, VALUE *, VALUE);
7999
8000 /*
8001 * call-seq:
8002 * readlines(sep=$/) -> array
8003 * readlines(limit) -> array
8004 * readlines(sep,limit) -> array
8005 *
8006 * Returns an array containing the lines returned by calling
8007 * <code>Kernel.gets(<i>sep</i>)</code> until the end of file.
8008 */
8009
8010 static VALUE
8011 rb_f_readlines(int argc, VALUE *argv, VALUE recv)
8012 {
8013 if (recv == argf) {
8014 return argf_readlines(argc, argv, argf);
8015 }
8016 return rb_funcall2(argf, rb_intern("readlines"), argc, argv);
8017 }
8018
8019 /*
8020 * call-seq:
8021 * ARGF.readlines(sep=$/) -> array
8022 * ARGF.readlines(limit) -> array
8023 * ARGF.readlines(sep, limit) -> array
8024 *
8025 * ARGF.to_a(sep=$/) -> array
8026 * ARGF.to_a(limit) -> array
8027 * ARGF.to_a(sep, limit) -> array
8028 *
8029 * Reads +ARGF+'s current file in its entirety, returning an +Array+ of its
8030 * lines, one line per element. Lines are assumed to be separated by _sep_.
8031 *
8032 * lines = ARGF.readlines
8033 * lines[0] #=> "This is line one\n"
8034 */
8035 static VALUE
8036 argf_readlines(int argc, VALUE *argv, VALUE argf)
8037 {
8038 long lineno = ARGF.lineno;
8039 VALUE lines, ary;
8040
8041 ary = rb_ary_new();
8042 while (next_argv()) {
8043 if (ARGF_GENERIC_INPUT_P()) {
8044 lines = rb_funcall3(ARGF.current_file, rb_intern("readlines"), argc, argv);
8045 }
8046 else {
8047 lines = rb_io_readlines(argc, argv, ARGF.current_file);
8048 argf_close(ARGF.current_file);
8049 }
8050 ARGF.next_p = 1;
8051 rb_ary_concat(ary, lines);
8052 ARGF.lineno = lineno + RARRAY_LEN(ary);
8053 ARGF.last_lineno = ARGF.lineno;
8054 }
8055 ARGF.init_p = 0;
8056 return ary;
8057 }
8058
8059 /*
8060 * call-seq:
8061 * `cmd` -> string
8062 *
8063 * Returns the standard output of running _cmd_ in a subshell.
8064 * The built-in syntax <code>%x{...}</code> uses
8065 * this method. Sets <code>$?</code> to the process status.
8066 *
8067 * `date` #=> "Wed Apr 9 08:56:30 CDT 2003\n"
8068 * `ls testdir`.split[1] #=> "main.rb"
8069 * `echo oops && exit 99` #=> "oops\n"
8070 * $?.exitstatus #=> 99
8071 */
8072
8073 static VALUE
8074 rb_f_backquote(VALUE obj, VALUE str)
8075 {
8076 volatile VALUE port;
8077 VALUE result;
8078 rb_io_t *fptr;
8079
8080 SafeStringValue(str);
8081 rb_last_status_clear();
8082 port = pipe_open_s(str, "r", FMODE_READABLE|DEFAULT_TEXTMODE, NULL);
8083 if (NIL_P(port)) return rb_str_new(0,0);
8084
8085 GetOpenFile(port, fptr);
8086 result = read_all(fptr, remain_size(fptr), Qnil);
8087 rb_io_close(port);
8088
8089 return result;
8090 }
8091
8092 #ifdef HAVE_SYS_SELECT_H
8093 #include <sys/select.h>
8094 #endif
8095
8096 static VALUE
8097 select_internal(VALUE read, VALUE write, VALUE except, struct timeval *tp, rb_fdset_t *fds)
8098 {
8099 VALUE res, list;
8100 rb_fdset_t *rp, *wp, *ep;
8101 rb_io_t *fptr;
8102 long i;
8103 int max = 0, n;
8104 int pending = 0;
8105 struct timeval timerec;
8106
8107 if (!NIL_P(read)) {
8108 Check_Type(read, T_ARRAY);
8109 for (i=0; i<RARRAY_LEN(read); i++) {
8110 GetOpenFile(rb_io_get_io(RARRAY_PTR(read)[i]), fptr);
8111 rb_fd_set(fptr->fd, &fds[0]);
8112 if (READ_DATA_PENDING(fptr) || READ_CHAR_PENDING(fptr)) { /* check for buffered data */
8113 pending++;
8114 rb_fd_set(fptr->fd, &fds[3]);
8115 }
8116 if (max < fptr->fd) max = fptr->fd;
8117 }
8118 if (pending) { /* no blocking if there's buffered data */
8119 timerec.tv_sec = timerec.tv_usec = 0;
8120 tp = &timerec;
8121 }
8122 rp = &fds[0];
8123 }
8124 else
8125 rp = 0;
8126
8127 if (!NIL_P(write)) {
8128 Check_Type(write, T_ARRAY);
8129 for (i=0; i<RARRAY_LEN(write); i++) {
8130 VALUE write_io = GetWriteIO(rb_io_get_io(RARRAY_PTR(write)[i]));
8131 GetOpenFile(write_io, fptr);
8132 rb_fd_set(fptr->fd, &fds[1]);
8133 if (max < fptr->fd) max = fptr->fd;
8134 }
8135 wp = &fds[1];
8136 }
8137 else
8138 wp = 0;
8139
8140 if (!NIL_P(except)) {
8141 Check_Type(except, T_ARRAY);
8142 for (i=0; i<RARRAY_LEN(except); i++) {
8143 VALUE io = rb_io_get_io(RARRAY_PTR(except)[i]);
8144 VALUE write_io = GetWriteIO(io);
8145 GetOpenFile(io, fptr);
8146 rb_fd_set(fptr->fd, &fds[2]);
8147 if (max < fptr->fd) max = fptr->fd;
8148 if (io != write_io) {
8149 GetOpenFile(write_io, fptr);
8150 rb_fd_set(fptr->fd, &fds[2]);
8151 if (max < fptr->fd) max = fptr->fd;
8152 }
8153 }
8154 ep = &fds[2];
8155 }
8156 else {
8157 ep = 0;
8158 }
8159
8160 max++;
8161
8162 n = rb_thread_fd_select(max, rp, wp, ep, tp);
8163 if (n < 0) {
8164 rb_sys_fail(0);
8165 }
8166 if (!pending && n == 0) return Qnil; /* returns nil on timeout */
8167
8168 res = rb_ary_new2(3);
8169 rb_ary_push(res, rp?rb_ary_new():rb_ary_new2(0));
8170 rb_ary_push(res, wp?rb_ary_new():rb_ary_new2(0));
8171 rb_ary_push(res, ep?rb_ary_new():rb_ary_new2(0));
8172
8173 if (rp) {
8174 list = RARRAY_PTR(res)[0];
8175 for (i=0; i< RARRAY_LEN(read); i++) {
8176 VALUE obj = rb_ary_entry(read, i);
8177 VALUE io = rb_io_get_io(obj);
8178 GetOpenFile(io, fptr);
8179 if (rb_fd_isset(fptr->fd, &fds[0]) ||
8180 rb_fd_isset(fptr->fd, &fds[3])) {
8181 rb_ary_push(list, obj);
8182 }
8183 }
8184 }
8185
8186 if (wp) {
8187 list = RARRAY_PTR(res)[1];
8188 for (i=0; i< RARRAY_LEN(write); i++) {
8189 VALUE obj = rb_ary_entry(write, i);
8190 VALUE io = rb_io_get_io(obj);
8191 VALUE write_io = GetWriteIO(io);
8192 GetOpenFile(write_io, fptr);
8193 if (rb_fd_isset(fptr->fd, &fds[1])) {
8194 rb_ary_push(list, obj);
8195 }
8196 }
8197 }
8198
8199 if (ep) {
8200 list = RARRAY_PTR(res)[2];
8201 for (i=0; i< RARRAY_LEN(except); i++) {
8202 VALUE obj = rb_ary_entry(except, i);
8203 VALUE io = rb_io_get_io(obj);
8204 VALUE write_io = GetWriteIO(io);
8205 GetOpenFile(io, fptr);
8206 if (rb_fd_isset(fptr->fd, &fds[2])) {
8207 rb_ary_push(list, obj);
8208 }
8209 else if (io != write_io) {
8210 GetOpenFile(write_io, fptr);
8211 if (rb_fd_isset(fptr->fd, &fds[2])) {
8212 rb_ary_push(list, obj);
8213 }
8214 }
8215 }
8216 }
8217
8218 return res; /* returns an empty array on interrupt */
8219 }
8220
8221 struct select_args {
8222 VALUE read, write, except;
8223 struct timeval *timeout;
8224 rb_fdset_t fdsets[4];
8225 };
8226
8227 static VALUE
8228 select_call(VALUE arg)
8229 {
8230 struct select_args *p = (struct select_args *)arg;
8231
8232 return select_internal(p->read, p->write, p->except, p->timeout, p->fdsets);
8233 }
8234
8235 static VALUE
8236 select_end(VALUE arg)
8237 {
8238 struct select_args *p = (struct select_args *)arg;
8239 int i;
8240
8241 for (i = 0; i < numberof(p->fdsets); ++i)
8242 rb_fd_term(&p->fdsets[i]);
8243 return Qnil;
8244 }
8245
8246 static VALUE sym_normal, sym_sequential, sym_random,
8247 sym_willneed, sym_dontneed, sym_noreuse;
8248
8249 #ifdef HAVE_POSIX_FADVISE
8250 struct io_advise_struct {
8251 int fd;
8252 off_t offset;
8253 off_t len;
8254 int advice;
8255 };
8256
8257 static VALUE
8258 io_advise_internal(void *arg)
8259 {
8260 struct io_advise_struct *ptr = arg;
8261 return posix_fadvise(ptr->fd, ptr->offset, ptr->len, ptr->advice);
8262 }
8263
8264 static VALUE
8265 io_advise_sym_to_const(VALUE sym)
8266 {
8267 #ifdef POSIX_FADV_NORMAL
8268 if (sym == sym_normal)
8269 return INT2NUM(POSIX_FADV_NORMAL);
8270 #endif
8271
8272 #ifdef POSIX_FADV_RANDOM
8273 if (sym == sym_random)
8274 return INT2NUM(POSIX_FADV_RANDOM);
8275 #endif
8276
8277 #ifdef POSIX_FADV_SEQUENTIAL
8278 if (sym == sym_sequential)
8279 return INT2NUM(POSIX_FADV_SEQUENTIAL);
8280 #endif
8281
8282 #ifdef POSIX_FADV_WILLNEED
8283 if (sym == sym_willneed)
8284 return INT2NUM(POSIX_FADV_WILLNEED);
8285 #endif
8286
8287 #ifdef POSIX_FADV_DONTNEED
8288 if (sym == sym_dontneed)
8289 return INT2NUM(POSIX_FADV_DONTNEED);
8290 #endif
8291
8292 #ifdef POSIX_FADV_NOREUSE
8293 if (sym == sym_noreuse)
8294 return INT2NUM(POSIX_FADV_NOREUSE);
8295 #endif
8296
8297 return Qnil;
8298 }
8299
8300 static VALUE
8301 do_io_advise(rb_io_t *fptr, VALUE advice, off_t offset, off_t len)
8302 {
8303 int rv;
8304 struct io_advise_struct ias;
8305 VALUE num_adv;
8306
8307 num_adv = io_advise_sym_to_const(advice);
8308
8309 /*
8310 * The platform doesn't support this hint. We don't raise exception, instead
8311 * silently ignore it. Because IO::advise is only hint.
8312 */
8313 if (NIL_P(num_adv))
8314 return Qnil;
8315
8316 ias.fd = fptr->fd;
8317 ias.advice = NUM2INT(num_adv);
8318 ias.offset = offset;
8319 ias.len = len;
8320
8321 rv = (int)rb_thread_io_blocking_region(io_advise_internal, &ias, fptr->fd);
8322 if (rv) {
8323 /* posix_fadvise(2) doesn't set errno. On success it returns 0; otherwise
8324 it returns the error code. */
8325 rb_syserr_fail_str(rv, fptr->pathv);
8326 }
8327
8328 return Qnil;
8329 }
8330
8331 #endif /* HAVE_POSIX_FADVISE */
8332
8333 static void
8334 advice_arg_check(VALUE advice)
8335 {
8336 if (!SYMBOL_P(advice))
8337 rb_raise(rb_eTypeError, "advice must be a Symbol");
8338
8339 if (advice != sym_normal &&
8340 advice != sym_sequential &&
8341 advice != sym_random &&
8342 advice != sym_willneed &&
8343 advice != sym_dontneed &&
8344 advice != sym_noreuse) {
8345 VALUE symname = rb_inspect(advice);
8346 rb_raise(rb_eNotImpError, "Unsupported advice: %s",
8347 StringValuePtr(symname));
8348 }
8349 }
8350
8351 /*
8352 * call-seq:
8353 * ios.advise(advice, offset=0, len=0) -> nil
8354 *
8355 * Announce an intention to access data from the current file in a
8356 * specific pattern. On platforms that do not support the
8357 * <em>posix_fadvise(2)</em> system call, this method is a no-op.
8358 *
8359 * _advice_ is one of the following symbols:
8360 *
8361 * * :normal - No advice to give; the default assumption for an open file.
8362 * * :sequential - The data will be accessed sequentially:
8363 * with lower offsets read before higher ones.
8364 * * :random - The data will be accessed in random order.
8365 * * :willneed - The data will be accessed in the near future.
8366 * * :dontneed - The data will not be accessed in the near future.
8367 * * :noreuse - The data will only be accessed once.
8368 *
8369 * The semantics of a piece of advice are platform-dependent. See
8370 * <em>man 2 posix_fadvise</em> for details.
8371 *
8372 * "data" means the region of the current file that begins at
8373 * _offset_ and extends for _len_ bytes. If _len_ is 0, the region
8374 * ends at the last byte of the file. By default, both _offset_ and
8375 * _len_ are 0, meaning that the advice applies to the entire file.
8376 *
8377 * If an error occurs, one of the following exceptions will be raised:
8378 *
8379 * * <code>IOError</code> - The <code>IO</code> stream is closed.
8380 * * <code>Errno::EBADF</code> - The file descriptor of the current file is
8381 invalid.
8382 * * <code>Errno::EINVAL</code> - An invalid value for _advice_ was given.
8383 * * <code>Errno::ESPIPE</code> - The file descriptor of the current
8384 * * file refers to a FIFO or pipe. (Linux raises <code>Errno::EINVAL</code>
8385 * * in this case).
8386 * * <code>TypeError</code> - Either _advice_ was not a Symbol, or one of the
8387 other arguments was not an <code>Integer</code>.
8388 * * <code>RangeError</code> - One of the arguments given was too big/small.
8389 *
8390 * This list is not exhaustive; other Errno:: exceptions are also possible.
8391 */
8392 static VALUE
8393 rb_io_advise(int argc, VALUE *argv, VALUE io)
8394 {
8395 VALUE advice, offset, len;
8396 off_t off, l;
8397 rb_io_t *fptr;
8398
8399 rb_scan_args(argc, argv, "12", &advice, &offset, &len);
8400 advice_arg_check(advice);
8401
8402 io = GetWriteIO(io);
8403 GetOpenFile(io, fptr);
8404
8405 off = NIL_P(offset) ? 0 : NUM2OFFT(offset);
8406 l = NIL_P(len) ? 0 : NUM2OFFT(len);
8407
8408 #ifdef HAVE_POSIX_FADVISE
8409 return do_io_advise(fptr, advice, off, l);
8410 #else
8411 ((void)off, (void)l); /* Ignore all hint */
8412 return Qnil;
8413 #endif
8414 }
8415
8416 /*
8417 * call-seq:
8418 * IO.select(read_array
8419 * [, write_array
8420 * [, error_array
8421 * [, timeout]]]) -> array or nil
8422 *
8423 * Calls select(2) system call.
8424 * It monitors given arrays of <code>IO</code> objects, waits one or more
8425 * of <code>IO</code> objects ready for reading, are ready for writing,
8426 * and have pending exceptions respectably, and returns an array that
8427 * contains arrays of those IO objects. It will return <code>nil</code>
8428 * if optional <i>timeout</i> value is given and no <code>IO</code> object
8429 * is ready in <i>timeout</i> seconds.
8430 *
8431 * === Parameters
8432 * read_array:: an array of <code>IO</code> objects that wait until ready for read
8433 * write_array:: an array of <code>IO</code> objects that wait until ready for write
8434 * error_array:: an array of <code>IO</code> objects that wait for exceptions
8435 * timeout:: a numeric value in second
8436 *
8437 * === Example
8438 *
8439 * rp, wp = IO.pipe
8440 * mesg = "ping "
8441 * 100.times {
8442 * rs, ws, = IO.select([rp], [wp])
8443 * if r = rs[0]
8444 * ret = r.read(5)
8445 * print ret
8446 * case ret
8447 * when /ping/
8448 * mesg = "pong\n"
8449 * when /pong/
8450 * mesg = "ping "
8451 * end
8452 * end
8453 * if w = ws[0]
8454 * w.write(mesg)
8455 * end
8456 * }
8457 *
8458 * <em>produces:</em>
8459 *
8460 * ping pong
8461 * ping pong
8462 * ping pong
8463 * (snipped)
8464 * ping
8465 */
8466
8467 static VALUE
8468 rb_f_select(int argc, VALUE *argv, VALUE obj)
8469 {
8470 VALUE timeout;
8471 struct select_args args;
8472 struct timeval timerec;
8473 int i;
8474
8475 rb_scan_args(argc, argv, "13", &args.read, &args.write, &args.except, &timeout);
8476 if (NIL_P(timeout)) {
8477 args.timeout = 0;
8478 }
8479 else {
8480 timerec = rb_time_interval(timeout);
8481 args.timeout = &timerec;
8482 }
8483
8484 for (i = 0; i < numberof(args.fdsets); ++i)
8485 rb_fd_init(&args.fdsets[i]);
8486
8487 return rb_ensure(select_call, (VALUE)&args, select_end, (VALUE)&args);
8488 }
8489
8490 #if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
8491 typedef unsigned long ioctl_req_t;
8492 # define NUM2IOCTLREQ(num) NUM2ULONG(num)
8493 #else
8494 typedef int ioctl_req_t;
8495 # define NUM2IOCTLREQ(num) NUM2INT(num)
8496 #endif
8497
8498 struct ioctl_arg {
8499 int fd;
8500 ioctl_req_t cmd;
8501 long narg;
8502 };
8503
8504 static VALUE
8505 nogvl_ioctl(void *ptr)
8506 {
8507 struct ioctl_arg *arg = ptr;
8508
8509 return (VALUE)ioctl(arg->fd, arg->cmd, arg->narg);
8510 }
8511
8512 static int
8513 do_ioctl(int fd, ioctl_req_t cmd, long narg)
8514 {
8515 int retval;
8516 struct ioctl_arg arg;
8517
8518 arg.fd = fd;
8519 arg.cmd = cmd;
8520 arg.narg = narg;
8521
8522 retval = (int)rb_thread_io_blocking_region(nogvl_ioctl, &arg, fd);
8523
8524 return retval;
8525 }
8526
8527 #define DEFULT_IOCTL_NARG_LEN (256)
8528
8529 #ifdef __linux__
8530 static long
8531 linux_iocparm_len(ioctl_req_t cmd)
8532 {
8533 long len;
8534
8535 if ((cmd & 0xFFFF0000) == 0) {
8536 /* legacy and unstructured ioctl number. */
8537 return DEFULT_IOCTL_NARG_LEN;
8538 }
8539
8540 len = _IOC_SIZE(cmd);
8541
8542 /* paranoia check for silly drivers which don't keep ioctl convention */
8543 if (len < DEFULT_IOCTL_NARG_LEN)
8544 len = DEFULT_IOCTL_NARG_LEN;
8545
8546 return len;
8547 }
8548 #endif
8549
8550 static long
8551 ioctl_narg_len(ioctl_req_t cmd)
8552 {
8553 long len;
8554
8555 #ifdef IOCPARM_MASK
8556 #ifndef IOCPARM_LEN
8557 #define IOCPARM_LEN(x) (((x) >> 16) & IOCPARM_MASK)
8558 #endif
8559 #endif
8560 #ifdef IOCPARM_LEN
8561 len = IOCPARM_LEN(cmd); /* on BSDish systems we're safe */
8562 #elif defined(__linux__)
8563 len = linux_iocparm_len(cmd);
8564 #else
8565 /* otherwise guess at what's safe */
8566 len = DEFULT_IOCTL_NARG_LEN;
8567 #endif
8568
8569 return len;
8570 }
8571
8572 #ifdef HAVE_FCNTL
8573 #ifdef __linux__
8574 typedef long fcntl_arg_t;
8575 #else
8576 /* posix */
8577 typedef int fcntl_arg_t;
8578 #endif
8579
8580 static long
8581 fcntl_narg_len(int cmd)
8582 {
8583 long len;
8584
8585 switch (cmd) {
8586 #ifdef F_DUPFD
8587 case F_DUPFD:
8588 len = sizeof(fcntl_arg_t);
8589 break;
8590 #endif
8591 #ifdef F_DUP2FD /* bsd specific */
8592 case F_DUP2FD:
8593 len = sizeof(int);
8594 break;
8595 #endif
8596 #ifdef F_DUPFD_CLOEXEC /* linux specific */
8597 case F_DUPFD_CLOEXEC:
8598 len = sizeof(fcntl_arg_t);
8599 break;
8600 #endif
8601 #ifdef F_GETFD
8602 case F_GETFD:
8603 len = 1;
8604 break;
8605 #endif
8606 #ifdef F_SETFD
8607 case F_SETFD:
8608 len = sizeof(fcntl_arg_t);
8609 break;
8610 #endif
8611 #ifdef F_GETFL
8612 case F_GETFL:
8613 len = 1;
8614 break;
8615 #endif
8616 #ifdef F_SETFL
8617 case F_SETFL:
8618 len = sizeof(fcntl_arg_t);
8619 break;
8620 #endif
8621 #ifdef F_GETOWN
8622 case F_GETOWN:
8623 len = 1;
8624 break;
8625 #endif
8626 #ifdef F_SETOWN
8627 case F_SETOWN:
8628 len = sizeof(fcntl_arg_t);
8629 break;
8630 #endif
8631 #ifdef F_GETOWN_EX /* linux specific */
8632 case F_GETOWN_EX:
8633 len = sizeof(struct f_owner_ex);
8634 break;
8635 #endif
8636 #ifdef F_SETOWN_EX /* linux specific */
8637 case F_SETOWN_EX:
8638 len = sizeof(struct f_owner_ex);
8639 break;
8640 #endif
8641 #ifdef F_GETLK
8642 case F_GETLK:
8643 len = sizeof(struct flock);
8644 break;
8645 #endif
8646 #ifdef F_SETLK
8647 case F_SETLK:
8648 len = sizeof(struct flock);
8649 break;
8650 #endif
8651 #ifdef F_SETLKW
8652 case F_SETLKW:
8653 len = sizeof(struct flock);
8654 break;
8655 #endif
8656 #ifdef F_READAHEAD /* bsd specific */
8657 case F_READAHEAD:
8658 len = sizeof(int);
8659 break;
8660 #endif
8661 #ifdef F_RDAHEAD /* Darwin specific */
8662 case F_RDAHEAD:
8663 len = sizeof(int);
8664 break;
8665 #endif
8666 #ifdef F_GETSIG /* linux specific */
8667 case F_GETSIG:
8668 len = 1;
8669 break;
8670 #endif
8671 #ifdef F_SETSIG /* linux specific */
8672 case F_SETSIG:
8673 len = sizeof(fcntl_arg_t);
8674 break;
8675 #endif
8676 #ifdef F_GETLEASE /* linux specific */
8677 case F_GETLEASE:
8678 len = 1;
8679 break;
8680 #endif
8681 #ifdef F_SETLEASE /* linux specific */
8682 case F_SETLEASE:
8683 len = sizeof(fcntl_arg_t);
8684 break;
8685 #endif
8686 #ifdef F_NOTIFY /* linux specific */
8687 case F_NOTIFY:
8688 len = sizeof(fcntl_arg_t);
8689 break;
8690 #endif
8691
8692 default:
8693 len = 256;
8694 break;
8695 }
8696
8697 return len;
8698 }
8699 #else /* HAVE_FCNTL */
8700 static long
8701 fcntl_narg_len(int cmd)
8702 {
8703 return 0;
8704 }
8705 #endif /* HAVE_FCNTL */
8706
8707 static long
8708 setup_narg(ioctl_req_t cmd, VALUE *argp, int io_p)
8709 {
8710 long narg = 0;
8711 VALUE arg = *argp;
8712
8713 if (NIL_P(arg) || arg == Qfalse) {
8714 narg = 0;
8715 }
8716 else if (FIXNUM_P(arg)) {
8717 narg = FIX2LONG(arg);
8718 }
8719 else if (arg == Qtrue) {
8720 narg = 1;
8721 }
8722 else {
8723 VALUE tmp = rb_check_string_type(arg);
8724
8725 if (NIL_P(tmp)) {
8726 narg = NUM2LONG(arg);
8727 }
8728 else {
8729 long len;
8730
8731 *argp = arg = tmp;
8732 if (io_p)
8733 len = ioctl_narg_len(cmd);
8734 else
8735 len = fcntl_narg_len((int)cmd);
8736 rb_str_modify(arg);
8737
8738 /* expand for data + sentinel. */
8739 if (RSTRING_LEN(arg) < len+1) {
8740 rb_str_resize(arg, len+1);
8741 }
8742 /* a little sanity check here */
8743 RSTRING_PTR(arg)[RSTRING_LEN(arg) - 1] = 17;
8744 narg = (long)(SIGNED_VALUE)RSTRING_PTR(arg);
8745 }
8746 }
8747
8748 return narg;
8749 }
8750
8751 static VALUE
8752 rb_ioctl(VALUE io, VALUE req, VALUE arg)
8753 {
8754 ioctl_req_t cmd = NUM2IOCTLREQ(req);
8755 rb_io_t *fptr;
8756 long narg;
8757 int retval;
8758
8759 rb_secure(2);
8760
8761 narg = setup_narg(cmd, &arg, 1);
8762 GetOpenFile(io, fptr);
8763 retval = do_ioctl(fptr->fd, cmd, narg);
8764 if (retval < 0) rb_sys_fail_path(fptr->pathv);
8765 if (RB_TYPE_P(arg, T_STRING)) {
8766 if (RSTRING_PTR(arg)[RSTRING_LEN(arg)-1] != 17)
8767 rb_raise(rb_eArgError, "return value overflowed string");
8768 RSTRING_PTR(arg)[RSTRING_LEN(arg)-1] = '\0';
8769 }
8770
8771 return INT2NUM(retval);
8772 }
8773
8774 /*
8775 * call-seq:
8776 * ios.ioctl(integer_cmd, arg) -> integer
8777 *
8778 * Provides a mechanism for issuing low-level commands to control or
8779 * query I/O devices. Arguments and results are platform dependent. If
8780 * <i>arg</i> is a number, its value is passed directly. If it is a
8781 * string, it is interpreted as a binary sequence of bytes. On Unix
8782 * platforms, see <code>ioctl(2)</code> for details. Not implemented on
8783 * all platforms.
8784 */
8785
8786 static VALUE
8787 rb_io_ioctl(int argc, VALUE *argv, VALUE io)
8788 {
8789 VALUE req, arg;
8790
8791 rb_scan_args(argc, argv, "11", &req, &arg);
8792 return rb_ioctl(io, req, arg);
8793 }
8794
8795 #ifdef HAVE_FCNTL
8796 struct fcntl_arg {
8797 int fd;
8798 int cmd;
8799 long narg;
8800 };
8801
8802 static VALUE
8803 nogvl_fcntl(void *ptr)
8804 {
8805 struct fcntl_arg *arg = ptr;
8806
8807 #if defined(F_DUPFD)
8808 if (arg->cmd == F_DUPFD)
8809 return (VALUE)rb_cloexec_fcntl_dupfd(arg->fd, (int)arg->narg);
8810 #endif
8811 return (VALUE)fcntl(arg->fd, arg->cmd, arg->narg);
8812 }
8813
8814 static int
8815 do_fcntl(int fd, int cmd, long narg)
8816 {
8817 int retval;
8818 struct fcntl_arg arg;
8819
8820 arg.fd = fd;
8821 arg.cmd = cmd;
8822 arg.narg = narg;
8823
8824 retval = (int)rb_thread_io_blocking_region(nogvl_fcntl, &arg, fd);
8825 #if defined(F_DUPFD)
8826 if (retval != -1 && cmd == F_DUPFD) {
8827 rb_update_max_fd(retval);
8828 }
8829 #endif
8830
8831 return retval;
8832 }
8833
8834 static VALUE
8835 rb_fcntl(VALUE io, VALUE req, VALUE arg)
8836 {
8837 int cmd = NUM2INT(req);
8838 rb_io_t *fptr;
8839 long narg;
8840 int retval;
8841
8842 rb_secure(2);
8843
8844 narg = setup_narg(cmd, &arg, 0);
8845 GetOpenFile(io, fptr);
8846 retval = do_fcntl(fptr->fd, cmd, narg);
8847 if (retval < 0) rb_sys_fail_path(fptr->pathv);
8848 if (RB_TYPE_P(arg, T_STRING)) {
8849 if (RSTRING_PTR(arg)[RSTRING_LEN(arg)-1] != 17)
8850 rb_raise(rb_eArgError, "return value overflowed string");
8851 RSTRING_PTR(arg)[RSTRING_LEN(arg)-1] = '\0';
8852 }
8853
8854 if (cmd == F_SETFL) {
8855 if (narg & O_NONBLOCK) {
8856 fptr->mode |= FMODE_WSPLIT_INITIALIZED;
8857 fptr->mode &= ~FMODE_WSPLIT;
8858 }
8859 else {
8860 fptr->mode &= ~(FMODE_WSPLIT_INITIALIZED|FMODE_WSPLIT);
8861 }
8862 }
8863
8864 return INT2NUM(retval);
8865 }
8866
8867 /*
8868 * call-seq:
8869 * ios.fcntl(integer_cmd, arg) -> integer
8870 *
8871 * Provides a mechanism for issuing low-level commands to control or
8872 * query file-oriented I/O streams. Arguments and results are platform
8873 * dependent. If <i>arg</i> is a number, its value is passed
8874 * directly. If it is a string, it is interpreted as a binary sequence
8875 * of bytes (<code>Array#pack</code> might be a useful way to build this
8876 * string). On Unix platforms, see <code>fcntl(2)</code> for details.
8877 * Not implemented on all platforms.
8878 */
8879
8880 static VALUE
8881 rb_io_fcntl(int argc, VALUE *argv, VALUE io)
8882 {
8883 VALUE req, arg;
8884
8885 rb_scan_args(argc, argv, "11", &req, &arg);
8886 return rb_fcntl(io, req, arg);
8887 }
8888 #else
8889 #define rb_io_fcntl rb_f_notimplement
8890 #endif
8891
8892 #if defined(HAVE_SYSCALL) || defined(HAVE___SYSCALL)
8893 /*
8894 * call-seq:
8895 * syscall(num [, args...]) -> integer
8896 *
8897 * Calls the operating system function identified by _num_ and
8898 * returns the result of the function or raises SystemCallError if
8899 * it failed.
8900 *
8901 * Arguments for the function can follow _num_. They must be either
8902 * +String+ objects or +Integer+ objects. A +String+ object is passed
8903 * as a pointer to the byte sequence. An +Integer+ object is passed
8904 * as an integer whose bit size is same as a pointer.
8905 * Up to nine parameters may be passed (14 on the Atari-ST).
8906 *
8907 * The function identified by _num_ is system
8908 * dependent. On some Unix systems, the numbers may be obtained from a
8909 * header file called <code>syscall.h</code>.
8910 *
8911 * syscall 4, 1, "hello\n", 6 # '4' is write(2) on our box
8912 *
8913 * <em>produces:</em>
8914 *
8915 * hello
8916 *
8917 *
8918 * Calling +syscall+ on a platform which does not have any way to
8919 * an arbitrary system function just fails with NotImplementedError.
8920 *
8921 * Note::
8922 * +syscall+ is essentially unsafe and unportable. Feel free to shoot your foot.
8923 * DL (Fiddle) library is preferred for safer and a bit more portable programming.
8924 */
8925
8926 static VALUE
8927 rb_f_syscall(int argc, VALUE *argv)
8928 {
8929 #ifdef atarist
8930 VALUE arg[13]; /* yes, we really need that many ! */
8931 #else
8932 VALUE arg[8];
8933 #endif
8934 #if SIZEOF_VOIDP == 8 && defined(HAVE___SYSCALL) && SIZEOF_INT != 8 /* mainly *BSD */
8935 # define SYSCALL __syscall
8936 # define NUM2SYSCALLID(x) NUM2LONG(x)
8937 # define RETVAL2NUM(x) LONG2NUM(x)
8938 # if SIZEOF_LONG == 8
8939 long num, retval = -1;
8940 # elif SIZEOF_LONG_LONG == 8
8941 long long num, retval = -1;
8942 # else
8943 # error ---->> it is asserted that __syscall takes the first argument and returns retval in 64bit signed integer. <<----
8944 # endif
8945 #elif defined(__linux__)
8946 # define SYSCALL syscall
8947 # define NUM2SYSCALLID(x) NUM2LONG(x)
8948 # define RETVAL2NUM(x) LONG2NUM(x)
8949 /*
8950 * Linux man page says, syscall(2) function prototype is below.
8951 *
8952 * int syscall(int number, ...);
8953 *
8954 * But, it's incorrect. Actual one takes and returned long. (see unistd.h)
8955 */
8956 long num, retval = -1;
8957 #else
8958 # define SYSCALL syscall
8959 # define NUM2SYSCALLID(x) NUM2INT(x)
8960 # define RETVAL2NUM(x) INT2NUM(x)
8961 int num, retval = -1;
8962 #endif
8963 int i;
8964
8965 if (RTEST(ruby_verbose)) {
8966 rb_warning("We plan to remove a syscall function at future release. DL(Fiddle) provides safer alternative.");
8967 }
8968
8969 rb_secure(2);
8970 if (argc == 0)
8971 rb_raise(rb_eArgError, "too few arguments for syscall");
8972 if (argc > numberof(arg))
8973 rb_raise(rb_eArgError, "too many arguments for syscall");
8974 num = NUM2SYSCALLID(argv[0]); ++argv;
8975 for (i = argc - 1; i--; ) {
8976 VALUE v = rb_check_string_type(argv[i]);
8977
8978 if (!NIL_P(v)) {
8979 SafeStringValue(v);
8980 rb_str_modify(v);
8981 arg[i] = (VALUE)StringValueCStr(v);
8982 }
8983 else {
8984 arg[i] = (VALUE)NUM2LONG(argv[i]);
8985 }
8986 }
8987
8988 switch (argc) {
8989 case 1:
8990 retval = SYSCALL(num);
8991 break;
8992 case 2:
8993 retval = SYSCALL(num, arg[0]);
8994 break;
8995 case 3:
8996 retval = SYSCALL(num, arg[0],arg[1]);
8997 break;
8998 case 4:
8999 retval = SYSCALL(num, arg[0],arg[1],arg[2]);
9000 break;
9001 case 5:
9002 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3]);
9003 break;
9004 case 6:
9005 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4]);
9006 break;
9007 case 7:
9008 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5]);
9009 break;
9010 case 8:
9011 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6]);
9012 break;
9013 #ifdef atarist
9014 case 9:
9015 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
9016 arg[7]);
9017 break;
9018 case 10:
9019 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
9020 arg[7], arg[8]);
9021 break;
9022 case 11:
9023 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
9024 arg[7], arg[8], arg[9]);
9025 break;
9026 case 12:
9027 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
9028 arg[7], arg[8], arg[9], arg[10]);
9029 break;
9030 case 13:
9031 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
9032 arg[7], arg[8], arg[9], arg[10], arg[11]);
9033 break;
9034 case 14:
9035 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
9036 arg[7], arg[8], arg[9], arg[10], arg[11], arg[12]);
9037 break;
9038 #endif
9039 }
9040
9041 if (retval == -1)
9042 rb_sys_fail(0);
9043 return RETVAL2NUM(retval);
9044 #undef SYSCALL
9045 #undef NUM2SYSCALLID
9046 #undef RETVAL2NUM
9047 }
9048 #else
9049 #define rb_f_syscall rb_f_notimplement
9050 #endif
9051
9052 static VALUE
9053 io_new_instance(VALUE args)
9054 {
9055 return rb_class_new_instance(2, (VALUE*)args+1, *(VALUE*)args);
9056 }
9057
9058 static rb_encoding *
9059 find_encoding(VALUE v)
9060 {
9061 rb_encoding *enc = rb_find_encoding(v);
9062 if (!enc) unsupported_encoding(StringValueCStr(v));
9063 return enc;
9064 }
9065
9066 static void
9067 io_encoding_set(rb_io_t *fptr, VALUE v1, VALUE v2, VALUE opt)
9068 {
9069 rb_encoding *enc, *enc2;
9070 int ecflags = fptr->encs.ecflags;
9071 VALUE ecopts, tmp;
9072
9073 if (!NIL_P(v2)) {
9074 enc2 = find_encoding(v1);
9075 tmp = rb_check_string_type(v2);
9076 if (!NIL_P(tmp)) {
9077 if (RSTRING_LEN(tmp) == 1 && RSTRING_PTR(tmp)[0] == '-') {
9078 /* Special case - "-" => no transcoding */
9079 enc = enc2;
9080 enc2 = NULL;
9081 }
9082 else
9083 enc = find_encoding(v2);
9084 if (enc == enc2) {
9085 /* Special case - "-" => no transcoding */
9086 enc2 = NULL;
9087 }
9088 }
9089 else {
9090 enc = find_encoding(v2);
9091 if (enc == enc2) {
9092 /* Special case - "-" => no transcoding */
9093 enc2 = NULL;
9094 }
9095 }
9096 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
9097 ecflags = rb_econv_prepare_options(opt, &ecopts, ecflags);
9098 }
9099 else {
9100 if (NIL_P(v1)) {
9101 /* Set to default encodings */
9102 rb_io_ext_int_to_encs(NULL, NULL, &enc, &enc2, 0);
9103 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
9104 ecopts = Qnil;
9105 }
9106 else {
9107 tmp = rb_check_string_type(v1);
9108 if (!NIL_P(tmp) && rb_enc_asciicompat(rb_enc_get(tmp))) {
9109 parse_mode_enc(RSTRING_PTR(tmp), &enc, &enc2, NULL);
9110 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
9111 ecflags = rb_econv_prepare_options(opt, &ecopts, ecflags);
9112 }
9113 else {
9114 rb_io_ext_int_to_encs(find_encoding(v1), NULL, &enc, &enc2, 0);
9115 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
9116 ecopts = Qnil;
9117 }
9118 }
9119 }
9120 validate_enc_binmode(&fptr->mode, ecflags, enc, enc2);
9121 fptr->encs.enc = enc;
9122 fptr->encs.enc2 = enc2;
9123 fptr->encs.ecflags = ecflags;
9124 fptr->encs.ecopts = ecopts;
9125 clear_codeconv(fptr);
9126
9127 }
9128
9129 static VALUE
9130 pipe_pair_close(VALUE rw)
9131 {
9132 VALUE *rwp = (VALUE *)rw;
9133 return rb_ensure(io_close, rwp[0], io_close, rwp[1]);
9134 }
9135
9136 /*
9137 * call-seq:
9138 * IO.pipe -> [read_io, write_io]
9139 * IO.pipe(ext_enc) -> [read_io, write_io]
9140 * IO.pipe("ext_enc:int_enc" [, opt]) -> [read_io, write_io]
9141 * IO.pipe(ext_enc, int_enc [, opt]) -> [read_io, write_io]
9142 *
9143 * IO.pipe(...) {|read_io, write_io| ... }
9144 *
9145 * Creates a pair of pipe endpoints (connected to each other) and
9146 * returns them as a two-element array of <code>IO</code> objects:
9147 * <code>[</code> <i>read_io</i>, <i>write_io</i> <code>]</code>.
9148 *
9149 * If a block is given, the block is called and
9150 * returns the value of the block.
9151 * <i>read_io</i> and <i>write_io</i> are sent to the block as arguments.
9152 * If read_io and write_io are not closed when the block exits, they are closed.
9153 * i.e. closing read_io and/or write_io doesn't cause an error.
9154 *
9155 * Not available on all platforms.
9156 *
9157 * If an encoding (encoding name or encoding object) is specified as an optional argument,
9158 * read string from pipe is tagged with the encoding specified.
9159 * If the argument is a colon separated two encoding names "A:B",
9160 * the read string is converted from encoding A (external encoding)
9161 * to encoding B (internal encoding), then tagged with B.
9162 * If two optional arguments are specified, those must be
9163 * encoding objects or encoding names,
9164 * and the first one is the external encoding,
9165 * and the second one is the internal encoding.
9166 * If the external encoding and the internal encoding is specified,
9167 * optional hash argument specify the conversion option.
9168 *
9169 * In the example below, the two processes close the ends of the pipe
9170 * that they are not using. This is not just a cosmetic nicety. The
9171 * read end of a pipe will not generate an end of file condition if
9172 * there are any writers with the pipe still open. In the case of the
9173 * parent process, the <code>rd.read</code> will never return if it
9174 * does not first issue a <code>wr.close</code>.
9175 *
9176 * rd, wr = IO.pipe
9177 *
9178 * if fork
9179 * wr.close
9180 * puts "Parent got: <#{rd.read}>"
9181 * rd.close
9182 * Process.wait
9183 * else
9184 * rd.close
9185 * puts "Sending message to parent"
9186 * wr.write "Hi Dad"
9187 * wr.close
9188 * end
9189 *
9190 * <em>produces:</em>
9191 *
9192 * Sending message to parent
9193 * Parent got: <Hi Dad>
9194 */
9195
9196 static VALUE
9197 rb_io_s_pipe(int argc, VALUE *argv, VALUE klass)
9198 {
9199 int pipes[2], state;
9200 VALUE r, w, args[3], v1, v2;
9201 VALUE opt;
9202 rb_io_t *fptr, *fptr2;
9203 int fmode = 0;
9204 VALUE ret;
9205
9206 argc = rb_scan_args(argc, argv, "02:", &v1, &v2, &opt);
9207 if (rb_pipe(pipes) == -1)
9208 rb_sys_fail(0);
9209
9210 args[0] = klass;
9211 args[1] = INT2NUM(pipes[0]);
9212 args[2] = INT2FIX(O_RDONLY);
9213 r = rb_protect(io_new_instance, (VALUE)args, &state);
9214 if (state) {
9215 close(pipes[0]);
9216 close(pipes[1]);
9217 rb_jump_tag(state);
9218 }
9219 GetOpenFile(r, fptr);
9220 io_encoding_set(fptr, v1, v2, opt);
9221 args[1] = INT2NUM(pipes[1]);
9222 args[2] = INT2FIX(O_WRONLY);
9223 w = rb_protect(io_new_instance, (VALUE)args, &state);
9224 if (state) {
9225 close(pipes[1]);
9226 if (!NIL_P(r)) rb_io_close(r);
9227 rb_jump_tag(state);
9228 }
9229 GetOpenFile(w, fptr2);
9230 rb_io_synchronized(fptr2);
9231
9232 extract_binmode(opt, &fmode);
9233 #if DEFAULT_TEXTMODE
9234 if ((fptr->mode & FMODE_TEXTMODE) && (fmode & FMODE_BINMODE)) {
9235 fptr->mode &= ~FMODE_TEXTMODE;
9236 setmode(fptr->fd, O_BINARY);
9237 }
9238 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
9239 if (fptr->encs.ecflags & ECONV_DEFAULT_NEWLINE_DECORATOR) {
9240 fptr->encs.ecflags |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;
9241 }
9242 #endif
9243 #endif
9244 fptr->mode |= fmode;
9245 #if DEFAULT_TEXTMODE
9246 if ((fptr2->mode & FMODE_TEXTMODE) && (fmode & FMODE_BINMODE)) {
9247 fptr2->mode &= ~FMODE_TEXTMODE;
9248 setmode(fptr2->fd, O_BINARY);
9249 }
9250 #endif
9251 fptr2->mode |= fmode;
9252
9253 ret = rb_assoc_new(r, w);
9254 if (rb_block_given_p()) {
9255 VALUE rw[2];
9256 rw[0] = r;
9257 rw[1] = w;
9258 return rb_ensure(rb_yield, ret, pipe_pair_close, (VALUE)rw);
9259 }
9260 return ret;
9261 }
9262
9263 struct foreach_arg {
9264 int argc;
9265 VALUE *argv;
9266 VALUE io;
9267 };
9268
9269 static void
9270 open_key_args(int argc, VALUE *argv, VALUE opt, struct foreach_arg *arg)
9271 {
9272 VALUE path, v;
9273
9274 path = *argv++;
9275 argc--;
9276 FilePathValue(path);
9277 arg->io = 0;
9278 arg->argc = argc;
9279 arg->argv = argv;
9280 if (NIL_P(opt)) {
9281 arg->io = rb_io_open(path, INT2NUM(O_RDONLY), INT2FIX(0666), Qnil);
9282 return;
9283 }
9284 v = rb_hash_aref(opt, sym_open_args);
9285 if (!NIL_P(v)) {
9286 VALUE args;
9287 long n;
9288
9289 v = rb_convert_type(v, T_ARRAY, "Array", "to_ary");
9290 n = RARRAY_LEN(v) + 1;
9291 #if SIZEOF_LONG > SIZEOF_INT
9292 if (n > INT_MAX) {
9293 rb_raise(rb_eArgError, "too many arguments");
9294 }
9295 #endif
9296 args = rb_ary_tmp_new(n);
9297 rb_ary_push(args, path);
9298 rb_ary_concat(args, v);
9299 arg->io = rb_io_open_with_args((int)n, RARRAY_PTR(args));
9300 rb_ary_clear(args); /* prevent from GC */
9301 return;
9302 }
9303 arg->io = rb_io_open(path, Qnil, Qnil, opt);
9304 }
9305
9306 static VALUE
9307 io_s_foreach(struct foreach_arg *arg)
9308 {
9309 VALUE str;
9310
9311 while (!NIL_P(str = rb_io_gets_m(arg->argc, arg->argv, arg->io))) {
9312 rb_yield(str);
9313 }
9314 return Qnil;
9315 }
9316
9317 /*
9318 * call-seq:
9319 * IO.foreach(name, sep=$/ [, open_args]) {|line| block } -> nil
9320 * IO.foreach(name, limit [, open_args]) {|line| block } -> nil
9321 * IO.foreach(name, sep, limit [, open_args]) {|line| block } -> nil
9322 * IO.foreach(...) -> an_enumerator
9323 *
9324 * Executes the block for every line in the named I/O port, where lines
9325 * are separated by <em>sep</em>.
9326 *
9327 * If no block is given, an enumerator is returned instead.
9328 *
9329 * IO.foreach("testfile") {|x| print "GOT ", x }
9330 *
9331 * <em>produces:</em>
9332 *
9333 * GOT This is line one
9334 * GOT This is line two
9335 * GOT This is line three
9336 * GOT And so on...
9337 *
9338 * If the last argument is a hash, it's the keyword argument to open.
9339 * See <code>IO.read</code> for detail.
9340 *
9341 */
9342
9343 static VALUE
9344 rb_io_s_foreach(int argc, VALUE *argv, VALUE self)
9345 {
9346 VALUE opt;
9347 int orig_argc = argc;
9348 struct foreach_arg arg;
9349
9350 argc = rb_scan_args(argc, argv, "13:", NULL, NULL, NULL, NULL, &opt);
9351 RETURN_ENUMERATOR(self, orig_argc, argv);
9352 open_key_args(argc, argv, opt, &arg);
9353 if (NIL_P(arg.io)) return Qnil;
9354 return rb_ensure(io_s_foreach, (VALUE)&arg, rb_io_close, arg.io);
9355 }
9356
9357 static VALUE
9358 io_s_readlines(struct foreach_arg *arg)
9359 {
9360 return rb_io_readlines(arg->argc, arg->argv, arg->io);
9361 }
9362
9363 /*
9364 * call-seq:
9365 * IO.readlines(name, sep=$/ [, open_args]) -> array
9366 * IO.readlines(name, limit [, open_args]) -> array
9367 * IO.readlines(name, sep, limit [, open_args]) -> array
9368 *
9369 * Reads the entire file specified by <i>name</i> as individual
9370 * lines, and returns those lines in an array. Lines are separated by
9371 * <i>sep</i>.
9372 *
9373 * a = IO.readlines("testfile")
9374 * a[0] #=> "This is line one\n"
9375 *
9376 * If the last argument is a hash, it's the keyword argument to open.
9377 * See <code>IO.read</code> for detail.
9378 *
9379 */
9380
9381 static VALUE
9382 rb_io_s_readlines(int argc, VALUE *argv, VALUE io)
9383 {
9384 VALUE opt;
9385 struct foreach_arg arg;
9386
9387 argc = rb_scan_args(argc, argv, "13:", NULL, NULL, NULL, NULL, &opt);
9388 open_key_args(argc, argv, opt, &arg);
9389 if (NIL_P(arg.io)) return Qnil;
9390 return rb_ensure(io_s_readlines, (VALUE)&arg, rb_io_close, arg.io);
9391 }
9392
9393 static VALUE
9394 io_s_read(struct foreach_arg *arg)
9395 {
9396 return io_read(arg->argc, arg->argv, arg->io);
9397 }
9398
9399 struct seek_arg {
9400 VALUE io;
9401 VALUE offset;
9402 int mode;
9403 };
9404
9405 static VALUE
9406 seek_before_access(VALUE argp)
9407 {
9408 struct seek_arg *arg = (struct seek_arg *)argp;
9409 rb_io_binmode(arg->io);
9410 return rb_io_seek(arg->io, arg->offset, arg->mode);
9411 }
9412
9413 /*
9414 * call-seq:
9415 * IO.read(name, [length [, offset]] ) -> string
9416 * IO.read(name, [length [, offset]], open_args) -> string
9417 *
9418 * Opens the file, optionally seeks to the given +offset+, then returns
9419 * +length+ bytes (defaulting to the rest of the file). <code>read</code>
9420 * ensures the file is closed before returning.
9421 *
9422 * If the last argument is a hash, it specifies option for internal
9423 * open(). The key would be the following. open_args: is exclusive
9424 * to others.
9425 *
9426 * encoding::
9427 * string or encoding
9428 *
9429 * specifies encoding of the read string. +encoding+ will be ignored
9430 * if length is specified.
9431 *
9432 * mode::
9433 * string
9434 *
9435 * specifies mode argument for open(). It should start with "r"
9436 * otherwise it will cause an error.
9437 *
9438 * open_args:: array of strings
9439 *
9440 * specifies arguments for open() as an array.
9441 *
9442 * Examples:
9443 *
9444 * IO.read("testfile") #=> "This is line one\nThis is line two\nThis is line three\nAnd so on...\n"
9445 * IO.read("testfile", 20) #=> "This is line one\nThi"
9446 * IO.read("testfile", 20, 10) #=> "ne one\nThis is line "
9447 */
9448
9449 static VALUE
9450 rb_io_s_read(int argc, VALUE *argv, VALUE io)
9451 {
9452 VALUE opt, offset;
9453 struct foreach_arg arg;
9454
9455 argc = rb_scan_args(argc, argv, "13:", NULL, NULL, &offset, NULL, &opt);
9456 open_key_args(argc, argv, opt, &arg);
9457 if (NIL_P(arg.io)) return Qnil;
9458 if (!NIL_P(offset)) {
9459 struct seek_arg sarg;
9460 int state = 0;
9461 sarg.io = arg.io;
9462 sarg.offset = offset;
9463 sarg.mode = SEEK_SET;
9464 rb_protect(seek_before_access, (VALUE)&sarg, &state);
9465 if (state) {
9466 rb_io_close(arg.io);
9467 rb_jump_tag(state);
9468 }
9469 if (arg.argc == 2) arg.argc = 1;
9470 }
9471 return rb_ensure(io_s_read, (VALUE)&arg, rb_io_close, arg.io);
9472 }
9473
9474 /*
9475 * call-seq:
9476 * IO.binread(name, [length [, offset]] ) -> string
9477 *
9478 * Opens the file, optionally seeks to the given <i>offset</i>, then returns
9479 * <i>length</i> bytes (defaulting to the rest of the file).
9480 * <code>binread</code> ensures the file is closed before returning.
9481 * The open mode would be "rb:ASCII-8BIT".
9482 *
9483 * IO.binread("testfile") #=> "This is line one\nThis is line two\nThis is line three\nAnd so on...\n"
9484 * IO.binread("testfile", 20) #=> "This is line one\nThi"
9485 * IO.binread("testfile", 20, 10) #=> "ne one\nThis is line "
9486 */
9487
9488 static VALUE
9489 rb_io_s_binread(int argc, VALUE *argv, VALUE io)
9490 {
9491 VALUE offset;
9492 struct foreach_arg arg;
9493
9494 rb_scan_args(argc, argv, "12", NULL, NULL, &offset);
9495 FilePathValue(argv[0]);
9496 arg.io = rb_io_open(argv[0], rb_str_new_cstr("rb:ASCII-8BIT"), Qnil, Qnil);
9497 if (NIL_P(arg.io)) return Qnil;
9498 arg.argv = argv+1;
9499 arg.argc = (argc > 1) ? 1 : 0;
9500 if (!NIL_P(offset)) {
9501 rb_io_seek(arg.io, offset, SEEK_SET);
9502 }
9503 return rb_ensure(io_s_read, (VALUE)&arg, rb_io_close, arg.io);
9504 }
9505
9506 static VALUE
9507 io_s_write0(struct write_arg *arg)
9508 {
9509 return io_write(arg->io,arg->str,arg->nosync);
9510 }
9511
9512 static VALUE
9513 io_s_write(int argc, VALUE *argv, int binary)
9514 {
9515 VALUE string, offset, opt;
9516 struct foreach_arg arg;
9517 struct write_arg warg;
9518
9519 rb_scan_args(argc, argv, "21:", NULL, &string, &offset, &opt);
9520
9521 if (NIL_P(opt)) opt = rb_hash_new();
9522 else opt = rb_hash_dup(opt);
9523
9524
9525 if (NIL_P(rb_hash_aref(opt,sym_mode))) {
9526 int mode = O_WRONLY|O_CREAT;
9527 #ifdef O_BINARY
9528 if (binary) mode |= O_BINARY;
9529 #endif
9530 if (NIL_P(offset)) mode |= O_TRUNC;
9531 rb_hash_aset(opt,sym_mode,INT2NUM(mode));
9532 }
9533 open_key_args(argc,argv,opt,&arg);
9534
9535 #ifndef O_BINARY
9536 if (binary) rb_io_binmode_m(arg.io);
9537 #endif
9538
9539 if (NIL_P(arg.io)) return Qnil;
9540 if (!NIL_P(offset)) {
9541 struct seek_arg sarg;
9542 int state = 0;
9543 sarg.io = arg.io;
9544 sarg.offset = offset;
9545 sarg.mode = SEEK_SET;
9546 rb_protect(seek_before_access, (VALUE)&sarg, &state);
9547 if (state) {
9548 rb_io_close(arg.io);
9549 rb_jump_tag(state);
9550 }
9551 }
9552
9553 warg.io = arg.io;
9554 warg.str = string;
9555 warg.nosync = 0;
9556
9557 return rb_ensure(io_s_write0, (VALUE)&warg, rb_io_close, arg.io);
9558 }
9559
9560 /*
9561 * call-seq:
9562 * IO.write(name, string, [offset] ) => fixnum
9563 * IO.write(name, string, [offset], open_args ) => fixnum
9564 *
9565 * Opens the file, optionally seeks to the given <i>offset</i>, writes
9566 * <i>string</i>, then returns the length written.
9567 * <code>write</code> ensures the file is closed before returning.
9568 * If <i>offset</i> is not given, the file is truncated. Otherwise,
9569 * it is not truncated.
9570 *
9571 * If the last argument is a hash, it specifies option for internal
9572 * open(). The key would be the following. open_args: is exclusive
9573 * to others.
9574 *
9575 * encoding: string or encoding
9576 *
9577 * specifies encoding of the read string. encoding will be ignored
9578 * if length is specified.
9579 *
9580 * mode: string
9581 *
9582 * specifies mode argument for open(). it should start with "w" or "a" or "r+"
9583 * otherwise it would cause error.
9584 *
9585 * perm: fixnum
9586 *
9587 * specifies perm argument for open().
9588 *
9589 * open_args: array
9590 *
9591 * specifies arguments for open() as an array.
9592 *
9593 * IO.write("testfile", "0123456789", 20) # => 10
9594 * # File could contain: "This is line one\nThi0123456789two\nThis is line three\nAnd so on...\n"
9595 * IO.write("testfile", "0123456789") #=> 10
9596 * # File would now read: "0123456789"
9597 */
9598
9599 static VALUE
9600 rb_io_s_write(int argc, VALUE *argv, VALUE io)
9601 {
9602 return io_s_write(argc, argv, 0);
9603 }
9604
9605 /*
9606 * call-seq:
9607 * IO.binwrite(name, string, [offset] ) => fixnum
9608 * IO.binwrite(name, string, [offset], open_args ) => fixnum
9609 *
9610 * Same as <code>IO.write</code> except opening the file in binary mode
9611 * and ASCII-8BIT encoding ("wb:ASCII-8BIT").
9612 *
9613 */
9614
9615 static VALUE
9616 rb_io_s_binwrite(int argc, VALUE *argv, VALUE io)
9617 {
9618 return io_s_write(argc, argv, 1);
9619 }
9620
9621 struct copy_stream_struct {
9622 VALUE src;
9623 VALUE dst;
9624 off_t copy_length; /* (off_t)-1 if not specified */
9625 off_t src_offset; /* (off_t)-1 if not specified */
9626
9627 int src_fd;
9628 int dst_fd;
9629 int close_src;
9630 int close_dst;
9631 off_t total;
9632 const char *syserr;
9633 int error_no;
9634 const char *notimp;
9635 rb_fdset_t fds;
9636 VALUE th;
9637 };
9638
9639 static void *
9640 exec_interrupts(void *arg)
9641 {
9642 VALUE th = (VALUE)arg;
9643 rb_thread_execute_interrupts(th);
9644 return NULL;
9645 }
9646
9647 /*
9648 * returns TRUE if the preceding system call was interrupted
9649 * so we can continue. If the thread was interrupted, we
9650 * reacquire the GVL to execute interrupts before continuing.
9651 */
9652 static int
9653 maygvl_copy_stream_continue_p(int has_gvl, struct copy_stream_struct *stp)
9654 {
9655 switch (errno) {
9656 case EINTR:
9657 #if defined(ERESTART)
9658 case ERESTART:
9659 #endif
9660 if (rb_thread_interrupted(stp->th)) {
9661 if (has_gvl)
9662 rb_thread_execute_interrupts(stp->th);
9663 else
9664 rb_thread_call_with_gvl(exec_interrupts, (void *)stp->th);
9665 }
9666 return TRUE;
9667 }
9668 return FALSE;
9669 }
9670
9671 static int
9672 maygvl_select(int has_gvl, int n, rb_fdset_t *rfds, rb_fdset_t *wfds, rb_fdset_t *efds, struct timeval *timeout)
9673 {
9674 if (has_gvl)
9675 return rb_thread_fd_select(n, rfds, wfds, efds, timeout);
9676 else
9677 return rb_fd_select(n, rfds, wfds, efds, timeout);
9678 }
9679
9680 static int
9681 maygvl_copy_stream_wait_read(int has_gvl, struct copy_stream_struct *stp)
9682 {
9683 int ret;
9684
9685 do {
9686 rb_fd_zero(&stp->fds);
9687 rb_fd_set(stp->src_fd, &stp->fds);
9688 ret = maygvl_select(has_gvl, rb_fd_max(&stp->fds), &stp->fds, NULL, NULL, NULL);
9689 } while (ret == -1 && maygvl_copy_stream_continue_p(has_gvl, stp));
9690
9691 if (ret == -1) {
9692 stp->syserr = "select";
9693 stp->error_no = errno;
9694 return -1;
9695 }
9696 return 0;
9697 }
9698
9699 static int
9700 nogvl_copy_stream_wait_write(struct copy_stream_struct *stp)
9701 {
9702 int ret;
9703
9704 do {
9705 rb_fd_zero(&stp->fds);
9706 rb_fd_set(stp->dst_fd, &stp->fds);
9707 ret = rb_fd_select(rb_fd_max(&stp->fds), NULL, &stp->fds, NULL, NULL);
9708 } while (ret == -1 && maygvl_copy_stream_continue_p(0, stp));
9709
9710 if (ret == -1) {
9711 stp->syserr = "select";
9712 stp->error_no = errno;
9713 return -1;
9714 }
9715 return 0;
9716 }
9717
9718 #ifdef HAVE_SENDFILE
9719
9720 # ifdef __linux__
9721 # define USE_SENDFILE
9722
9723 # ifdef HAVE_SYS_SENDFILE_H
9724 # include <sys/sendfile.h>
9725 # endif
9726
9727 static ssize_t
9728 simple_sendfile(int out_fd, int in_fd, off_t *offset, off_t count)
9729 {
9730 return sendfile(out_fd, in_fd, offset, (size_t)count);
9731 }
9732
9733 # elif 0 /* defined(__FreeBSD__) || defined(__DragonFly__) */ || defined(__APPLE__)
9734 /* This runs on FreeBSD8.1 r30210, but sendfiles blocks its execution
9735 * without cpuset -l 0.
9736 */
9737 # define USE_SENDFILE
9738
9739 # ifdef HAVE_SYS_UIO_H
9740 # include <sys/uio.h>
9741 # endif
9742
9743 static ssize_t
9744 simple_sendfile(int out_fd, int in_fd, off_t *offset, off_t count)
9745 {
9746 int r;
9747 off_t pos = offset ? *offset : lseek(in_fd, 0, SEEK_CUR);
9748 off_t sbytes;
9749 # ifdef __APPLE__
9750 r = sendfile(in_fd, out_fd, pos, &count, NULL, 0);
9751 sbytes = count;
9752 # else
9753 r = sendfile(in_fd, out_fd, pos, (size_t)count, NULL, &sbytes, 0);
9754 # endif
9755 if (r != 0 && sbytes == 0) return -1;
9756 if (offset) {
9757 *offset += sbytes;
9758 }
9759 else {
9760 lseek(in_fd, sbytes, SEEK_CUR);
9761 }
9762 return (ssize_t)sbytes;
9763 }
9764
9765 # endif
9766
9767 #endif
9768
9769 #ifdef USE_SENDFILE
9770 static int
9771 nogvl_copy_stream_sendfile(struct copy_stream_struct *stp)
9772 {
9773 struct stat src_stat, dst_stat;
9774 ssize_t ss;
9775 int ret;
9776
9777 off_t copy_length;
9778 off_t src_offset;
9779 int use_pread;
9780
9781 ret = fstat(stp->src_fd, &src_stat);
9782 if (ret == -1) {
9783 stp->syserr = "fstat";
9784 stp->error_no = errno;
9785 return -1;
9786 }
9787 if (!S_ISREG(src_stat.st_mode))
9788 return 0;
9789
9790 ret = fstat(stp->dst_fd, &dst_stat);
9791 if (ret == -1) {
9792 stp->syserr = "fstat";
9793 stp->error_no = errno;
9794 return -1;
9795 }
9796 if ((dst_stat.st_mode & S_IFMT) != S_IFSOCK)
9797 return 0;
9798
9799 src_offset = stp->src_offset;
9800 use_pread = src_offset != (off_t)-1;
9801
9802 copy_length = stp->copy_length;
9803 if (copy_length == (off_t)-1) {
9804 if (use_pread)
9805 copy_length = src_stat.st_size - src_offset;
9806 else {
9807 off_t cur;
9808 errno = 0;
9809 cur = lseek(stp->src_fd, 0, SEEK_CUR);
9810 if (cur == (off_t)-1 && errno) {
9811 stp->syserr = "lseek";
9812 stp->error_no = errno;
9813 return -1;
9814 }
9815 copy_length = src_stat.st_size - cur;
9816 }
9817 }
9818
9819 retry_sendfile:
9820 # if SIZEOF_OFF_T > SIZEOF_SIZE_T
9821 /* we are limited by the 32-bit ssize_t return value on 32-bit */
9822 ss = (copy_length > (off_t)SSIZE_MAX) ? SSIZE_MAX : (ssize_t)copy_length;
9823 # else
9824 ss = (ssize_t)copy_length;
9825 # endif
9826 if (use_pread) {
9827 ss = simple_sendfile(stp->dst_fd, stp->src_fd, &src_offset, ss);
9828 }
9829 else {
9830 ss = simple_sendfile(stp->dst_fd, stp->src_fd, NULL, ss);
9831 }
9832 if (0 < ss) {
9833 stp->total += ss;
9834 copy_length -= ss;
9835 if (0 < copy_length) {
9836 goto retry_sendfile;
9837 }
9838 }
9839 if (ss == -1) {
9840 if (maygvl_copy_stream_continue_p(0, stp))
9841 goto retry_sendfile;
9842 switch (errno) {
9843 case EINVAL:
9844 #ifdef ENOSYS
9845 case ENOSYS:
9846 #endif
9847 return 0;
9848 case EAGAIN:
9849 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
9850 case EWOULDBLOCK:
9851 #endif
9852 #ifndef __linux__
9853 /*
9854 * Linux requires stp->src_fd to be a mmap-able (regular) file,
9855 * select() reports regular files to always be "ready", so
9856 * there is no need to select() on it.
9857 * Other OSes may have the same limitation for sendfile() which
9858 * allow us to bypass maygvl_copy_stream_wait_read()...
9859 */
9860 if (maygvl_copy_stream_wait_read(0, stp) == -1)
9861 return -1;
9862 #endif
9863 if (nogvl_copy_stream_wait_write(stp) == -1)
9864 return -1;
9865 goto retry_sendfile;
9866 }
9867 stp->syserr = "sendfile";
9868 stp->error_no = errno;
9869 return -1;
9870 }
9871 return 1;
9872 }
9873 #endif
9874
9875 static ssize_t
9876 maygvl_read(int has_gvl, int fd, void *buf, size_t count)
9877 {
9878 if (has_gvl)
9879 return rb_read_internal(fd, buf, count);
9880 else
9881 return read(fd, buf, count);
9882 }
9883
9884 static ssize_t
9885 maygvl_copy_stream_read(int has_gvl, struct copy_stream_struct *stp, char *buf, size_t len, off_t offset)
9886 {
9887 ssize_t ss;
9888 retry_read:
9889 if (offset == (off_t)-1) {
9890 ss = maygvl_read(has_gvl, stp->src_fd, buf, len);
9891 }
9892 else {
9893 #ifdef HAVE_PREAD
9894 ss = pread(stp->src_fd, buf, len, offset);
9895 #else
9896 stp->notimp = "pread";
9897 return -1;
9898 #endif
9899 }
9900 if (ss == 0) {
9901 return 0;
9902 }
9903 if (ss == -1) {
9904 if (maygvl_copy_stream_continue_p(has_gvl, stp))
9905 goto retry_read;
9906 switch (errno) {
9907 case EAGAIN:
9908 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
9909 case EWOULDBLOCK:
9910 #endif
9911 if (maygvl_copy_stream_wait_read(has_gvl, stp) == -1)
9912 return -1;
9913 goto retry_read;
9914 #ifdef ENOSYS
9915 case ENOSYS:
9916 #endif
9917 stp->notimp = "pread";
9918 return -1;
9919 }
9920 stp->syserr = offset == (off_t)-1 ? "read" : "pread";
9921 stp->error_no = errno;
9922 return -1;
9923 }
9924 return ss;
9925 }
9926
9927 static int
9928 nogvl_copy_stream_write(struct copy_stream_struct *stp, char *buf, size_t len)
9929 {
9930 ssize_t ss;
9931 int off = 0;
9932 while (len) {
9933 ss = write(stp->dst_fd, buf+off, len);
9934 if (ss == -1) {
9935 if (maygvl_copy_stream_continue_p(0, stp))
9936 continue;
9937 if (errno == EAGAIN || errno == EWOULDBLOCK) {
9938 if (nogvl_copy_stream_wait_write(stp) == -1)
9939 return -1;
9940 continue;
9941 }
9942 stp->syserr = "write";
9943 stp->error_no = errno;
9944 return -1;
9945 }
9946 off += (int)ss;
9947 len -= (int)ss;
9948 stp->total += ss;
9949 }
9950 return 0;
9951 }
9952
9953 static void
9954 nogvl_copy_stream_read_write(struct copy_stream_struct *stp)
9955 {
9956 char buf[1024*16];
9957 size_t len;
9958 ssize_t ss;
9959 int ret;
9960 off_t copy_length;
9961 int use_eof;
9962 off_t src_offset;
9963 int use_pread;
9964
9965 copy_length = stp->copy_length;
9966 use_eof = copy_length == (off_t)-1;
9967 src_offset = stp->src_offset;
9968 use_pread = src_offset != (off_t)-1;
9969
9970 if (use_pread && stp->close_src) {
9971 off_t r;
9972 errno = 0;
9973 r = lseek(stp->src_fd, src_offset, SEEK_SET);
9974 if (r == (off_t)-1 && errno) {
9975 stp->syserr = "lseek";
9976 stp->error_no = errno;
9977 return;
9978 }
9979 src_offset = (off_t)-1;
9980 use_pread = 0;
9981 }
9982
9983 while (use_eof || 0 < copy_length) {
9984 if (!use_eof && copy_length < (off_t)sizeof(buf)) {
9985 len = (size_t)copy_length;
9986 }
9987 else {
9988 len = sizeof(buf);
9989 }
9990 if (use_pread) {
9991 ss = maygvl_copy_stream_read(0, stp, buf, len, src_offset);
9992 if (0 < ss)
9993 src_offset += ss;
9994 }
9995 else {
9996 ss = maygvl_copy_stream_read(0, stp, buf, len, (off_t)-1);
9997 }
9998 if (ss <= 0) /* EOF or error */
9999 return;
10000
10001 ret = nogvl_copy_stream_write(stp, buf, ss);
10002 if (ret < 0)
10003 return;
10004
10005 if (!use_eof)
10006 copy_length -= ss;
10007 }
10008 }
10009
10010 static void *
10011 nogvl_copy_stream_func(void *arg)
10012 {
10013 struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
10014 #ifdef USE_SENDFILE
10015 int ret;
10016 #endif
10017
10018 #ifdef USE_SENDFILE
10019 ret = nogvl_copy_stream_sendfile(stp);
10020 if (ret != 0)
10021 goto finish; /* error or success */
10022 #endif
10023
10024 nogvl_copy_stream_read_write(stp);
10025
10026 #ifdef USE_SENDFILE
10027 finish:
10028 #endif
10029 return 0;
10030 }
10031
10032 static VALUE
10033 copy_stream_fallback_body(VALUE arg)
10034 {
10035 struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
10036 const int buflen = 16*1024;
10037 VALUE n;
10038 VALUE buf = rb_str_buf_new(buflen);
10039 off_t rest = stp->copy_length;
10040 off_t off = stp->src_offset;
10041 ID read_method = id_readpartial;
10042
10043 if (stp->src_fd == -1) {
10044 if (!rb_respond_to(stp->src, read_method)) {
10045 read_method = id_read;
10046 }
10047 }
10048
10049 while (1) {
10050 long numwrote;
10051 long l;
10052 if (stp->copy_length == (off_t)-1) {
10053 l = buflen;
10054 }
10055 else {
10056 if (rest == 0)
10057 break;
10058 l = buflen < rest ? buflen : (long)rest;
10059 }
10060 if (stp->src_fd == -1) {
10061 VALUE rc = rb_funcall(stp->src, read_method, 2, INT2FIX(l), buf);
10062
10063 if (read_method == id_read && NIL_P(rc))
10064 break;
10065 }
10066 else {
10067 ssize_t ss;
10068 rb_str_resize(buf, buflen);
10069 ss = maygvl_copy_stream_read(1, stp, RSTRING_PTR(buf), l, off);
10070 if (ss == -1)
10071 return Qnil;
10072 if (ss == 0)
10073 rb_eof_error();
10074 rb_str_resize(buf, ss);
10075 if (off != (off_t)-1)
10076 off += ss;
10077 }
10078 n = rb_io_write(stp->dst, buf);
10079 numwrote = NUM2LONG(n);
10080 stp->total += numwrote;
10081 rest -= numwrote;
10082 if (read_method == id_read && RSTRING_LEN(buf) == 0) {
10083 break;
10084 }
10085 }
10086
10087 return Qnil;
10088 }
10089
10090 static VALUE
10091 copy_stream_fallback(struct copy_stream_struct *stp)
10092 {
10093 if (stp->src_fd == -1 && stp->src_offset != (off_t)-1) {
10094 rb_raise(rb_eArgError, "cannot specify src_offset for non-IO");
10095 }
10096 rb_rescue2(copy_stream_fallback_body, (VALUE)stp,
10097 (VALUE (*) (ANYARGS))0, (VALUE)0,
10098 rb_eEOFError, (VALUE)0);
10099 return Qnil;
10100 }
10101
10102 static VALUE
10103 copy_stream_body(VALUE arg)
10104 {
10105 struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
10106 VALUE src_io, dst_io;
10107 rb_io_t *src_fptr = 0, *dst_fptr = 0;
10108 int src_fd, dst_fd;
10109
10110 stp->th = rb_thread_current();
10111
10112 stp->total = 0;
10113
10114 if (stp->src == argf ||
10115 !(RB_TYPE_P(stp->src, T_FILE) ||
10116 RB_TYPE_P(stp->src, T_STRING) ||
10117 rb_respond_to(stp->src, rb_intern("to_path")))) {
10118 src_fd = -1;
10119 }
10120 else {
10121 src_io = RB_TYPE_P(stp->src, T_FILE) ? stp->src : Qnil;
10122 if (NIL_P(src_io)) {
10123 VALUE args[2];
10124 int oflags = O_RDONLY;
10125 #ifdef O_NOCTTY
10126 oflags |= O_NOCTTY;
10127 #endif
10128 FilePathValue(stp->src);
10129 args[0] = stp->src;
10130 args[1] = INT2NUM(oflags);
10131 src_io = rb_class_new_instance(2, args, rb_cFile);
10132 stp->src = src_io;
10133 stp->close_src = 1;
10134 }
10135 GetOpenFile(src_io, src_fptr);
10136 rb_io_check_byte_readable(src_fptr);
10137 src_fd = src_fptr->fd;
10138 }
10139 stp->src_fd = src_fd;
10140
10141 if (stp->dst == argf ||
10142 !(RB_TYPE_P(stp->dst, T_FILE) ||
10143 RB_TYPE_P(stp->dst, T_STRING) ||
10144 rb_respond_to(stp->dst, rb_intern("to_path")))) {
10145 dst_fd = -1;
10146 }
10147 else {
10148 dst_io = RB_TYPE_P(stp->dst, T_FILE) ? stp->dst : Qnil;
10149 if (NIL_P(dst_io)) {
10150 VALUE args[3];
10151 int oflags = O_WRONLY|O_CREAT|O_TRUNC;
10152 #ifdef O_NOCTTY
10153 oflags |= O_NOCTTY;
10154 #endif
10155 FilePathValue(stp->dst);
10156 args[0] = stp->dst;
10157 args[1] = INT2NUM(oflags);
10158 args[2] = INT2FIX(0666);
10159 dst_io = rb_class_new_instance(3, args, rb_cFile);
10160 stp->dst = dst_io;
10161 stp->close_dst = 1;
10162 }
10163 else {
10164 dst_io = GetWriteIO(dst_io);
10165 stp->dst = dst_io;
10166 }
10167 GetOpenFile(dst_io, dst_fptr);
10168 rb_io_check_writable(dst_fptr);
10169 dst_fd = dst_fptr->fd;
10170 }
10171 stp->dst_fd = dst_fd;
10172
10173 #ifdef O_BINARY
10174 if (src_fptr)
10175 SET_BINARY_MODE_WITH_SEEK_CUR(src_fptr);
10176 if (dst_fptr)
10177 setmode(dst_fd, O_BINARY);
10178 #endif
10179
10180 if (stp->src_offset == (off_t)-1 && src_fptr && src_fptr->rbuf.len) {
10181 size_t len = src_fptr->rbuf.len;
10182 VALUE str;
10183 if (stp->copy_length != (off_t)-1 && stp->copy_length < (off_t)len) {
10184 len = (size_t)stp->copy_length;
10185 }
10186 str = rb_str_buf_new(len);
10187 rb_str_resize(str,len);
10188 read_buffered_data(RSTRING_PTR(str), len, src_fptr);
10189 if (dst_fptr) { /* IO or filename */
10190 if (io_binwrite(str, RSTRING_PTR(str), RSTRING_LEN(str), dst_fptr, 0) < 0)
10191 rb_sys_fail(0);
10192 }
10193 else /* others such as StringIO */
10194 rb_io_write(stp->dst, str);
10195 stp->total += len;
10196 if (stp->copy_length != (off_t)-1)
10197 stp->copy_length -= len;
10198 }
10199
10200 if (dst_fptr && io_fflush(dst_fptr) < 0) {
10201 rb_raise(rb_eIOError, "flush failed");
10202 }
10203
10204 if (stp->copy_length == 0)
10205 return Qnil;
10206
10207 if (src_fd == -1 || dst_fd == -1) {
10208 return copy_stream_fallback(stp);
10209 }
10210
10211 rb_fd_set(src_fd, &stp->fds);
10212 rb_fd_set(dst_fd, &stp->fds);
10213
10214 rb_thread_call_without_gvl(nogvl_copy_stream_func, (void*)stp, RUBY_UBF_IO, 0);
10215 return Qnil;
10216 }
10217
10218 static VALUE
10219 copy_stream_finalize(VALUE arg)
10220 {
10221 struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
10222 if (stp->close_src) {
10223 rb_io_close_m(stp->src);
10224 }
10225 if (stp->close_dst) {
10226 rb_io_close_m(stp->dst);
10227 }
10228 rb_fd_term(&stp->fds);
10229 if (stp->syserr) {
10230 errno = stp->error_no;
10231 rb_sys_fail(stp->syserr);
10232 }
10233 if (stp->notimp) {
10234 rb_raise(rb_eNotImpError, "%s() not implemented", stp->notimp);
10235 }
10236 return Qnil;
10237 }
10238
10239 /*
10240 * call-seq:
10241 * IO.copy_stream(src, dst)
10242 * IO.copy_stream(src, dst, copy_length)
10243 * IO.copy_stream(src, dst, copy_length, src_offset)
10244 *
10245 * IO.copy_stream copies <i>src</i> to <i>dst</i>.
10246 * <i>src</i> and <i>dst</i> is either a filename or an IO.
10247 *
10248 * This method returns the number of bytes copied.
10249 *
10250 * If optional arguments are not given,
10251 * the start position of the copy is
10252 * the beginning of the filename or
10253 * the current file offset of the IO.
10254 * The end position of the copy is the end of file.
10255 *
10256 * If <i>copy_length</i> is given,
10257 * No more than <i>copy_length</i> bytes are copied.
10258 *
10259 * If <i>src_offset</i> is given,
10260 * it specifies the start position of the copy.
10261 *
10262 * When <i>src_offset</i> is specified and
10263 * <i>src</i> is an IO,
10264 * IO.copy_stream doesn't move the current file offset.
10265 *
10266 */
10267 static VALUE
10268 rb_io_s_copy_stream(int argc, VALUE *argv, VALUE io)
10269 {
10270 VALUE src, dst, length, src_offset;
10271 struct copy_stream_struct st;
10272
10273 MEMZERO(&st, struct copy_stream_struct, 1);
10274
10275 rb_scan_args(argc, argv, "22", &src, &dst, &length, &src_offset);
10276
10277 st.src = src;
10278 st.dst = dst;
10279
10280 if (NIL_P(length))
10281 st.copy_length = (off_t)-1;
10282 else
10283 st.copy_length = NUM2OFFT(length);
10284
10285 if (NIL_P(src_offset))
10286 st.src_offset = (off_t)-1;
10287 else
10288 st.src_offset = NUM2OFFT(src_offset);
10289
10290 rb_fd_init(&st.fds);
10291 rb_ensure(copy_stream_body, (VALUE)&st, copy_stream_finalize, (VALUE)&st);
10292
10293 return OFFT2NUM(st.total);
10294 }
10295
10296 /*
10297 * call-seq:
10298 * io.external_encoding -> encoding
10299 *
10300 * Returns the Encoding object that represents the encoding of the file.
10301 * If io is write mode and no encoding is specified, returns <code>nil</code>.
10302 */
10303
10304 static VALUE
10305 rb_io_external_encoding(VALUE io)
10306 {
10307 rb_io_t *fptr;
10308
10309 GetOpenFile(io, fptr);
10310 if (fptr->encs.enc2) {
10311 return rb_enc_from_encoding(fptr->encs.enc2);
10312 }
10313 if (fptr->mode & FMODE_WRITABLE) {
10314 if (fptr->encs.enc)
10315 return rb_enc_from_encoding(fptr->encs.enc);
10316 return Qnil;
10317 }
10318 return rb_enc_from_encoding(io_read_encoding(fptr));
10319 }
10320
10321 /*
10322 * call-seq:
10323 * io.internal_encoding -> encoding
10324 *
10325 * Returns the Encoding of the internal string if conversion is
10326 * specified. Otherwise returns nil.
10327 */
10328
10329 static VALUE
10330 rb_io_internal_encoding(VALUE io)
10331 {
10332 rb_io_t *fptr;
10333
10334 GetOpenFile(io, fptr);
10335 if (!fptr->encs.enc2) return Qnil;
10336 return rb_enc_from_encoding(io_read_encoding(fptr));
10337 }
10338
10339 /*
10340 * call-seq:
10341 * io.set_encoding(ext_enc) -> io
10342 * io.set_encoding("ext_enc:int_enc") -> io
10343 * io.set_encoding(ext_enc, int_enc) -> io
10344 * io.set_encoding("ext_enc:int_enc", opt) -> io
10345 * io.set_encoding(ext_enc, int_enc, opt) -> io
10346 *
10347 * If single argument is specified, read string from io is tagged
10348 * with the encoding specified. If encoding is a colon separated two
10349 * encoding names "A:B", the read string is converted from encoding A
10350 * (external encoding) to encoding B (internal encoding), then tagged
10351 * with B. If two arguments are specified, those must be encoding
10352 * objects or encoding names, and the first one is the external encoding, and the
10353 * second one is the internal encoding.
10354 * If the external encoding and the internal encoding is specified,
10355 * optional hash argument specify the conversion option.
10356 */
10357
10358 static VALUE
10359 rb_io_set_encoding(int argc, VALUE *argv, VALUE io)
10360 {
10361 rb_io_t *fptr;
10362 VALUE v1, v2, opt;
10363
10364 if (!RB_TYPE_P(io, T_FILE)) {
10365 return rb_funcall2(io, id_set_encoding, argc, argv);
10366 }
10367
10368 argc = rb_scan_args(argc, argv, "11:", &v1, &v2, &opt);
10369 GetOpenFile(io, fptr);
10370 io_encoding_set(fptr, v1, v2, opt);
10371 return io;
10372 }
10373
10374 void
10375 rb_stdio_set_default_encoding(void)
10376 {
10377 extern VALUE rb_stdin, rb_stdout, rb_stderr;
10378 VALUE val = Qnil;
10379
10380 rb_io_set_encoding(1, &val, rb_stdin);
10381 rb_io_set_encoding(1, &val, rb_stdout);
10382 rb_io_set_encoding(1, &val, rb_stderr);
10383 }
10384
10385 /*
10386 * call-seq:
10387 * ARGF.external_encoding -> encoding
10388 *
10389 * Returns the external encoding for files read from +ARGF+ as an +Encoding+
10390 * object. The external encoding is the encoding of the text as stored in a
10391 * file. Contrast with +ARGF.internal_encoding+, which is the encoding used
10392 * to represent this text within Ruby.
10393 *
10394 * To set the external encoding use +ARGF.set_encoding+.
10395 *
10396 * For example:
10397 *
10398 * ARGF.external_encoding #=> #<Encoding:UTF-8>
10399 *
10400 */
10401 static VALUE
10402 argf_external_encoding(VALUE argf)
10403 {
10404 if (!RTEST(ARGF.current_file)) {
10405 return rb_enc_from_encoding(rb_default_external_encoding());
10406 }
10407 return rb_io_external_encoding(rb_io_check_io(ARGF.current_file));
10408 }
10409
10410 /*
10411 * call-seq:
10412 * ARGF.internal_encoding -> encoding
10413 *
10414 * Returns the internal encoding for strings read from +ARGF+ as an
10415 * +Encoding+ object.
10416 *
10417 * If +ARGF.set_encoding+ has been called with two encoding names, the second
10418 * is returned. Otherwise, if +Encoding.default_external+ has been set, that
10419 * value is returned. Failing that, if a default external encoding was
10420 * specified on the command-line, that value is used. If the encoding is
10421 * unknown, nil is returned.
10422 */
10423 static VALUE
10424 argf_internal_encoding(VALUE argf)
10425 {
10426 if (!RTEST(ARGF.current_file)) {
10427 return rb_enc_from_encoding(rb_default_external_encoding());
10428 }
10429 return rb_io_internal_encoding(rb_io_check_io(ARGF.current_file));
10430 }
10431
10432 /*
10433 * call-seq:
10434 * ARGF.set_encoding(ext_enc) -> ARGF
10435 * ARGF.set_encoding("ext_enc:int_enc") -> ARGF
10436 * ARGF.set_encoding(ext_enc, int_enc) -> ARGF
10437 * ARGF.set_encoding("ext_enc:int_enc", opt) -> ARGF
10438 * ARGF.set_encoding(ext_enc, int_enc, opt) -> ARGF
10439 *
10440 * If single argument is specified, strings read from ARGF are tagged with
10441 * the encoding specified.
10442 *
10443 * If two encoding names separated by a colon are given, e.g. "ascii:utf-8",
10444 * the read string is converted from the first encoding (external encoding)
10445 * to the second encoding (internal encoding), then tagged with the second
10446 * encoding.
10447 *
10448 * If two arguments are specified, they must be encoding objects or encoding
10449 * names. Again, the first specifies the external encoding; the second
10450 * specifies the internal encoding.
10451 *
10452 * If the external encoding and the internal encoding are specified, the
10453 * optional +Hash+ argument can be used to adjust the conversion process. The
10454 * structure of this hash is explained in the +String#encode+ documentation.
10455 *
10456 * For example:
10457 *
10458 * ARGF.set_encoding('ascii') # Tag the input as US-ASCII text
10459 * ARGF.set_encoding(Encoding::UTF_8) # Tag the input as UTF-8 text
10460 * ARGF.set_encoding('utf-8','ascii') # Transcode the input from US-ASCII
10461 * # to UTF-8.
10462 */
10463 static VALUE
10464 argf_set_encoding(int argc, VALUE *argv, VALUE argf)
10465 {
10466 rb_io_t *fptr;
10467
10468 if (!next_argv()) {
10469 rb_raise(rb_eArgError, "no stream to set encoding");
10470 }
10471 rb_io_set_encoding(argc, argv, ARGF.current_file);
10472 GetOpenFile(ARGF.current_file, fptr);
10473 ARGF.encs = fptr->encs;
10474 return argf;
10475 }
10476
10477 /*
10478 * call-seq:
10479 * ARGF.tell -> Integer
10480 * ARGF.pos -> Integer
10481 *
10482 * Returns the current offset (in bytes) of the current file in +ARGF+.
10483 *
10484 * ARGF.pos #=> 0
10485 * ARGF.gets #=> "This is line one\n"
10486 * ARGF.pos #=> 17
10487 *
10488 */
10489 static VALUE
10490 argf_tell(VALUE argf)
10491 {
10492 if (!next_argv()) {
10493 rb_raise(rb_eArgError, "no stream to tell");
10494 }
10495 ARGF_FORWARD(0, 0);
10496 return rb_io_tell(ARGF.current_file);
10497 }
10498
10499 /*
10500 * call-seq:
10501 * ARGF.seek(amount, whence=IO::SEEK_SET) -> 0
10502 *
10503 * Seeks to offset _amount_ (an +Integer+) in the +ARGF+ stream according to
10504 * the value of _whence_. See +IO#seek+ for further details.
10505 */
10506 static VALUE
10507 argf_seek_m(int argc, VALUE *argv, VALUE argf)
10508 {
10509 if (!next_argv()) {
10510 rb_raise(rb_eArgError, "no stream to seek");
10511 }
10512 ARGF_FORWARD(argc, argv);
10513 return rb_io_seek_m(argc, argv, ARGF.current_file);
10514 }
10515
10516 /*
10517 * call-seq:
10518 * ARGF.pos = position -> Integer
10519 *
10520 * Seeks to the position given by _position_ (in bytes) in +ARGF+.
10521 *
10522 * For example:
10523 *
10524 * ARGF.pos = 17
10525 * ARGF.gets #=> "This is line two\n"
10526 */
10527 static VALUE
10528 argf_set_pos(VALUE argf, VALUE offset)
10529 {
10530 if (!next_argv()) {
10531 rb_raise(rb_eArgError, "no stream to set position");
10532 }
10533 ARGF_FORWARD(1, &offset);
10534 return rb_io_set_pos(ARGF.current_file, offset);
10535 }
10536
10537 /*
10538 * call-seq:
10539 * ARGF.rewind -> 0
10540 *
10541 * Positions the current file to the beginning of input, resetting
10542 * +ARGF.lineno+ to zero.
10543 *
10544 * ARGF.readline #=> "This is line one\n"
10545 * ARGF.rewind #=> 0
10546 * ARGF.lineno #=> 0
10547 * ARGF.readline #=> "This is line one\n"
10548 */
10549 static VALUE
10550 argf_rewind(VALUE argf)
10551 {
10552 if (!next_argv()) {
10553 rb_raise(rb_eArgError, "no stream to rewind");
10554 }
10555 ARGF_FORWARD(0, 0);
10556 return rb_io_rewind(ARGF.current_file);
10557 }
10558
10559 /*
10560 * call-seq:
10561 * ARGF.fileno -> fixnum
10562 * ARGF.to_i -> fixnum
10563 *
10564 * Returns an integer representing the numeric file descriptor for
10565 * the current file. Raises an +ArgumentError+ if there isn't a current file.
10566 *
10567 * ARGF.fileno #=> 3
10568 */
10569 static VALUE
10570 argf_fileno(VALUE argf)
10571 {
10572 if (!next_argv()) {
10573 rb_raise(rb_eArgError, "no stream");
10574 }
10575 ARGF_FORWARD(0, 0);
10576 return rb_io_fileno(ARGF.current_file);
10577 }
10578
10579 /*
10580 * call-seq:
10581 * ARGF.to_io -> IO
10582 *
10583 * Returns an +IO+ object representing the current file. This will be a
10584 * +File+ object unless the current file is a stream such as STDIN.
10585 *
10586 * For example:
10587 *
10588 * ARGF.to_io #=> #<File:glark.txt>
10589 * ARGF.to_io #=> #<IO:<STDIN>>
10590 */
10591 static VALUE
10592 argf_to_io(VALUE argf)
10593 {
10594 next_argv();
10595 ARGF_FORWARD(0, 0);
10596 return ARGF.current_file;
10597 }
10598
10599 /*
10600 * call-seq:
10601 * ARGF.eof? -> true or false
10602 * ARGF.eof -> true or false
10603 *
10604 * Returns true if the current file in +ARGF+ is at end of file, i.e. it has
10605 * no data to read. The stream must be opened for reading or an +IOError+
10606 * will be raised.
10607 *
10608 * $ echo "eof" | ruby argf.rb
10609 *
10610 * ARGF.eof? #=> false
10611 * 3.times { ARGF.readchar }
10612 * ARGF.eof? #=> false
10613 * ARGF.readchar #=> "\n"
10614 * ARGF.eof? #=> true
10615 */
10616
10617 static VALUE
10618 argf_eof(VALUE argf)
10619 {
10620 next_argv();
10621 if (RTEST(ARGF.current_file)) {
10622 if (ARGF.init_p == 0) return Qtrue;
10623 next_argv();
10624 ARGF_FORWARD(0, 0);
10625 if (rb_io_eof(ARGF.current_file)) {
10626 return Qtrue;
10627 }
10628 }
10629 return Qfalse;
10630 }
10631
10632 /*
10633 * call-seq:
10634 * ARGF.read([length [, outbuf]]) -> string, outbuf, or nil
10635 *
10636 * Reads _length_ bytes from ARGF. The files named on the command line
10637 * are concatenated and treated as a single file by this method, so when
10638 * called without arguments the contents of this pseudo file are returned in
10639 * their entirety.
10640 *
10641 * _length_ must be a non-negative integer or nil. If it is a positive
10642 * integer, +read+ tries to read at most _length_ bytes. It returns nil
10643 * if an EOF was encountered before anything could be read. Fewer than
10644 * _length_ bytes may be returned if an EOF is encountered during the read.
10645 *
10646 * If _length_ is omitted or is _nil_, it reads until EOF. A String is
10647 * returned even if EOF is encountered before any data is read.
10648 *
10649 * If _length_ is zero, it returns _""_.
10650 *
10651 * If the optional _outbuf_ argument is present, it must reference a String,
10652 * which will receive the data.
10653 * The <i>outbuf</i> will contain only the received data after the method call
10654 * even if it is not empty at the beginning.
10655 *
10656 * For example:
10657 *
10658 * $ echo "small" > small.txt
10659 * $ echo "large" > large.txt
10660 * $ ./glark.rb small.txt large.txt
10661 *
10662 * ARGF.read #=> "small\nlarge"
10663 * ARGF.read(200) #=> "small\nlarge"
10664 * ARGF.read(2) #=> "sm"
10665 * ARGF.read(0) #=> ""
10666 *
10667 * Note that this method behaves like fread() function in C. If you need the
10668 * behavior like read(2) system call, consider +ARGF.readpartial+.
10669 */
10670
10671 static VALUE
10672 argf_read(int argc, VALUE *argv, VALUE argf)
10673 {
10674 VALUE tmp, str, length;
10675 long len = 0;
10676
10677 rb_scan_args(argc, argv, "02", &length, &str);
10678 if (!NIL_P(length)) {
10679 len = NUM2LONG(argv[0]);
10680 }
10681 if (!NIL_P(str)) {
10682 StringValue(str);
10683 rb_str_resize(str,0);
10684 argv[1] = Qnil;
10685 }
10686
10687 retry:
10688 if (!next_argv()) {
10689 return str;
10690 }
10691 if (ARGF_GENERIC_INPUT_P()) {
10692 tmp = argf_forward(argc, argv, argf);
10693 }
10694 else {
10695 tmp = io_read(argc, argv, ARGF.current_file);
10696 }
10697 if (NIL_P(str)) str = tmp;
10698 else if (!NIL_P(tmp)) rb_str_append(str, tmp);
10699 if (NIL_P(tmp) || NIL_P(length)) {
10700 if (ARGF.next_p != -1) {
10701 argf_close(ARGF.current_file);
10702 ARGF.next_p = 1;
10703 goto retry;
10704 }
10705 }
10706 else if (argc >= 1) {
10707 if (RSTRING_LEN(str) < len) {
10708 len -= RSTRING_LEN(str);
10709 argv[0] = INT2NUM(len);
10710 goto retry;
10711 }
10712 }
10713 return str;
10714 }
10715
10716 struct argf_call_arg {
10717 int argc;
10718 VALUE *argv;
10719 VALUE argf;
10720 };
10721
10722 static VALUE
10723 argf_forward_call(VALUE arg)
10724 {
10725 struct argf_call_arg *p = (struct argf_call_arg *)arg;
10726 argf_forward(p->argc, p->argv, p->argf);
10727 return Qnil;
10728 }
10729
10730 static VALUE argf_getpartial(int argc, VALUE *argv, VALUE argf, int nonblock);
10731
10732 /*
10733 * call-seq:
10734 * ARGF.readpartial(maxlen) -> string
10735 * ARGF.readpartial(maxlen, outbuf) -> outbuf
10736 *
10737 * Reads at most _maxlen_ bytes from the ARGF stream. It blocks only if
10738 * +ARGF+ has no data immediately available. If the optional _outbuf_
10739 * argument is present, it must reference a String, which will receive the
10740 * data.
10741 * The <i>outbuf</i> will contain only the received data after the method call
10742 * even if it is not empty at the beginning.
10743 * It raises <code>EOFError</code> on end of file.
10744 *
10745 * +readpartial+ is designed for streams such as pipes, sockets, and ttys. It
10746 * blocks only when no data is immediately available. This means that it
10747 * blocks only when following all conditions hold:
10748 *
10749 * * The byte buffer in the +IO+ object is empty.
10750 * * The content of the stream is empty.
10751 * * The stream has not reached EOF.
10752 *
10753 * When +readpartial+ blocks, it waits for data or EOF. If some data is read,
10754 * +readpartial+ returns with the data. If EOF is reached, readpartial raises
10755 * an +EOFError+.
10756 *
10757 * When +readpartial+ doesn't block, it returns or raises immediately. If
10758 * the byte buffer is not empty, it returns the data in the buffer. Otherwise, if
10759 * the stream has some content, it returns the data in the stream. If the
10760 * stream reaches EOF an +EOFError+ is raised.
10761 */
10762
10763 static VALUE
10764 argf_readpartial(int argc, VALUE *argv, VALUE argf)
10765 {
10766 return argf_getpartial(argc, argv, argf, 0);
10767 }
10768
10769 /*
10770 * call-seq:
10771 * ARGF.read_nonblock(maxlen) -> string
10772 * ARGF.read_nonblock(maxlen, outbuf) -> outbuf
10773 *
10774 * Reads at most _maxlen_ bytes from the ARGF stream in non-blocking mode.
10775 */
10776
10777 static VALUE
10778 argf_read_nonblock(int argc, VALUE *argv, VALUE argf)
10779 {
10780 return argf_getpartial(argc, argv, argf, 1);
10781 }
10782
10783 static VALUE
10784 argf_getpartial(int argc, VALUE *argv, VALUE argf, int nonblock)
10785 {
10786 VALUE tmp, str, length;
10787
10788 rb_scan_args(argc, argv, "11", &length, &str);
10789 if (!NIL_P(str)) {
10790 StringValue(str);
10791 argv[1] = str;
10792 }
10793
10794 if (!next_argv()) {
10795 rb_str_resize(str, 0);
10796 rb_eof_error();
10797 }
10798 if (ARGF_GENERIC_INPUT_P()) {
10799 struct argf_call_arg arg;
10800 arg.argc = argc;
10801 arg.argv = argv;
10802 arg.argf = argf;
10803 tmp = rb_rescue2(argf_forward_call, (VALUE)&arg,
10804 RUBY_METHOD_FUNC(0), Qnil, rb_eEOFError, (VALUE)0);
10805 }
10806 else {
10807 tmp = io_getpartial(argc, argv, ARGF.current_file, nonblock);
10808 }
10809 if (NIL_P(tmp)) {
10810 if (ARGF.next_p == -1) {
10811 rb_eof_error();
10812 }
10813 argf_close(ARGF.current_file);
10814 ARGF.next_p = 1;
10815 if (RARRAY_LEN(ARGF.argv) == 0)
10816 rb_eof_error();
10817 if (NIL_P(str))
10818 str = rb_str_new(NULL, 0);
10819 return str;
10820 }
10821 return tmp;
10822 }
10823
10824 /*
10825 * call-seq:
10826 * ARGF.getc -> String or nil
10827 *
10828 * Reads the next character from +ARGF+ and returns it as a +String+. Returns
10829 * +nil+ at the end of the stream.
10830 *
10831 * +ARGF+ treats the files named on the command line as a single file created
10832 * by concatenating their contents. After returning the last character of the
10833 * first file, it returns the first character of the second file, and so on.
10834 *
10835 * For example:
10836 *
10837 * $ echo "foo" > file
10838 * $ ruby argf.rb file
10839 *
10840 * ARGF.getc #=> "f"
10841 * ARGF.getc #=> "o"
10842 * ARGF.getc #=> "o"
10843 * ARGF.getc #=> "\n"
10844 * ARGF.getc #=> nil
10845 * ARGF.getc #=> nil
10846 */
10847 static VALUE
10848 argf_getc(VALUE argf)
10849 {
10850 VALUE ch;
10851
10852 retry:
10853 if (!next_argv()) return Qnil;
10854 if (ARGF_GENERIC_INPUT_P()) {
10855 ch = rb_funcall3(ARGF.current_file, rb_intern("getc"), 0, 0);
10856 }
10857 else {
10858 ch = rb_io_getc(ARGF.current_file);
10859 }
10860 if (NIL_P(ch) && ARGF.next_p != -1) {
10861 argf_close(ARGF.current_file);
10862 ARGF.next_p = 1;
10863 goto retry;
10864 }
10865
10866 return ch;
10867 }
10868
10869 /*
10870 * call-seq:
10871 * ARGF.getbyte -> Fixnum or nil
10872 *
10873 * Gets the next 8-bit byte (0..255) from +ARGF+. Returns +nil+ if called at
10874 * the end of the stream.
10875 *
10876 * For example:
10877 *
10878 * $ echo "foo" > file
10879 * $ ruby argf.rb file
10880 *
10881 * ARGF.getbyte #=> 102
10882 * ARGF.getbyte #=> 111
10883 * ARGF.getbyte #=> 111
10884 * ARGF.getbyte #=> 10
10885 * ARGF.getbyte #=> nil
10886 */
10887 static VALUE
10888 argf_getbyte(VALUE argf)
10889 {
10890 VALUE ch;
10891
10892 retry:
10893 if (!next_argv()) return Qnil;
10894 if (!RB_TYPE_P(ARGF.current_file, T_FILE)) {
10895 ch = rb_funcall3(ARGF.current_file, rb_intern("getbyte"), 0, 0);
10896 }
10897 else {
10898 ch = rb_io_getbyte(ARGF.current_file);
10899 }
10900 if (NIL_P(ch) && ARGF.next_p != -1) {
10901 argf_close(ARGF.current_file);
10902 ARGF.next_p = 1;
10903 goto retry;
10904 }
10905
10906 return ch;
10907 }
10908
10909 /*
10910 * call-seq:
10911 * ARGF.readchar -> String or nil
10912 *
10913 * Reads the next character from +ARGF+ and returns it as a +String+. Raises
10914 * an +EOFError+ after the last character of the last file has been read.
10915 *
10916 * For example:
10917 *
10918 * $ echo "foo" > file
10919 * $ ruby argf.rb file
10920 *
10921 * ARGF.readchar #=> "f"
10922 * ARGF.readchar #=> "o"
10923 * ARGF.readchar #=> "o"
10924 * ARGF.readchar #=> "\n"
10925 * ARGF.readchar #=> end of file reached (EOFError)
10926 */
10927 static VALUE
10928 argf_readchar(VALUE argf)
10929 {
10930 VALUE ch;
10931
10932 retry:
10933 if (!next_argv()) rb_eof_error();
10934 if (!RB_TYPE_P(ARGF.current_file, T_FILE)) {
10935 ch = rb_funcall3(ARGF.current_file, rb_intern("getc"), 0, 0);
10936 }
10937 else {
10938 ch = rb_io_getc(ARGF.current_file);
10939 }
10940 if (NIL_P(ch) && ARGF.next_p != -1) {
10941 argf_close(ARGF.current_file);
10942 ARGF.next_p = 1;
10943 goto retry;
10944 }
10945
10946 return ch;
10947 }
10948
10949 /*
10950 * call-seq:
10951 * ARGF.readbyte -> Fixnum
10952 *
10953 * Reads the next 8-bit byte from ARGF and returns it as a +Fixnum+. Raises
10954 * an +EOFError+ after the last byte of the last file has been read.
10955 *
10956 * For example:
10957 *
10958 * $ echo "foo" > file
10959 * $ ruby argf.rb file
10960 *
10961 * ARGF.readbyte #=> 102
10962 * ARGF.readbyte #=> 111
10963 * ARGF.readbyte #=> 111
10964 * ARGF.readbyte #=> 10
10965 * ARGF.readbyte #=> end of file reached (EOFError)
10966 */
10967 static VALUE
10968 argf_readbyte(VALUE argf)
10969 {
10970 VALUE c;
10971
10972 NEXT_ARGF_FORWARD(0, 0);
10973 c = argf_getbyte(argf);
10974 if (NIL_P(c)) {
10975 rb_eof_error();
10976 }
10977 return c;
10978 }
10979
10980 /*
10981 * call-seq:
10982 * ARGF.each(sep=$/) {|line| block } -> ARGF
10983 * ARGF.each(sep=$/,limit) {|line| block } -> ARGF
10984 * ARGF.each(...) -> an_enumerator
10985 *
10986 * ARGF.each_line(sep=$/) {|line| block } -> ARGF
10987 * ARGF.each_line(sep=$/,limit) {|line| block } -> ARGF
10988 * ARGF.each_line(...) -> an_enumerator
10989 *
10990 * Returns an enumerator which iterates over each line (separated by _sep_,
10991 * which defaults to your platform's newline character) of each file in
10992 * +ARGV+. If a block is supplied, each line in turn will be yielded to the
10993 * block, otherwise an enumerator is returned.
10994 * The optional _limit_ argument is a +Fixnum+ specifying the maximum
10995 * length of each line; longer lines will be split according to this limit.
10996 *
10997 * This method allows you to treat the files supplied on the command line as
10998 * a single file consisting of the concatenation of each named file. After
10999 * the last line of the first file has been returned, the first line of the
11000 * second file is returned. The +ARGF.filename+ and +ARGF.lineno+ methods can
11001 * be used to determine the filename and line number, respectively, of the
11002 * current line.
11003 *
11004 * For example, the following code prints out each line of each named file
11005 * prefixed with its line number, displaying the filename once per file:
11006 *
11007 * ARGF.lines do |line|
11008 * puts ARGF.filename if ARGF.lineno == 1
11009 * puts "#{ARGF.lineno}: #{line}"
11010 * end
11011 */
11012 static VALUE
11013 argf_each_line(int argc, VALUE *argv, VALUE argf)
11014 {
11015 RETURN_ENUMERATOR(argf, argc, argv);
11016 for (;;) {
11017 if (!next_argv()) return argf;
11018 rb_block_call(ARGF.current_file, rb_intern("each_line"), argc, argv, 0, 0);
11019 ARGF.next_p = 1;
11020 }
11021 }
11022
11023 /*
11024 * This is a deprecated alias for <code>each_line</code>.
11025 */
11026
11027 static VALUE
11028 argf_lines(int argc, VALUE *argv, VALUE argf)
11029 {
11030 rb_warn("ARGF#lines is deprecated; use #each_line instead");
11031 if (!rb_block_given_p())
11032 return rb_enumeratorize(argf, ID2SYM(rb_intern("each_line")), argc, argv);
11033 return argf_each_line(argc, argv, argf);
11034 }
11035
11036 /*
11037 * call-seq:
11038 * ARGF.bytes {|byte| block } -> ARGF
11039 * ARGF.bytes -> an_enumerator
11040 *
11041 * ARGF.each_byte {|byte| block } -> ARGF
11042 * ARGF.each_byte -> an_enumerator
11043 *
11044 * Iterates over each byte of each file in +ARGV+.
11045 * A byte is returned as a +Fixnum+ in the range 0..255.
11046 *
11047 * This method allows you to treat the files supplied on the command line as
11048 * a single file consisting of the concatenation of each named file. After
11049 * the last byte of the first file has been returned, the first byte of the
11050 * second file is returned. The +ARGF.filename+ method can be used to
11051 * determine the filename of the current byte.
11052 *
11053 * If no block is given, an enumerator is returned instead.
11054 *
11055 * For example:
11056 *
11057 * ARGF.bytes.to_a #=> [35, 32, ... 95, 10]
11058 *
11059 */
11060 static VALUE
11061 argf_each_byte(VALUE argf)
11062 {
11063 RETURN_ENUMERATOR(argf, 0, 0);
11064 for (;;) {
11065 if (!next_argv()) return argf;
11066 rb_block_call(ARGF.current_file, rb_intern("each_byte"), 0, 0, 0, 0);
11067 ARGF.next_p = 1;
11068 }
11069 }
11070
11071 /*
11072 * This is a deprecated alias for <code>each_byte</code>.
11073 */
11074
11075 static VALUE
11076 argf_bytes(VALUE argf)
11077 {
11078 rb_warn("ARGF#bytes is deprecated; use #each_byte instead");
11079 if (!rb_block_given_p())
11080 return rb_enumeratorize(argf, ID2SYM(rb_intern("each_byte")), 0, 0);
11081 return argf_each_byte(argf);
11082 }
11083
11084 /*
11085 * call-seq:
11086 * ARGF.each_char {|char| block } -> ARGF
11087 * ARGF.each_char -> an_enumerator
11088 *
11089 * Iterates over each character of each file in +ARGF+.
11090 *
11091 * This method allows you to treat the files supplied on the command line as
11092 * a single file consisting of the concatenation of each named file. After
11093 * the last character of the first file has been returned, the first
11094 * character of the second file is returned. The +ARGF.filename+ method can
11095 * be used to determine the name of the file in which the current character
11096 * appears.
11097 *
11098 * If no block is given, an enumerator is returned instead.
11099 */
11100 static VALUE
11101 argf_each_char(VALUE argf)
11102 {
11103 RETURN_ENUMERATOR(argf, 0, 0);
11104 for (;;) {
11105 if (!next_argv()) return argf;
11106 rb_block_call(ARGF.current_file, rb_intern("each_char"), 0, 0, 0, 0);
11107 ARGF.next_p = 1;
11108 }
11109 }
11110
11111 /*
11112 * This is a deprecated alias for <code>each_char</code>.
11113 */
11114
11115 static VALUE
11116 argf_chars(VALUE argf)
11117 {
11118 rb_warn("ARGF#chars is deprecated; use #each_char instead");
11119 if (!rb_block_given_p())
11120 return rb_enumeratorize(argf, ID2SYM(rb_intern("each_char")), 0, 0);
11121 return argf_each_char(argf);
11122 }
11123
11124 /*
11125 * call-seq:
11126 * ARGF.each_codepoint {|codepoint| block } -> ARGF
11127 * ARGF.each_codepoint -> an_enumerator
11128 *
11129 * Iterates over each codepoint of each file in +ARGF+.
11130 *
11131 * This method allows you to treat the files supplied on the command line as
11132 * a single file consisting of the concatenation of each named file. After
11133 * the last codepoint of the first file has been returned, the first
11134 * codepoint of the second file is returned. The +ARGF.filename+ method can
11135 * be used to determine the name of the file in which the current codepoint
11136 * appears.
11137 *
11138 * If no block is given, an enumerator is returned instead.
11139 */
11140 static VALUE
11141 argf_each_codepoint(VALUE argf)
11142 {
11143 RETURN_ENUMERATOR(argf, 0, 0);
11144 for (;;) {
11145 if (!next_argv()) return argf;
11146 rb_block_call(ARGF.current_file, rb_intern("each_codepoint"), 0, 0, 0, 0);
11147 ARGF.next_p = 1;
11148 }
11149 }
11150
11151 /*
11152 * This is a deprecated alias for <code>each_codepoint</code>.
11153 */
11154
11155 static VALUE
11156 argf_codepoints(VALUE argf)
11157 {
11158 rb_warn("ARGF#codepoints is deprecated; use #each_codepoint instead");
11159 if (!rb_block_given_p())
11160 return rb_enumeratorize(argf, ID2SYM(rb_intern("each_codepoint")), 0, 0);
11161 return argf_each_codepoint(argf);
11162 }
11163
11164 /*
11165 * call-seq:
11166 * ARGF.filename -> String
11167 * ARGF.path -> String
11168 *
11169 * Returns the current filename. "-" is returned when the current file is
11170 * STDIN.
11171 *
11172 * For example:
11173 *
11174 * $ echo "foo" > foo
11175 * $ echo "bar" > bar
11176 * $ echo "glark" > glark
11177 *
11178 * $ ruby argf.rb foo bar glark
11179 *
11180 * ARGF.filename #=> "foo"
11181 * ARGF.read(5) #=> "foo\nb"
11182 * ARGF.filename #=> "bar"
11183 * ARGF.skip
11184 * ARGF.filename #=> "glark"
11185 */
11186 static VALUE
11187 argf_filename(VALUE argf)
11188 {
11189 next_argv();
11190 return ARGF.filename;
11191 }
11192
11193 static VALUE
11194 argf_filename_getter(ID id, VALUE *var)
11195 {
11196 return argf_filename(*var);
11197 }
11198
11199 /*
11200 * call-seq:
11201 * ARGF.file -> IO or File object
11202 *
11203 * Returns the current file as an +IO+ or +File+ object. #<IO:<STDIN>> is
11204 * returned when the current file is STDIN.
11205 *
11206 * For example:
11207 *
11208 * $ echo "foo" > foo
11209 * $ echo "bar" > bar
11210 *
11211 * $ ruby argf.rb foo bar
11212 *
11213 * ARGF.file #=> #<File:foo>
11214 * ARGF.read(5) #=> "foo\nb"
11215 * ARGF.file #=> #<File:bar>
11216 */
11217 static VALUE
11218 argf_file(VALUE argf)
11219 {
11220 next_argv();
11221 return ARGF.current_file;
11222 }
11223
11224 /*
11225 * call-seq:
11226 * ARGF.binmode -> ARGF
11227 *
11228 * Puts +ARGF+ into binary mode. Once a stream is in binary mode, it cannot
11229 * be reset to non-binary mode. This option has the following effects:
11230 *
11231 * * Newline conversion is disabled.
11232 * * Encoding conversion is disabled.
11233 * * Content is treated as ASCII-8BIT.
11234 */
11235 static VALUE
11236 argf_binmode_m(VALUE argf)
11237 {
11238 ARGF.binmode = 1;
11239 next_argv();
11240 ARGF_FORWARD(0, 0);
11241 rb_io_ascii8bit_binmode(ARGF.current_file);
11242 return argf;
11243 }
11244
11245 /*
11246 * call-seq:
11247 * ARGF.binmode? -> true or false
11248 *
11249 * Returns true if +ARGF+ is being read in binary mode; false otherwise. (To
11250 * enable binary mode use +ARGF.binmode+.
11251 *
11252 * For example:
11253 *
11254 * ARGF.binmode? #=> false
11255 * ARGF.binmode
11256 * ARGF.binmode? #=> true
11257 */
11258 static VALUE
11259 argf_binmode_p(VALUE argf)
11260 {
11261 return ARGF.binmode ? Qtrue : Qfalse;
11262 }
11263
11264 /*
11265 * call-seq:
11266 * ARGF.skip -> ARGF
11267 *
11268 * Sets the current file to the next file in ARGV. If there aren't any more
11269 * files it has no effect.
11270 *
11271 * For example:
11272 *
11273 * $ ruby argf.rb foo bar
11274 * ARGF.filename #=> "foo"
11275 * ARGF.skip
11276 * ARGF.filename #=> "bar"
11277 */
11278 static VALUE
11279 argf_skip(VALUE argf)
11280 {
11281 if (ARGF.init_p && ARGF.next_p == 0) {
11282 argf_close(ARGF.current_file);
11283 ARGF.next_p = 1;
11284 }
11285 return argf;
11286 }
11287
11288 /*
11289 * call-seq:
11290 * ARGF.close -> ARGF
11291 *
11292 * Closes the current file and skips to the next in the stream. Trying to
11293 * close a file that has already been closed causes an +IOError+ to be
11294 * raised.
11295 *
11296 * For example:
11297 *
11298 * $ ruby argf.rb foo bar
11299 *
11300 * ARGF.filename #=> "foo"
11301 * ARGF.close
11302 * ARGF.filename #=> "bar"
11303 * ARGF.close
11304 * ARGF.close #=> closed stream (IOError)
11305 */
11306 static VALUE
11307 argf_close_m(VALUE argf)
11308 {
11309 next_argv();
11310 argf_close(ARGF.current_file);
11311 if (ARGF.next_p != -1) {
11312 ARGF.next_p = 1;
11313 }
11314 ARGF.lineno = 0;
11315 return argf;
11316 }
11317
11318 /*
11319 * call-seq:
11320 * ARGF.closed? -> true or false
11321 *
11322 * Returns _true_ if the current file has been closed; _false_ otherwise. Use
11323 * +ARGF.close+ to actually close the current file.
11324 */
11325 static VALUE
11326 argf_closed(VALUE argf)
11327 {
11328 next_argv();
11329 ARGF_FORWARD(0, 0);
11330 return rb_io_closed(ARGF.current_file);
11331 }
11332
11333 /*
11334 * call-seq:
11335 * ARGF.to_s -> String
11336 *
11337 * Returns "ARGF".
11338 */
11339 static VALUE
11340 argf_to_s(VALUE argf)
11341 {
11342 return rb_str_new2("ARGF");
11343 }
11344
11345 /*
11346 * call-seq:
11347 * ARGF.inplace_mode -> String
11348 *
11349 * Returns the file extension appended to the names of modified files under
11350 * inplace-edit mode. This value can be set using +ARGF.inplace_mode=+ or
11351 * passing the +-i+ switch to the Ruby binary.
11352 */
11353 static VALUE
11354 argf_inplace_mode_get(VALUE argf)
11355 {
11356 if (!ARGF.inplace) return Qnil;
11357 return rb_str_new2(ARGF.inplace);
11358 }
11359
11360 static VALUE
11361 opt_i_get(ID id, VALUE *var)
11362 {
11363 return argf_inplace_mode_get(*var);
11364 }
11365
11366 /*
11367 * call-seq:
11368 * ARGF.inplace_mode = ext -> ARGF
11369 *
11370 * Sets the filename extension for inplace editing mode to the given String.
11371 * Each file being edited has this value appended to its filename. The
11372 * modified file is saved under this new name.
11373 *
11374 * For example:
11375 *
11376 * $ ruby argf.rb file.txt
11377 *
11378 * ARGF.inplace_mode = '.bak'
11379 * ARGF.lines do |line|
11380 * print line.sub("foo","bar")
11381 * end
11382 *
11383 * Each line of _file.txt_ has the first occurrence of "foo" replaced with
11384 * "bar", then the new line is written out to _file.txt.bak_.
11385 */
11386 static VALUE
11387 argf_inplace_mode_set(VALUE argf, VALUE val)
11388 {
11389 if (rb_safe_level() >= 1 && OBJ_TAINTED(val))
11390 rb_insecure_operation();
11391
11392 if (!RTEST(val)) {
11393 if (ARGF.inplace) free(ARGF.inplace);
11394 ARGF.inplace = 0;
11395 }
11396 else {
11397 StringValue(val);
11398 if (ARGF.inplace) free(ARGF.inplace);
11399 ARGF.inplace = 0;
11400 ARGF.inplace = strdup(RSTRING_PTR(val));
11401 }
11402 return argf;
11403 }
11404
11405 static void
11406 opt_i_set(VALUE val, ID id, VALUE *var)
11407 {
11408 argf_inplace_mode_set(*var, val);
11409 }
11410
11411 const char *
11412 ruby_get_inplace_mode(void)
11413 {
11414 return ARGF.inplace;
11415 }
11416
11417 void
11418 ruby_set_inplace_mode(const char *suffix)
11419 {
11420 if (ARGF.inplace) free(ARGF.inplace);
11421 ARGF.inplace = 0;
11422 if (suffix) ARGF.inplace = strdup(suffix);
11423 }
11424
11425 /*
11426 * call-seq:
11427 * ARGF.argv -> ARGV
11428 *
11429 * Returns the +ARGV+ array, which contains the arguments passed to your
11430 * script, one per element.
11431 *
11432 * For example:
11433 *
11434 * $ ruby argf.rb -v glark.txt
11435 *
11436 * ARGF.argv #=> ["-v", "glark.txt"]
11437 *
11438 */
11439 static VALUE
11440 argf_argv(VALUE argf)
11441 {
11442 return ARGF.argv;
11443 }
11444
11445 static VALUE
11446 argf_argv_getter(ID id, VALUE *var)
11447 {
11448 return argf_argv(*var);
11449 }
11450
11451 VALUE
11452 rb_get_argv(void)
11453 {
11454 return ARGF.argv;
11455 }
11456
11457 /*
11458 * call-seq:
11459 * ARGF.to_write_io -> io
11460 *
11461 * Returns IO instance tied to _ARGF_ for writing if inplace mode is
11462 * enabled.
11463 */
11464 static VALUE
11465 argf_write_io(VALUE argf)
11466 {
11467 if (!RTEST(ARGF.current_file)) {
11468 rb_raise(rb_eIOError, "not opened for writing");
11469 }
11470 return GetWriteIO(ARGF.current_file);
11471 }
11472
11473 /*
11474 * call-seq:
11475 * ARGF.write(string) -> integer
11476 *
11477 * Writes _string_ if inplace mode.
11478 */
11479 static VALUE
11480 argf_write(VALUE argf, VALUE str)
11481 {
11482 return rb_io_write(argf_write_io(argf), str);
11483 }
11484
11485 /*
11486 * Document-class: IOError
11487 *
11488 * Raised when an IO operation fails.
11489 *
11490 * File.open("/etc/hosts") {|f| f << "example"}
11491 * #=> IOError: not opened for writing
11492 *
11493 * File.open("/etc/hosts") {|f| f.close; f.read }
11494 * #=> IOError: closed stream
11495 *
11496 * Note that some IO failures raise +SystemCallError+s and these are not
11497 * subclasses of IOError:
11498 *
11499 * File.open("does/not/exist")
11500 * #=> Errno::ENOENT: No such file or directory - does/not/exist
11501 */
11502
11503 /*
11504 * Document-class: EOFError
11505 *
11506 * Raised by some IO operations when reaching the end of file. Many IO
11507 * methods exist in two forms,
11508 *
11509 * one that returns +nil+ when the end of file is reached, the other
11510 * raises EOFError +EOFError+.
11511 *
11512 * +EOFError+ is a subclass of +IOError+.
11513 *
11514 * file = File.open("/etc/hosts")
11515 * file.read
11516 * file.gets #=> nil
11517 * file.readline #=> EOFError: end of file reached
11518 */
11519
11520 /*
11521 * Document-class: ARGF
11522 *
11523 * +ARGF+ is a stream designed for use in scripts that process files given as
11524 * command-line arguments or passed in via STDIN.
11525 *
11526 * The arguments passed to your script are stored in the +ARGV+ Array, one
11527 * argument per element. +ARGF+ assumes that any arguments that aren't
11528 * filenames have been removed from +ARGV+. For example:
11529 *
11530 * $ ruby argf.rb --verbose file1 file2
11531 *
11532 * ARGV #=> ["--verbose", "file1", "file2"]
11533 * option = ARGV.shift #=> "--verbose"
11534 * ARGV #=> ["file1", "file2"]
11535 *
11536 * You can now use +ARGF+ to work with a concatenation of each of these named
11537 * files. For instance, +ARGF.read+ will return the contents of _file1_
11538 * followed by the contents of _file2_.
11539 *
11540 * After a file in +ARGV+ has been read +ARGF+ removes it from the Array.
11541 * Thus, after all files have been read +ARGV+ will be empty.
11542 *
11543 * You can manipulate +ARGV+ yourself to control what +ARGF+ operates on. If
11544 * you remove a file from +ARGV+, it is ignored by +ARGF+; if you add files to
11545 * +ARGV+, they are treated as if they were named on the command line. For
11546 * example:
11547 *
11548 * ARGV.replace ["file1"]
11549 * ARGF.readlines # Returns the contents of file1 as an Array
11550 * ARGV #=> []
11551 * ARGV.replace ["file2", "file3"]
11552 * ARGF.read # Returns the contents of file2 and file3
11553 *
11554 * If +ARGV+ is empty, +ARGF+ acts as if it contained STDIN, i.e. the data
11555 * piped to your script. For example:
11556 *
11557 * $ echo "glark" | ruby -e 'p ARGF.read'
11558 * "glark\n"
11559 */
11560
11561 /*
11562 * The IO class is the basis for all input and output in Ruby.
11563 * An I/O stream may be <em>duplexed</em> (that is, bidirectional), and
11564 * so may use more than one native operating system stream.
11565 *
11566 * Many of the examples in this section use the File class, the only standard
11567 * subclass of IO. The two classes are closely associated. Like the File
11568 * class, the Socket library subclasses from IO (such as TCPSocket or
11569 * UDPSocket).
11570 *
11571 * The Kernel#open method can create an IO (or File) object for these types
11572 * of arguments:
11573 *
11574 * * A plain string represents a filename suitable for the underlying
11575 * operating system.
11576 *
11577 * * A string starting with <code>"|"</code> indicates a subprocess.
11578 * The remainder of the string following the <code>"|"</code> is
11579 * invoked as a process with appropriate input/output channels
11580 * connected to it.
11581 *
11582 * * A string equal to <code>"|-"</code> will create another Ruby
11583 * instance as a subprocess.
11584 *
11585 * The IO may be opened with different file modes (read-only, write-only) and
11586 * encodings for proper conversion. See IO.new for these options. See
11587 * Kernel#open for details of the various command formats described above.
11588 *
11589 * IO.popen, the Open3 library, or Process#spawn may also be used to
11590 * communicate with subprocesses through an IO.
11591 *
11592 * Ruby will convert pathnames between different operating system
11593 * conventions if possible. For instance, on a Windows system the
11594 * filename <code>"/gumby/ruby/test.rb"</code> will be opened as
11595 * <code>"\gumby\ruby\test.rb"</code>. When specifying a Windows-style
11596 * filename in a Ruby string, remember to escape the backslashes:
11597 *
11598 * "c:\\gumby\\ruby\\test.rb"
11599 *
11600 * Our examples here will use the Unix-style forward slashes;
11601 * File::ALT_SEPARATOR can be used to get the platform-specific separator
11602 * character.
11603 *
11604 * The global constant ARGF (also accessible as $<) provides an
11605 * IO-like stream which allows access to all files mentioned on the
11606 * command line (or STDIN if no files are mentioned). ARGF#path and its alias
11607 * ARGF#filename are provided to access the name of the file currently being
11608 * read.
11609 *
11610 * == io/console
11611 *
11612 * The io/console extension provides methods for interacting with the
11613 * console. The console can be accessed from IO.console or the standard
11614 * input/output/error IO objects.
11615 *
11616 * Requiring io/console adds the following methods:
11617 *
11618 * * IO::console
11619 * * IO#raw
11620 * * IO#raw!
11621 * * IO#cooked
11622 * * IO#cooked!
11623 * * IO#getch
11624 * * IO#echo=
11625 * * IO#echo?
11626 * * IO#noecho
11627 * * IO#winsize
11628 * * IO#winsize=
11629 * * IO#iflush
11630 * * IO#ioflush
11631 * * IO#oflush
11632 *
11633 * Example:
11634 *
11635 * require 'io/console'
11636 * rows, columns = $stdin.winsize
11637 * puts "Your screen is #{columns} wide and #{rows} tall"
11638 */
11639
11640 void
11641 Init_IO(void)
11642 {
11643 #undef rb_intern
11644 #define rb_intern(str) rb_intern_const(str)
11645
11646 VALUE rb_cARGF;
11647 #ifdef __CYGWIN__
11648 #include <sys/cygwin.h>
11649 static struct __cygwin_perfile pf[] =
11650 {
11651 {"", O_RDONLY | O_BINARY},
11652 {"", O_WRONLY | O_BINARY},
11653 {"", O_RDWR | O_BINARY},
11654 {"", O_APPEND | O_BINARY},
11655 {NULL, 0}
11656 };
11657 cygwin_internal(CW_PERFILE, pf);
11658 #endif
11659
11660 rb_eIOError = rb_define_class("IOError", rb_eStandardError);
11661 rb_eEOFError = rb_define_class("EOFError", rb_eIOError);
11662
11663 id_write = rb_intern("write");
11664 id_read = rb_intern("read");
11665 id_getc = rb_intern("getc");
11666 id_flush = rb_intern("flush");
11667 id_readpartial = rb_intern("readpartial");
11668 id_set_encoding = rb_intern("set_encoding");
11669
11670 rb_define_global_function("syscall", rb_f_syscall, -1);
11671
11672 rb_define_global_function("open", rb_f_open, -1);
11673 rb_define_global_function("printf", rb_f_printf, -1);
11674 rb_define_global_function("print", rb_f_print, -1);
11675 rb_define_global_function("putc", rb_f_putc, 1);
11676 rb_define_global_function("puts", rb_f_puts, -1);
11677 rb_define_global_function("gets", rb_f_gets, -1);
11678 rb_define_global_function("readline", rb_f_readline, -1);
11679 rb_define_global_function("select", rb_f_select, -1);
11680
11681 rb_define_global_function("readlines", rb_f_readlines, -1);
11682
11683 rb_define_global_function("`", rb_f_backquote, 1);
11684
11685 rb_define_global_function("p", rb_f_p, -1);
11686 rb_define_method(rb_mKernel, "display", rb_obj_display, -1);
11687
11688 rb_cIO = rb_define_class("IO", rb_cObject);
11689 rb_include_module(rb_cIO, rb_mEnumerable);
11690
11691 rb_mWaitReadable = rb_define_module_under(rb_cIO, "WaitReadable");
11692 rb_mWaitWritable = rb_define_module_under(rb_cIO, "WaitWritable");
11693
11694 #if 0
11695 /* This is necessary only for forcing rdoc handle File::open */
11696 rb_define_singleton_method(rb_cFile, "open", rb_io_s_open, -1);
11697 #endif
11698
11699 rb_define_alloc_func(rb_cIO, io_alloc);
11700 rb_define_singleton_method(rb_cIO, "new", rb_io_s_new, -1);
11701 rb_define_singleton_method(rb_cIO, "open", rb_io_s_open, -1);
11702 rb_define_singleton_method(rb_cIO, "sysopen", rb_io_s_sysopen, -1);
11703 rb_define_singleton_method(rb_cIO, "for_fd", rb_io_s_for_fd, -1);
11704 rb_define_singleton_method(rb_cIO, "popen", rb_io_s_popen, -1);
11705 rb_define_singleton_method(rb_cIO, "foreach", rb_io_s_foreach, -1);
11706 rb_define_singleton_method(rb_cIO, "readlines", rb_io_s_readlines, -1);
11707 rb_define_singleton_method(rb_cIO, "read", rb_io_s_read, -1);
11708 rb_define_singleton_method(rb_cIO, "binread", rb_io_s_binread, -1);
11709 rb_define_singleton_method(rb_cIO, "write", rb_io_s_write, -1);
11710 rb_define_singleton_method(rb_cIO, "binwrite", rb_io_s_binwrite, -1);
11711 rb_define_singleton_method(rb_cIO, "select", rb_f_select, -1);
11712 rb_define_singleton_method(rb_cIO, "pipe", rb_io_s_pipe, -1);
11713 rb_define_singleton_method(rb_cIO, "try_convert", rb_io_s_try_convert, 1);
11714 rb_define_singleton_method(rb_cIO, "copy_stream", rb_io_s_copy_stream, -1);
11715
11716 rb_define_method(rb_cIO, "initialize", rb_io_initialize, -1);
11717
11718 rb_output_fs = Qnil;
11719 rb_define_hooked_variable("$,", &rb_output_fs, 0, rb_str_setter);
11720
11721 rb_rs = rb_default_rs = rb_usascii_str_new2("\n");
11722 rb_gc_register_mark_object(rb_default_rs);
11723 rb_output_rs = Qnil;
11724 OBJ_FREEZE(rb_default_rs); /* avoid modifying RS_default */
11725 rb_define_hooked_variable("$/", &rb_rs, 0, rb_str_setter);
11726 rb_define_hooked_variable("$-0", &rb_rs, 0, rb_str_setter);
11727 rb_define_hooked_variable("$\\", &rb_output_rs, 0, rb_str_setter);
11728
11729 rb_define_virtual_variable("$_", rb_lastline_get, rb_lastline_set);
11730
11731 rb_define_method(rb_cIO, "initialize_copy", rb_io_init_copy, 1);
11732 rb_define_method(rb_cIO, "reopen", rb_io_reopen, -1);
11733
11734 rb_define_method(rb_cIO, "print", rb_io_print, -1);
11735 rb_define_method(rb_cIO, "putc", rb_io_putc, 1);
11736 rb_define_method(rb_cIO, "puts", rb_io_puts, -1);
11737 rb_define_method(rb_cIO, "printf", rb_io_printf, -1);
11738
11739 rb_define_method(rb_cIO, "each", rb_io_each_line, -1);
11740 rb_define_method(rb_cIO, "each_line", rb_io_each_line, -1);
11741 rb_define_method(rb_cIO, "each_byte", rb_io_each_byte, 0);
11742 rb_define_method(rb_cIO, "each_char", rb_io_each_char, 0);
11743 rb_define_method(rb_cIO, "each_codepoint", rb_io_each_codepoint, 0);
11744 rb_define_method(rb_cIO, "lines", rb_io_lines, -1);
11745 rb_define_method(rb_cIO, "bytes", rb_io_bytes, 0);
11746 rb_define_method(rb_cIO, "chars", rb_io_chars, 0);
11747 rb_define_method(rb_cIO, "codepoints", rb_io_codepoints, 0);
11748
11749 rb_define_method(rb_cIO, "syswrite", rb_io_syswrite, 1);
11750 rb_define_method(rb_cIO, "sysread", rb_io_sysread, -1);
11751
11752 rb_define_method(rb_cIO, "fileno", rb_io_fileno, 0);
11753 rb_define_alias(rb_cIO, "to_i", "fileno");
11754 rb_define_method(rb_cIO, "to_io", rb_io_to_io, 0);
11755
11756 rb_define_method(rb_cIO, "fsync", rb_io_fsync, 0);
11757 rb_define_method(rb_cIO, "fdatasync", rb_io_fdatasync, 0);
11758 rb_define_method(rb_cIO, "sync", rb_io_sync, 0);
11759 rb_define_method(rb_cIO, "sync=", rb_io_set_sync, 1);
11760
11761 rb_define_method(rb_cIO, "lineno", rb_io_lineno, 0);
11762 rb_define_method(rb_cIO, "lineno=", rb_io_set_lineno, 1);
11763
11764 rb_define_method(rb_cIO, "readlines", rb_io_readlines, -1);
11765
11766 rb_define_method(rb_cIO, "read_nonblock", io_read_nonblock, -1);
11767 rb_define_method(rb_cIO, "write_nonblock", rb_io_write_nonblock, 1);
11768 rb_define_method(rb_cIO, "readpartial", io_readpartial, -1);
11769 rb_define_method(rb_cIO, "read", io_read, -1);
11770 rb_define_method(rb_cIO, "write", io_write_m, 1);
11771 rb_define_method(rb_cIO, "gets", rb_io_gets_m, -1);
11772 rb_define_method(rb_cIO, "readline", rb_io_readline, -1);
11773 rb_define_method(rb_cIO, "getc", rb_io_getc, 0);
11774 rb_define_method(rb_cIO, "getbyte", rb_io_getbyte, 0);
11775 rb_define_method(rb_cIO, "readchar", rb_io_readchar, 0);
11776 rb_define_method(rb_cIO, "readbyte", rb_io_readbyte, 0);
11777 rb_define_method(rb_cIO, "ungetbyte",rb_io_ungetbyte, 1);
11778 rb_define_method(rb_cIO, "ungetc",rb_io_ungetc, 1);
11779 rb_define_method(rb_cIO, "<<", rb_io_addstr, 1);
11780 rb_define_method(rb_cIO, "flush", rb_io_flush, 0);
11781 rb_define_method(rb_cIO, "tell", rb_io_tell, 0);
11782 rb_define_method(rb_cIO, "seek", rb_io_seek_m, -1);
11783 rb_define_const(rb_cIO, "SEEK_SET", INT2FIX(SEEK_SET));
11784 rb_define_const(rb_cIO, "SEEK_CUR", INT2FIX(SEEK_CUR));
11785 rb_define_const(rb_cIO, "SEEK_END", INT2FIX(SEEK_END));
11786 rb_define_method(rb_cIO, "rewind", rb_io_rewind, 0);
11787 rb_define_method(rb_cIO, "pos", rb_io_tell, 0);
11788 rb_define_method(rb_cIO, "pos=", rb_io_set_pos, 1);
11789 rb_define_method(rb_cIO, "eof", rb_io_eof, 0);
11790 rb_define_method(rb_cIO, "eof?", rb_io_eof, 0);
11791
11792 rb_define_method(rb_cIO, "close_on_exec?", rb_io_close_on_exec_p, 0);
11793 rb_define_method(rb_cIO, "close_on_exec=", rb_io_set_close_on_exec, 1);
11794
11795 rb_define_method(rb_cIO, "close", rb_io_close_m, 0);
11796 rb_define_method(rb_cIO, "closed?", rb_io_closed, 0);
11797 rb_define_method(rb_cIO, "close_read", rb_io_close_read, 0);
11798 rb_define_method(rb_cIO, "close_write", rb_io_close_write, 0);
11799
11800 rb_define_method(rb_cIO, "isatty", rb_io_isatty, 0);
11801 rb_define_method(rb_cIO, "tty?", rb_io_isatty, 0);
11802 rb_define_method(rb_cIO, "binmode", rb_io_binmode_m, 0);
11803 rb_define_method(rb_cIO, "binmode?", rb_io_binmode_p, 0);
11804 rb_define_method(rb_cIO, "sysseek", rb_io_sysseek, -1);
11805 rb_define_method(rb_cIO, "advise", rb_io_advise, -1);
11806
11807 rb_define_method(rb_cIO, "ioctl", rb_io_ioctl, -1);
11808 rb_define_method(rb_cIO, "fcntl", rb_io_fcntl, -1);
11809 rb_define_method(rb_cIO, "pid", rb_io_pid, 0);
11810 rb_define_method(rb_cIO, "inspect", rb_io_inspect, 0);
11811
11812 rb_define_method(rb_cIO, "external_encoding", rb_io_external_encoding, 0);
11813 rb_define_method(rb_cIO, "internal_encoding", rb_io_internal_encoding, 0);
11814 rb_define_method(rb_cIO, "set_encoding", rb_io_set_encoding, -1);
11815
11816 rb_define_method(rb_cIO, "autoclose?", rb_io_autoclose_p, 0);
11817 rb_define_method(rb_cIO, "autoclose=", rb_io_set_autoclose, 1);
11818
11819 rb_define_variable("$stdin", &rb_stdin);
11820 rb_stdin = prep_stdio(stdin, FMODE_READABLE, rb_cIO, "<STDIN>");
11821 rb_define_hooked_variable("$stdout", &rb_stdout, 0, stdout_setter);
11822 rb_stdout = prep_stdio(stdout, FMODE_WRITABLE, rb_cIO, "<STDOUT>");
11823 rb_define_hooked_variable("$stderr", &rb_stderr, 0, stdout_setter);
11824 rb_stderr = prep_stdio(stderr, FMODE_WRITABLE|FMODE_SYNC, rb_cIO, "<STDERR>");
11825 rb_define_hooked_variable("$>", &rb_stdout, 0, stdout_setter);
11826 orig_stdout = rb_stdout;
11827 rb_deferr = orig_stderr = rb_stderr;
11828
11829 /* Holds the original stdin */
11830 rb_define_global_const("STDIN", rb_stdin);
11831 /* Holds the original stdout */
11832 rb_define_global_const("STDOUT", rb_stdout);
11833 /* Holds the original stderr */
11834 rb_define_global_const("STDERR", rb_stderr);
11835
11836 #if 0
11837 /* Hack to get rdoc to regard ARGF as a class: */
11838 rb_cARGF = rb_define_class("ARGF", rb_cObject);
11839 #endif
11840
11841 rb_cARGF = rb_class_new(rb_cObject);
11842 rb_set_class_path(rb_cARGF, rb_cObject, "ARGF.class");
11843 rb_define_alloc_func(rb_cARGF, argf_alloc);
11844
11845 rb_include_module(rb_cARGF, rb_mEnumerable);
11846
11847 rb_define_method(rb_cARGF, "initialize", argf_initialize, -2);
11848 rb_define_method(rb_cARGF, "initialize_copy", argf_initialize_copy, 1);
11849 rb_define_method(rb_cARGF, "to_s", argf_to_s, 0);
11850 rb_define_alias(rb_cARGF, "inspect", "to_s");
11851 rb_define_method(rb_cARGF, "argv", argf_argv, 0);
11852
11853 rb_define_method(rb_cARGF, "fileno", argf_fileno, 0);
11854 rb_define_method(rb_cARGF, "to_i", argf_fileno, 0);
11855 rb_define_method(rb_cARGF, "to_io", argf_to_io, 0);
11856 rb_define_method(rb_cARGF, "to_write_io", argf_write_io, 0);
11857 rb_define_method(rb_cARGF, "each", argf_each_line, -1);
11858 rb_define_method(rb_cARGF, "each_line", argf_each_line, -1);
11859 rb_define_method(rb_cARGF, "each_byte", argf_each_byte, 0);
11860 rb_define_method(rb_cARGF, "each_char", argf_each_char, 0);
11861 rb_define_method(rb_cARGF, "each_codepoint", argf_each_codepoint, 0);
11862 rb_define_method(rb_cARGF, "lines", argf_lines, -1);
11863 rb_define_method(rb_cARGF, "bytes", argf_bytes, 0);
11864 rb_define_method(rb_cARGF, "chars", argf_chars, 0);
11865 rb_define_method(rb_cARGF, "codepoints", argf_codepoints, 0);
11866
11867 rb_define_method(rb_cARGF, "read", argf_read, -1);
11868 rb_define_method(rb_cARGF, "readpartial", argf_readpartial, -1);
11869 rb_define_method(rb_cARGF, "read_nonblock", argf_read_nonblock, -1);
11870 rb_define_method(rb_cARGF, "readlines", argf_readlines, -1);
11871 rb_define_method(rb_cARGF, "to_a", argf_readlines, -1);
11872 rb_define_method(rb_cARGF, "gets", argf_gets, -1);
11873 rb_define_method(rb_cARGF, "readline", argf_readline, -1);
11874 rb_define_method(rb_cARGF, "getc", argf_getc, 0);
11875 rb_define_method(rb_cARGF, "getbyte", argf_getbyte, 0);
11876 rb_define_method(rb_cARGF, "readchar", argf_readchar, 0);
11877 rb_define_method(rb_cARGF, "readbyte", argf_readbyte, 0);
11878 rb_define_method(rb_cARGF, "tell", argf_tell, 0);
11879 rb_define_method(rb_cARGF, "seek", argf_seek_m, -1);
11880 rb_define_method(rb_cARGF, "rewind", argf_rewind, 0);
11881 rb_define_method(rb_cARGF, "pos", argf_tell, 0);
11882 rb_define_method(rb_cARGF, "pos=", argf_set_pos, 1);
11883 rb_define_method(rb_cARGF, "eof", argf_eof, 0);
11884 rb_define_method(rb_cARGF, "eof?", argf_eof, 0);
11885 rb_define_method(rb_cARGF, "binmode", argf_binmode_m, 0);
11886 rb_define_method(rb_cARGF, "binmode?", argf_binmode_p, 0);
11887
11888 rb_define_method(rb_cARGF, "write", argf_write, 1);
11889 rb_define_method(rb_cARGF, "print", rb_io_print, -1);
11890 rb_define_method(rb_cARGF, "putc", rb_io_putc, 1);
11891 rb_define_method(rb_cARGF, "puts", rb_io_puts, -1);
11892 rb_define_method(rb_cARGF, "printf", rb_io_printf, -1);
11893
11894 rb_define_method(rb_cARGF, "filename", argf_filename, 0);
11895 rb_define_method(rb_cARGF, "path", argf_filename, 0);
11896 rb_define_method(rb_cARGF, "file", argf_file, 0);
11897 rb_define_method(rb_cARGF, "skip", argf_skip, 0);
11898 rb_define_method(rb_cARGF, "close", argf_close_m, 0);
11899 rb_define_method(rb_cARGF, "closed?", argf_closed, 0);
11900
11901 rb_define_method(rb_cARGF, "lineno", argf_lineno, 0);
11902 rb_define_method(rb_cARGF, "lineno=", argf_set_lineno, 1);
11903
11904 rb_define_method(rb_cARGF, "inplace_mode", argf_inplace_mode_get, 0);
11905 rb_define_method(rb_cARGF, "inplace_mode=", argf_inplace_mode_set, 1);
11906
11907 rb_define_method(rb_cARGF, "external_encoding", argf_external_encoding, 0);
11908 rb_define_method(rb_cARGF, "internal_encoding", argf_internal_encoding, 0);
11909 rb_define_method(rb_cARGF, "set_encoding", argf_set_encoding, -1);
11910
11911 argf = rb_class_new_instance(0, 0, rb_cARGF);
11912
11913 rb_define_readonly_variable("$<", &argf);
11914 /*
11915 * ARGF is a stream designed for use in scripts that process files given
11916 * as command-line arguments or passed in via STDIN.
11917 *
11918 * See ARGF (the class) for more details.
11919 */
11920 rb_define_global_const("ARGF", argf);
11921
11922 rb_define_hooked_variable("$.", &argf, argf_lineno_getter, argf_lineno_setter);
11923 rb_define_hooked_variable("$FILENAME", &argf, argf_filename_getter, rb_gvar_readonly_setter);
11924 ARGF.filename = rb_str_new2("-");
11925
11926 rb_define_hooked_variable("$-i", &argf, opt_i_get, opt_i_set);
11927 rb_define_hooked_variable("$*", &argf, argf_argv_getter, rb_gvar_readonly_setter);
11928
11929 #if defined (_WIN32) || defined(__CYGWIN__)
11930 atexit(pipe_atexit);
11931 #endif
11932
11933 Init_File();
11934
11935 rb_define_method(rb_cFile, "initialize", rb_file_initialize, -1);
11936
11937 sym_mode = ID2SYM(rb_intern("mode"));
11938 sym_perm = ID2SYM(rb_intern("perm"));
11939 sym_extenc = ID2SYM(rb_intern("external_encoding"));
11940 sym_intenc = ID2SYM(rb_intern("internal_encoding"));
11941 sym_encoding = ID2SYM(rb_intern("encoding"));
11942 sym_open_args = ID2SYM(rb_intern("open_args"));
11943 sym_textmode = ID2SYM(rb_intern("textmode"));
11944 sym_binmode = ID2SYM(rb_intern("binmode"));
11945 sym_autoclose = ID2SYM(rb_intern("autoclose"));
11946 sym_normal = ID2SYM(rb_intern("normal"));
11947 sym_sequential = ID2SYM(rb_intern("sequential"));
11948 sym_random = ID2SYM(rb_intern("random"));
11949 sym_willneed = ID2SYM(rb_intern("willneed"));
11950 sym_dontneed = ID2SYM(rb_intern("dontneed"));
11951 sym_noreuse = ID2SYM(rb_intern("noreuse"));
11952 }
argf_bytes
static VALUE argf_bytes(VALUE argf)
Definition: io.c:11076
data
VALUE data
Definition: tcltklib.c:3368
ARGVSTR2ARGV
#define ARGVSTR2ARGV(argv_str)
RB_TYPE_P
#define RB_TYPE_P(obj, type)
RARRAY_PTR
RARRAY_PTR(q->result)[0]
read_internal_arg::len
long len
Definition: io.c:2360
make_readconv
static void make_readconv(rb_io_t *fptr, int size)
Definition: io.c:2104
ALLOC
#define ALLOC(type)
tmp
volatile VALUE tmp
Definition: tcltklib.c:10209
rb_eStandardError
VALUE rb_eStandardError
Definition: error.c:509
rb_io_rewind
static VALUE rb_io_rewind(VALUE io)
Definition: io.c:1617
rb_io_close_read
static VALUE rb_io_close_read(VALUE io)
Definition: io.c:4348
rb_str_locktmp_ensure
VALUE rb_str_locktmp_ensure(VALUE str, VALUE(*func)(VALUE), VALUE arg)
Definition: string.c:1830
rb_obj_display
static VALUE rb_obj_display(int argc, VALUE *argv, VALUE self)
Definition: io.c:7034
nogvl_copy_stream_wait_write
static int nogvl_copy_stream_wait_write(struct copy_stream_struct *stp)
Definition: io.c:9700
fcntl_narg_len
static long fcntl_narg_len(int cmd)
Definition: io.c:8701
rb_io_set_lineno
static VALUE rb_io_set_lineno(VALUE io, VALUE lineno)
Definition: io.c:3197
id_set_encoding
static ID id_set_encoding
Definition: io.c:148
FilePathValue
#define FilePathValue(v)
n
ssize_t n
Definition: bigdecimal.c:5655
rb_io_open_with_args
static VALUE rb_io_open_with_args(int argc, VALUE *argv)
Definition: io.c:6409
sym
VALUE sym
Definition: tkutil.c:1299
io_internal_write_struct::capa
size_t capa
Definition: io.c:907
ary
volatile VALUE ary
Definition: tcltklib.c:9713
copy_stream_struct::total
off_t total
Definition: io.c:9631
argf_getpartial
static VALUE argf_getpartial(int argc, VALUE *argv, VALUE argf, int nonblock)
Definition: io.c:10784
argf_call_arg::argf
VALUE argf
Definition: io.c:10719
copy_stream_struct::error_no
int error_no
Definition: io.c:9633
int
VP_EXPORT int
Definition: bigdecimal.c:5050
rb_ary_new4
VALUE rb_ary_new4(long n, const VALUE *elts)
Definition: array.c:451
rb_io_set_sync
static VALUE rb_io_set_sync(VALUE io, VALUE sync)
Definition: io.c:1817
rb_ary_entry
VALUE rb_ary_entry(VALUE ary, long offset)
Definition: array.c:1101
rb_any_to_s
VALUE rb_any_to_s(VALUE)
Definition: object.c:384
ioctl_arg
Definition: io.c:8498
rb_set_class_path
void rb_set_class_path(VALUE, VALUE, const char *)
Definition: variable.c:308
rb_bug
void rb_bug(const char *fmt,...)
Definition: error.c:290
FALSE
#define FALSE
Definition: nkf.h:174
ioctl
int ioctl(int, int,...)
Definition: win32.c:2438
rb_io_internal_encoding
static VALUE rb_io_internal_encoding(VALUE)
Definition: io.c:10330
rb_io_s_readlines
static VALUE rb_io_s_readlines(int argc, VALUE *argv, VALUE io)
Definition: io.c:9382
FMODE_READWRITE
#define FMODE_READWRITE
Definition: io.h:105
rb_hash_lookup
#define rb_hash_lookup
Definition: tcltklib.c:268
sym_random
static VALUE sym_random
Definition: io.c:8246
th
static VALUE VALUE th
Definition: tcltklib.c:2948
rb_io_closed
static VALUE rb_io_closed(VALUE io)
Definition: io.c:4310
SSIZE_MAX
#define SSIZE_MAX
Definition: ruby.h:298
rb_io_check_readable
void rb_io_check_readable(rb_io_t *)
Definition: io.c:781
strlen
size_t strlen(const char *)
enc2
gz enc2
Definition: zlib.c:2274
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)
io_enc_str
static VALUE io_enc_str(VALUE str, rb_io_t *fptr)
Definition: io.c:2096
OBJ_INFECT
#define OBJ_INFECT(x, s)
rb_io_set_nonblock
void rb_io_set_nonblock(rb_io_t *fptr)
Definition: io.c:2338
rb_thread_wait_fd
void rb_thread_wait_fd(int)
Definition: thread.c:3431
rb_class_new_instance
VALUE rb_class_new_instance(int, VALUE *, VALUE)
Definition: object.c:1775
dln.h
FIX2UINT
#define FIX2UINT(x)
sym_autoclose
static VALUE sym_autoclose
Definition: io.c:150
rb_io_synchronized
void rb_io_synchronized(rb_io_t *)
Definition: io.c:5544
setup_narg
static long setup_narg(ioctl_req_t cmd, VALUE *argp, int io_p)
Definition: io.c:8708
sym_encoding
static VALUE sym_encoding
Definition: io.c:149
rb_obj_classname
const char * rb_obj_classname(VALUE)
Definition: variable.c:396
rb_str_buf_cat_ascii
VALUE rb_str_buf_cat_ascii(VALUE, const char *)
Definition: string.c:2081
argf_set_pos
static VALUE argf_set_pos(VALUE argf, VALUE offset)
Definition: io.c:10528
id_getc
static ID id_getc
Definition: io.c:148
p
Win32OLEIDispatch * p
Definition: win32ole.c:786
rb_io_codepoints
static VALUE rb_io_codepoints(VALUE io)
Definition: io.c:3630
sym_noreuse
static VALUE sym_noreuse
Definition: io.c:8246
argf_set_lineno
static VALUE argf_set_lineno(VALUE argf, VALUE val)
Definition: io.c:7584
argf_inplace_mode_get
static VALUE argf_inplace_mode_get(VALUE argf)
Definition: io.c:11354
rb_f_putc
static VALUE rb_f_putc(VALUE recv, VALUE ch)
Definition: io.c:6825
argf_readpartial
static VALUE argf_readpartial(int argc, VALUE *argv, VALUE argf)
Definition: io.c:10764
count
int count
Definition: encoding.c:51
ECONV_AFTER_OUTPUT
#define ECONV_AFTER_OUTPUT
io_call_close
static VALUE io_call_close(VALUE io)
Definition: io.c:4279
max
static int max(int a, int b)
Definition: strftime.c:141
id_read
static ID id_read
Definition: io.c:148
io_fflush
static int io_fflush(rb_io_t *)
Definition: io.c:1049
ENCODING_MAXNAMELEN
#define ENCODING_MAXNAMELEN
pair
volatile VALUE pair
Definition: tkutil.c:554
getuid
rb_uid_t getuid(void)
Definition: win32.c:2392
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:1497
rb_gets
VALUE rb_gets(void)
Definition: io.c:7920
rb_io_modestr_oflags
int rb_io_modestr_oflags(const char *modestr)
Definition: io.c:4845
rb_io_fmode_modestr
static const char * rb_io_fmode_modestr(int fmode)
Definition: io.c:4690
argf_init
static void argf_init(struct argf *p, VALUE v)
Definition: io.c:7520
rb_io_ioctl
static VALUE rb_io_ioctl(int argc, VALUE *argv, VALUE io)
Definition: io.c:8787
argf_inplace_mode_set
static VALUE argf_inplace_mode_set(VALUE argf, VALUE val)
Definition: io.c:11387
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:2872
ruby.h
ioctl_req_t
int ioctl_req_t
Definition: io.c:8494
sysopen_struct::fname
VALUE fname
Definition: io.c:5232
out
C_block * out
Definition: crypt.c:308
pipe_open
static VALUE pipe_open(VALUE execarg_obj, const char *modestr, int fmode, convconfig_t *convconfig)
Definition: io.c:5709
econv_finished
Definition: ripper.y:247
rb_stdout
RUBY_EXTERN VALUE rb_stdout
Definition: ripper.y:1500
rb_io_puts
VALUE rb_io_puts(int, VALUE *, VALUE)
Definition: io.c:6890
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:7087
binwrite_arg::str
VALUE str
Definition: io.c:1182
io_s_write
static VALUE io_s_write(int argc, VALUE *argv, int binary)
Definition: io.c:9513
select_call
static VALUE select_call(VALUE arg)
Definition: io.c:8228
rb_io_ungetc
VALUE rb_io_ungetc(VALUE, VALUE)
Definition: io.c:3797
rb_io_eof
VALUE rb_io_eof(VALUE)
Definition: io.c:1706
PIDT2NUM
#define PIDT2NUM(v)
Definition: ruby.h:329
argf_readbyte
static VALUE argf_readbyte(VALUE argf)
Definition: io.c:10968
ARGF_FORWARD
#define ARGF_FORWARD(argc, argv)
Definition: io.c:7619
argf_gets
static VALUE argf_gets(int, VALUE *, VALUE)
Definition: io.c:7909
rb_mWaitReadable
RUBY_EXTERN VALUE rb_mWaitReadable
Definition: ripper.y:1422
rb_usascii_str_new2
#define rb_usascii_str_new2
siz
size_t siz
Definition: strlcat.c:49
rb_io_t
struct rb_io_t rb_io_t
rb_secure
void rb_secure(int)
Definition: safe.c:79
rb_enc_codepoint
#define rb_enc_codepoint(p, e, enc)
select_args::fdsets
rb_fdset_t fdsets[4]
Definition: io.c:8224
rb_io_t::cbuf
rb_io_buffer_t cbuf
Definition: io.h:90
rb_syswait
void rb_syswait(rb_pid_t pid)
Definition: process.c:3639
argf_mark
static void argf_mark(void *ptr)
Definition: io.c:7487
rb_io_t::rb_io_enc_t::ecopts
VALUE ecopts
Definition: io.h:86
io_puts_ary
static VALUE io_puts_ary(VALUE ary, VALUE out, int recur)
Definition: io.c:6850
rb_define_global_const
void rb_define_global_const(const char *, VALUE)
Definition: variable.c:2216
rb_io_binmode_p
static VALUE rb_io_binmode_p(VALUE io)
Definition: io.c:4682
rb_p
void rb_p(VALUE)
Definition: io.c:6939
i
ssize_t i
Definition: bigdecimal.c:5655
rb_pipe
int rb_pipe(int *pipes)
Definition: io.c:5557
rb_io_t
Definition: io.h:63
rb_str_locktmp
VALUE rb_str_locktmp(VALUE)
rb_io_write_nonblock
static VALUE rb_io_write_nonblock(VALUE io, VALUE str)
Definition: io.c:2610
rb_check_frozen
#define rb_check_frozen(obj)
io_internal_read_struct::buf
void * buf
Definition: io.c:900
memmove
RUBY_EXTERN void * memmove(void *, const void *, size_t)
Definition: memmove.c:7
rb_io_check_initialized
void rb_io_check_initialized(rb_io_t *)
Definition: io.c:596
READ_DATA_PENDING_COUNT
#define READ_DATA_PENDING_COUNT(fptr)
Definition: io.c:372
rb_ary_shift
VALUE rb_ary_shift(VALUE ary)
Definition: array.c:929
rb_enc_name
#define rb_enc_name(enc)
bufread_arg::str_ptr
char * str_ptr
Definition: io.c:2025
IO_WBUF_CAPA_MIN
#define IO_WBUF_CAPA_MIN
Definition: io.c:123
F_DUPFD
#define F_DUPFD
Definition: win32.h:581
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:1317
orig_stderr
static VALUE orig_stderr
Definition: io.c:139
io_s_foreach
static VALUE io_s_foreach(struct foreach_arg *arg)
Definition: io.c:9307
FMODE_WRITABLE
#define FMODE_WRITABLE
Definition: io.h:104
rb_hash_lookup2
VALUE rb_hash_lookup2(VALUE, VALUE, VALUE)
Definition: hash.c:571
rb_to_encoding
rb_encoding * rb_to_encoding(VALUE enc)
Definition: encoding.c:194
rb_str_new_cstr
VALUE rb_str_new_cstr(const char *)
Definition: string.c:447
is_popen_fork
static int is_popen_fork(VALUE prog)
Definition: io.c:5933
FMODE_READABLE
#define FMODE_READABLE
Definition: io.h:103
ret
int ret
Definition: tcltklib.c:280
io_flush_buffer_async
static VALUE io_flush_buffer_async(VALUE arg)
Definition: io.c:1009
rb_io_bufwrite
ssize_t rb_io_bufwrite(VALUE io, const void *buf, size_t size)
Definition: io.c:1352
io_binwrite_string
static VALUE io_binwrite_string(VALUE arg)
Definition: io.c:1194
argf_call_arg::argc
int argc
Definition: io.c:10717
io_encoding_set
static void io_encoding_set(rb_io_t *, VALUE, VALUE, VALUE)
Definition: io.c:9067
rb_io_syswrite
static VALUE rb_io_syswrite(VALUE io, VALUE str)
Definition: io.c:4500
FMODE_WSPLIT_INITIALIZED
#define FMODE_WSPLIT_INITIALIZED
Definition: io.h:114
rb_enc_from_encoding
VALUE rb_enc_from_encoding(rb_encoding *encoding)
Definition: encoding.c:103
find_encoding
static rb_encoding * find_encoding(VALUE v)
Definition: io.c:9059
rb_frame_this_func
ID rb_frame_this_func(void)
Definition: eval.c:902
status
int status
Definition: tcltklib.c:2197
argf_external_encoding
static VALUE argf_external_encoding(VALUE argf)
Definition: io.c:10402
rb_w32_get_osfhandle
SOCKET rb_w32_get_osfhandle(int)
Definition: win32.c:958
rb_obj_freeze
VALUE rb_obj_freeze(VALUE)
Definition: object.c:989
rb_io_printf
VALUE rb_io_printf(int, VALUE *, VALUE)
Definition: io.c:6666
argf_call_arg
Definition: io.c:10716
rb_eTypeError
VALUE rb_eTypeError
Definition: error.c:511
id_write
static ID id_write
Definition: io.c:148
sym_mode
static VALUE sym_mode
Definition: io.c:149
rb_define_hooked_variable
void rb_define_hooked_variable(const char *, VALUE *, VALUE(*)(ANYARGS), void(*)(ANYARGS))
Definition: variable.c:575
OBJ_FREEZE
#define OBJ_FREEZE(x)
argf_each_line
static VALUE argf_each_line(int argc, VALUE *argv, VALUE argf)
Definition: io.c:11013
rb_obj_dup
VALUE rb_obj_dup(VALUE)
Definition: object.c:338
rb_define_alloc_func
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
rb_execarg_extract_options
VALUE rb_execarg_extract_options(VALUE execarg_obj, VALUE opthash)
Definition: process.c:1897
ECONV_NEWLINE_DECORATOR_MASK
#define ECONV_NEWLINE_DECORATOR_MASK
OBJ_TAINTED
#define OBJ_TAINTED(x)
UNREACHABLE
#define UNREACHABLE
Definition: ruby.h:40
ruby_strtoul
unsigned long ruby_strtoul(const char *str, char **endptr, int base)
Definition: util.c:106
rb_io_close_write
static VALUE rb_io_close_write(VALUE io)
Definition: io.c:4411
rb_update_max_fd
void rb_update_max_fd(int fd)
Definition: io.c:164
argf_call_arg::argv
VALUE * argv
Definition: io.c:10718
rb_default_internal_encoding
rb_encoding * rb_default_internal_encoding(void)
Definition: encoding.c:1373
exc
VALUE exc
Definition: tcltklib.c:3096
argf_filename
static VALUE argf_filename(VALUE argf)
Definition: io.c:11187
enc
VALUE enc
Definition: tcltklib.c:10311
RUBY_UBF_IO
#define RUBY_UBF_IO
rb_ary_push
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:822
fptr_finalize
static void fptr_finalize(rb_io_t *fptr, int noraise)
Definition: io.c:4082
rb_io_check_byte_readable
void rb_io_check_byte_readable(rb_io_t *fptr)
Definition: io.c:772
rb_io_fcntl
#define rb_io_fcntl
Definition: io.c:8889
opt_i_get
static VALUE opt_i_get(ID id, VALUE *var)
Definition: io.c:11361
fcntl
int fcntl(int, int,...)
Definition: win32.c:3835
path
gz path
Definition: zlib.c:2279
TYPE
#define TYPE(x)
rb_enc_uint_chr
VALUE rb_enc_uint_chr(unsigned int code, rb_encoding *enc)
Definition: numeric.c:2417
rb_econv_prepare_options
int rb_econv_prepare_options(VALUE opthash, VALUE *ecopts, int ecflags)
Definition: transcode.c:2519
rb_ary_tmp_new
VALUE rb_ary_tmp_new(long capa)
Definition: array.c:465
argf_argv
static VALUE argf_argv(VALUE argf)
Definition: io.c:11440
io_encname_bom_p
static int io_encname_bom_p(const char *name, long len)
Definition: io.c:4714
rb_io_seek
static VALUE rb_io_seek(VALUE io, VALUE offset, int whence)
Definition: io.c:1524
RSTRING_PTR
#define RSTRING_PTR(str)
CLASS_OF
#define CLASS_OF(v)
rb_io_getline_fast
static VALUE rb_io_getline_fast(rb_io_t *fptr, rb_encoding *enc, VALUE io)
Definition: io.c:2890
NIL_P
NIL_P(eventloop_thread)
Definition: tcltklib.c:4068
rb_lastline_set
void rb_lastline_set(VALUE)
Definition: vm.c:780
RFILE
#define RFILE(obj)
T_ARRAY
#define T_ARRAY
rb_enc_str_new
VALUE rb_enc_str_new(const char *, long, rb_encoding *)
Definition: string.c:439
rb_io_buffer_t::ptr
char * ptr
Definition: io.h:57
argf::binmode
int8_t binmode
Definition: io.c:159
rb_io_t::writeconv_pre_ecflags
int writeconv_pre_ecflags
Definition: io.h:94
var
VALUE var
Definition: tcltklib.c:5517
rb_protect
VALUE rb_protect(VALUE(*proc)(VALUE), VALUE data, int *state)
Definition: eval.c:771
bufread_arg::fptr
rb_io_t * fptr
Definition: io.c:2027
xfree
#define xfree
MBCLEN_NEEDMORE_P
#define MBCLEN_NEEDMORE_P(ret)
rb_funcall
VALUE rb_funcall(VALUE, ID, int,...)
Calls a method.
Definition: vm_eval.c:774
rb_io_readchar
static VALUE rb_io_readchar(VALUE io)
Definition: io.c:3678
rb_io_modestr_fmode
int rb_io_modestr_fmode(const char *modestr)
Definition: io.c:4726
argf_write
static VALUE argf_write(VALUE argf, VALUE str)
Definition: io.c:11480
rb_sysopen_internal
static int rb_sysopen_internal(struct sysopen_struct *data)
Definition: io.c:5246
MEMMOVE
#define MEMMOVE(p1, p2, type, n)
tp
register C_block * tp
Definition: crypt.c:311
rb_raise
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:1780
rb_io_fptr_finalize
int rb_io_fptr_finalize(rb_io_t *)
Definition: io.c:4186
rb_io_sysseek
static VALUE rb_io_sysseek(int argc, VALUE *argv, VALUE io)
Definition: io.c:4460
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:558
rb_io_t::writeconv_initialized
int writeconv_initialized
Definition: io.h:96
Qtrue
return Qtrue
Definition: tcltklib.c:9610
rb_str_new4
#define rb_str_new4
FMODE_CREATE
#define FMODE_CREATE
Definition: io.h:111
rb_enc_associate
VALUE rb_enc_associate(VALUE obj, rb_encoding *enc)
Definition: encoding.c:766
rb_execarg_new
VALUE rb_execarg_new(int argc, VALUE *argv, int accept_shell)
Definition: process.c:2190
rb_obj_class
VALUE rb_obj_class(VALUE)
Definition: object.c:194
RETURN_ENUMERATOR
#define RETURN_ENUMERATOR(obj, argc, argv)
rb_ary_clear
VALUE rb_ary_clear(VALUE ary)
Definition: array.c:3220
pipe_add_fptr
static void pipe_add_fptr(rb_io_t *fptr)
Definition: io.c:5479
rb_io_taint_check
VALUE rb_io_taint_check(VALUE)
Definition: io.c:587
copy_stream_struct::close_src
int close_src
Definition: io.c:9629
rb_str_encode_ospath
VALUE rb_str_encode_ospath(VALUE)
Definition: file.c:230
rb_class_name
VALUE rb_class_name(VALUE)
Definition: variable.c:383
argf_binmode_p
static VALUE argf_binmode_p(VALUE argf)
Definition: io.c:11259
NEED_WRITECONV
#define NEED_WRITECONV(fptr)
Definition: io.c:554
rb_enc_left_char_head
#define rb_enc_left_char_head(s, p, e, enc)
T_FILE
#define T_FILE
argf::lineno
long lineno
Definition: io.c:155
rb_file_initialize
static VALUE rb_file_initialize(int argc, VALUE *argv, VALUE io)
Definition: io.c:7391
argf_write_io
static VALUE argf_write_io(VALUE argf)
Definition: io.c:11465
FMODE_DUPLEX
#define FMODE_DUPLEX
Definition: io.h:109
finish_writeconv_arg
Definition: io.c:4031
SafeStringValue
#define SafeStringValue(v)
ruby_dup
static int ruby_dup(int orig)
Definition: io.c:843
rb_eIOError
RUBY_EXTERN VALUE rb_eIOError
Definition: ripper.y:1476
rb_output_rs
RUBY_EXTERN VALUE rb_output_rs
Definition: ripper.y:491
rb_enc_mbclen
int rb_enc_mbclen(const char *p, const char *e, rb_encoding *enc)
Definition: encoding.c:886
FMODE_BINMODE
#define FMODE_BINMODE
Definition: io.h:106
STDIO_READ_DATA_PENDING
#define STDIO_READ_DATA_PENDING(fp)
Definition: io.c:366
rb_eSecurityError
VALUE rb_eSecurityError
Definition: error.c:520
FMODE_APPEND
#define FMODE_APPEND
Definition: io.h:110
rb_include_module
void rb_include_module(VALUE klass, VALUE module)
Definition: class.c:695
MORE_CHAR_FINISHED
#define MORE_CHAR_FINISHED
Definition: io.c:2131
rb_last_status_clear
void rb_last_status_clear(void)
Definition: process.c:285
more_char
static VALUE more_char(rb_io_t *fptr)
Definition: io.c:2207
rb_io_s_sysopen
static VALUE rb_io_s_sysopen(int argc, VALUE *argv)
Definition: io.c:6211
r
r
Definition: bigdecimal.c:1196
argf_lineno
static VALUE argf_lineno(VALUE argf)
Definition: io.c:7605
copy_stream_struct::copy_length
off_t copy_length
Definition: io.c:9624
rb_str_new2
#define rb_str_new2
argf
Definition: io.c:152
copy_stream_struct::dst_fd
int dst_fd
Definition: io.c:9628
prepare_getline_args
static void prepare_getline_args(int argc, VALUE *argv, VALUE *rsp, long *limit, VALUE io)
Definition: io.c:2944
rb_define_global_function
void rb_define_global_function(const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a global function.
Definition: class.c:1526
timeval::tv_sec
long tv_sec
Definition: ossl_asn1.c:17
rb_cloexec_dup
int rb_cloexec_dup(int oldfd)
Definition: io.c:225
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:5407
rb_lastline_get
VALUE rb_lastline_get(void)
Definition: vm.c:774
state
int state
Definition: tcltklib.c:1462
internal_write_func
static VALUE internal_write_func(void *ptr)
Definition: io.c:918
rb_str_unlocktmp
VALUE rb_str_unlocktmp(VALUE)
Definition: string.c:1820
last
unsigned int last
Definition: nkf.c:4310
rb_io_each_byte
static VALUE rb_io_each_byte(VALUE io)
Definition: io.c:3338
rb_io_t::writeconv_pre_ecopts
VALUE writeconv_pre_ecopts
Definition: io.h:95
rb_str_substr
VALUE rb_str_substr(VALUE, long, long)
Definition: string.c:1774
argf_close
static void argf_close(VALUE file)
Definition: io.c:7629
open_key_args
static void open_key_args(int argc, VALUE *argv, VALUE opt, struct foreach_arg *arg)
Definition: io.c:9270
argf_readchar
static VALUE argf_readchar(VALUE argf)
Definition: io.c:10928
copy_stream_struct::syserr
const char * syserr
Definition: io.c:9632
rb_io_external_encoding
static VALUE rb_io_external_encoding(VALUE io)
Definition: io.c:10305
ID2SYM
#define ID2SYM(x)
rb_f_readlines
static VALUE rb_f_readlines(int argc, VALUE *argv, VALUE recv)
Definition: io.c:8011
io_set_read_length
static void io_set_read_length(VALUE str, long n)
Definition: io.c:2268
argf_next_argv
static int argf_next_argv(VALUE argf)
Definition: io.c:7639
args
VALUE VALUE args
Definition: tcltklib.c:2561
rb_io_t::rb_io_enc_t::enc2
rb_encoding * enc2
Definition: io.h:84
argf_type
static const rb_data_type_t argf_type
Definition: io.c:7514
io_fwrite
static long io_fwrite(VALUE str, rb_io_t *fptr, int nosync)
Definition: io.c:1338
rb_f_open
static VALUE rb_f_open(int argc, VALUE *argv)
Definition: io.c:6352
argf_each_codepoint
static VALUE argf_each_codepoint(VALUE argf)
Definition: io.c:11141
ENC_CODERANGE_BROKEN
#define ENC_CODERANGE_BROKEN
rb_io_read_check
void rb_io_read_check(rb_io_t *)
Definition: io.c:834
GetOpenFile
#define GetOpenFile(obj, fp)
Definition: io.h:120
rb_write_internal2
static ssize_t rb_write_internal2(int fd, const void *buf, size_t count)
Definition: io.c:954
rb_execarg::envp_str
VALUE envp_str
Definition: ripper.y:221
rb_str_append
VALUE rb_str_append(VALUE, VALUE)
Definition: string.c:2121
rb_str_new_frozen
VALUE rb_str_new_frozen(VALUE)
Definition: string.c:713
rb_f_p_arg::argc
int argc
Definition: io.c:6954
copy_stream_struct
Definition: io.c:9621
io.h
nogvl_ioctl
static VALUE nogvl_ioctl(void *ptr)
Definition: io.c:8505
validate_enc_binmode
static void validate_enc_binmode(int *fmode_p, int ecflags, rb_encoding *enc, rb_encoding *enc2)
Definition: io.c:5056
rb_f_p_internal
static VALUE rb_f_p_internal(VALUE arg)
Definition: io.c:6959
rb_io_buffer_t::capa
int capa
Definition: io.h:60
rb_f_sprintf
VALUE rb_f_sprintf(int, const VALUE *)
Definition: sprintf.c:433
io_tell
#define io_tell(fptr)
Definition: io.c:744
rb_io_tell
static VALUE rb_io_tell(VALUE io)
Definition: io.c:1511
binwrite_arg::ptr
const char * ptr
Definition: io.c:1183
flag
flag
Definition: tcltklib.c:2048
argf::argv
VALUE argv
Definition: io.c:156
rb_str_modify_expand
void rb_str_modify_expand(VALUE, long)
Definition: string.c:1377
rb_fd_term
#define rb_fd_term(f)
argf
static VALUE argf
Definition: io.c:146
io_check_tty
static void io_check_tty(rb_io_t *fptr)
Definition: io.c:5318
rb_fd_max
#define rb_fd_max(f)
rb_fd_fix_cloexec
void rb_fd_fix_cloexec(int fd)
Definition: io.c:202
rb_mWaitWritable
RUBY_EXTERN VALUE rb_mWaitWritable
Definition: ripper.y:1423
lineno
gz lineno
Definition: zlib.c:2270
argf_seek_m
static VALUE argf_seek_m(int argc, VALUE *argv, VALUE argf)
Definition: io.c:10507
opt_i_set
static void opt_i_set(VALUE val, ID id, VALUE *var)
Definition: io.c:11406
GetWriteIO
#define GetWriteIO(io)
Definition: io.c:369
ENCODING_GET
#define ENCODING_GET(obj)
argf::last_lineno
long last_lineno
Definition: io.c:154
read_all
static VALUE read_all(rb_io_t *fptr, long siz, VALUE str)
Definition: io.c:2277
exec_interrupts
static void * exec_interrupts(void *arg)
Definition: io.c:9640
id.h
__sFILE
Definition: vsnprintf.c:175
rb_io_t::mode
int mode
Definition: io.h:66
rb_io_set_autoclose
static VALUE rb_io_set_autoclose(VALUE io, VALUE autoclose)
Definition: io.c:7474
maygvl_read
static ssize_t maygvl_read(int has_gvl, int fd, void *buf, size_t count)
Definition: io.c:9876
io_read_encoding
static rb_encoding * io_read_encoding(rb_io_t *fptr)
Definition: io.c:787
rb_io_s_popen
static VALUE rb_io_s_popen(int argc, VALUE *argv, VALUE klass)
Definition: io.c:6047
rb_io_lines
static VALUE rb_io_lines(int argc, VALUE *argv, VALUE io)
Definition: io.c:3312
MEMZERO
#define MEMZERO(p, type, n)
rb_enumeratorize
VALUE rb_enumeratorize(VALUE obj, VALUE meth, int argc, VALUE *argv)
Definition: enumerator.c:398
rb_exc_raise
void rb_exc_raise(VALUE mesg)
Definition: eval.c:527
ECONV_ERROR_HANDLER_MASK
#define ECONV_ERROR_HANDLER_MASK
SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2
#define SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags)
Definition: io.c:557
rb_io_set_close_on_exec
#define rb_io_set_close_on_exec
Definition: io.c:3961
NUM2OFFT
#define NUM2OFFT(x)
rb_usascii_str_new
VALUE rb_usascii_str_new(const char *, long)
Definition: string.c:431
select_args
Definition: io.c:8221
rb_io_sysread
static VALUE rb_io_sysread(int argc, VALUE *argv, VALUE io)
Definition: io.c:4545
ioctl_arg::narg
long narg
Definition: io.c:8501
io_ungetbyte
static void io_ungetbyte(VALUE str, rb_io_t *fptr)
Definition: io.c:701
ioctl_arg::cmd
ioctl_req_t cmd
Definition: io.c:8500
rb_file_open_internal
static VALUE rb_file_open_internal(VALUE io, VALUE filename, const char *modestr)
Definition: io.c:5433
rb_define_readonly_variable
void rb_define_readonly_variable(const char *, VALUE *)
Definition: variable.c:600
str_end_with_asciichar
static int str_end_with_asciichar(VALUE str, int c)
Definition: io.c:6835
ecflags
gz ecflags
Definition: zlib.c:2276
argf_binmode_m
static VALUE argf_binmode_m(VALUE argf)
Definition: io.c:11236
fmode
#define fmode
argf::current_file
VALUE current_file
Definition: io.c:153
O_CLOEXEC
#define O_CLOEXEC
rb_io_t::rb_io_enc_t::enc
rb_encoding * enc
Definition: io.h:83
rb_to_encoding_index
int rb_to_encoding_index(VALUE enc)
Definition: encoding.c:146
rb_default_external_encoding
rb_encoding * rb_default_external_encoding(void)
Definition: encoding.c:1288
rb_gc
void rb_gc(void)
Definition: gc.c:3108
io_internal_read_struct::fd
int fd
Definition: io.c:899
memset
memset(y->frac+ix+1, 0,(y->Prec-(ix+1))*sizeof(BDIGIT))
rb_fd_select
#define rb_fd_select(n, rfds, wfds, efds, timeout)
rb_rescue
VALUE rb_rescue(VALUE(*b_proc)(ANYARGS), VALUE data1, VALUE(*r_proc)(ANYARGS), VALUE data2)
Definition: eval.c:763
m
BDIGIT m
Definition: bigdecimal.c:5085
copy_stream_fallback_body
static VALUE copy_stream_fallback_body(VALUE arg)
Definition: io.c:10033
copy_stream_struct::src_offset
off_t src_offset
Definition: io.c:9625
thread.h
io_internal_write_struct::fd
int fd
Definition: io.c:905
orig_stdout
static VALUE orig_stdout
Definition: io.c:139
FIXNUM_P
#define FIXNUM_P(f)
Qfalse
return Qfalse
Definition: tcltklib.c:6779
rb_io_get_write_io
VALUE rb_io_get_write_io(VALUE io)
Definition: io.c:626
bufread_arg::len
long len
Definition: io.c:2026
io_internal_write_struct
Definition: io.c:904
argf_lines
static VALUE argf_lines(int argc, VALUE *argv, VALUE argf)
Definition: io.c:11028
nogvl_close
static void * nogvl_close(void *ptr)
Definition: io.c:4044
io_internal_write_struct::buf
const void * buf
Definition: io.c:906
rb_block_given_p
int rb_block_given_p(void)
Definition: eval.c:672
rb_io_unbuffered
void rb_io_unbuffered(rb_io_t *fptr)
Definition: io.c:5551
ruby_atomic.h
RARRAY_LEN
#define RARRAY_LEN(a)
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
argf_internal_encoding
static VALUE argf_internal_encoding(VALUE argf)
Definition: io.c:10424
F_SETFL
#define F_SETFL
Definition: win32.h:587
Qnil
#define Qnil
Definition: tcltklib.c:1896
StringValuePtr
#define StringValuePtr(v)
write_arg::nosync
int nosync
Definition: io.c:1190
val
#define val
Definition: tcltklib.c:1949
io_readpartial
static VALUE io_readpartial(int argc, VALUE *argv, VALUE io)
Definition: io.c:2484
argf_getbyte
static VALUE argf_getbyte(VALUE argf)
Definition: io.c:10888
rb_sys_fail_path
#define rb_sys_fail_path(path)
Definition: io.c:408
stdout_setter
static void stdout_setter(VALUE val, ID id, VALUE *variable)
Definition: io.c:7097
timeval::tv_usec
long tv_usec
Definition: ossl_asn1.c:18
rb_f_backquote
static VALUE rb_f_backquote(VALUE obj, VALUE str)
Definition: io.c:8074
rb_eRuntimeError
VALUE rb_eRuntimeError
Definition: error.c:510
PREP_STDIO_NAME
#define PREP_STDIO_NAME(f)
Definition: io.c:3966
pipe_list
static struct pipe_list * pipe_list
argf_readlines
static VALUE argf_readlines(int, VALUE *, VALUE)
Definition: io.c:8036
argf_getline
static VALUE argf_getline(int argc, VALUE *argv, VALUE argf)
Definition: io.c:7804
FMODE_SETENC_BY_BOM
#define FMODE_SETENC_BY_BOM
Definition: io.h:118
numberof
#define numberof(array)
Definition: io.c:118
rb_deferr
VALUE rb_deferr
Definition: io.c:138
copy_stream_struct::close_dst
int close_dst
Definition: io.c:9630
rb_mKernel
RUBY_EXTERN VALUE rb_mKernel
Definition: ripper.y:1414
rb_file_open
VALUE rb_file_open(const char *, const char *)
Definition: io.c:5467
rb_io_s_binread
static VALUE rb_io_s_binread(int argc, VALUE *argv, VALUE io)
Definition: io.c:9489
ruby_set_inplace_mode
void ruby_set_inplace_mode(const char *)
Definition: io.c:11418
str
static VALUE char * str
Definition: tcltklib.c:3547
ruby_strdup
char * ruby_strdup(const char *)
Definition: util.c:454
io_flush_buffer_sync
static VALUE io_flush_buffer_sync(void *arg)
Definition: io.c:977
rb_fdset_t
fd_set rb_fdset_t
Definition: ripper.y:326
io_strip_bom
static int io_strip_bom(VALUE io)
Definition: io.c:5328
rb_io_check_io
VALUE rb_io_check_io(VALUE io)
Definition: io.c:620
copy_stream_struct::src
VALUE src
Definition: io.c:9622
io_s_readlines
static VALUE io_s_readlines(struct foreach_arg *arg)
Definition: io.c:9358
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:9885
rb_ary_new
VALUE rb_ary_new(void)
Definition: array.c:424
rb_execarg_get
struct rb_execarg * rb_execarg_get(VALUE execarg_obj)
Definition: process.c:2201
Check_Type
#define Check_Type(v, t)
StringValueCStr
#define StringValueCStr(v)
rb_thread_io_blocking_region
VALUE rb_thread_io_blocking_region(rb_blocking_function_t *func, void *data1, int fd)
Definition: thread.c:1331
dp
#define dp(v)
Definition: vm_debug.h:23
flags
int flags
Definition: tcltklib.c:3023
rb_econv_binmode
void rb_econv_binmode(rb_econv_t *ec)
Definition: transcode.c:1934
ID
unsigned long ID
Definition: ripper.y:105
swallow
static int swallow(rb_io_t *fptr, int term)
Definition: io.c:2841
argf_set_encoding
static VALUE argf_set_encoding(int argc, VALUE *argv, VALUE argf)
Definition: io.c:10464
ARGF_GENERIC_INPUT_P
#define ARGF_GENERIC_INPUT_P()
Definition: io.c:7617
rb_gc_mark
void rb_gc_mark(VALUE)
Definition: gc.c:2598
copy_stream_struct::dst
VALUE dst
Definition: io.c:9623
rb_define_const
void rb_define_const(VALUE, const char *, VALUE)
Definition: variable.c:2202
pipe_finalize
static void pipe_finalize(rb_io_t *fptr, int noraise)
Definition: io.c:5526
copy_stream_fallback
static VALUE copy_stream_fallback(struct copy_stream_struct *stp)
Definition: io.c:10091
ISASCII
#define ISASCII(c)
Definition: ruby.h:1629
rb_str_cat2
VALUE rb_str_cat2(VALUE, const char *)
Definition: string.c:1982
sym_textmode
static VALUE sym_textmode
Definition: io.c:150
finish_writeconv_sync
static VALUE finish_writeconv_sync(VALUE arg)
Definition: io.c:4037
io_write
static VALUE io_write(VALUE io, VALUE str, int nosync)
Definition: io.c:1362
rb_f_puts
static VALUE rb_f_puts(int argc, VALUE *argv, VALUE recv)
Definition: io.c:6930
rb_define_class
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition: class.c:499
rb_cloexec_pipe
int rb_cloexec_pipe(int fildes[2])
Definition: io.c:271
pipe_pair_close
static VALUE pipe_pair_close(VALUE rw)
Definition: io.c:9130
obj
static VALUE VALUE obj
Definition: tcltklib.c:3158
RSTRING_LEN
#define RSTRING_LEN(str)
appendline
static int appendline(rb_io_t *fptr, int delim, VALUE *strp, long *lp)
Definition: io.c:2758
FIX2INT
#define FIX2INT(x)
INT2FIX
#define INT2FIX(i)
chown
int chown(const char *, int, int)
Definition: win32.c:4065
rb_io_t::fd
int fd
Definition: io.h:64
rb_check_to_integer
VALUE rb_check_to_integer(VALUE, const char *)
Definition: object.c:2417
idx
int idx
Definition: tcltklib.c:9716
rb_io_each_line
static VALUE rb_io_each_line(int argc, VALUE *argv, VALUE io)
Definition: io.c:3292
MODE_BINARY
#define MODE_BINARY(a, b)
rb_io_wait_writable
int rb_io_wait_writable(int)
Definition: io.c:1090
unistd.h
FIX2LONG
#define FIX2LONG(x)
argf::next_p
int8_t next_p
Definition: io.c:159
rb_sys_fail_str
void rb_sys_fail_str(VALUE mesg)
Definition: error.c:1905
select_internal
static VALUE select_internal(VALUE read, VALUE write, VALUE except, struct timeval *tp, rb_fdset_t *fds)
Definition: io.c:8097
ANYARGS
#define ANYARGS
rb_last_status_set
void rb_last_status_set(int status, rb_pid_t pid)
Definition: process.c:276
rb_io_each_char
static VALUE rb_io_each_char(VALUE io)
Definition: io.c:3497
T_STRING
#define T_STRING
rb_thread_alone
int rb_thread_alone(void)
Definition: thread.c:2904
argf_chars
static VALUE argf_chars(VALUE argf)
Definition: io.c:11116
rb_io_getline
static VALUE rb_io_getline(int argc, VALUE *argv, VALUE io)
Definition: io.c:3100
write_arg::str
VALUE str
Definition: io.c:1189
rb_gvar_readonly_setter
void rb_gvar_readonly_setter(VALUE val, ID id, void *data, struct rb_global_variable *gvar)
rb_fd_zero
#define rb_fd_zero(f)
MBCLEN_CHARFOUND_P
#define MBCLEN_CHARFOUND_P(ret)
rb_io_fdatasync
#define rb_io_fdatasync
Definition: io.c:1862
econv_invalid_byte_sequence
Definition: ripper.y:243
rb_io_t::encs
struct rb_io_t::rb_io_enc_t encs
Init_IO
void Init_IO(void)
Definition: io.c:11641
rb_close_before_exec
void rb_close_before_exec(int lowfd, int maxhint, VALUE noclose_fds)
nogvl_fclose
static void * nogvl_fclose(void *ptr)
Definition: io.c:4065
OBJ_INIT_COPY
#define OBJ_INIT_COPY(obj, orig)
NUM2IOCTLREQ
#define NUM2IOCTLREQ(num)
Definition: io.c:8495
READ_DATA_PENDING
#define READ_DATA_PENDING(fptr)
Definition: io.c:371
rb_io_t::writeconv_asciicompat
VALUE writeconv_asciicompat
Definition: io.h:93
FMODE_TRUNC
#define FMODE_TRUNC
Definition: io.h:115
finish_writeconv
static VALUE finish_writeconv(rb_io_t *fptr, int noalloc)
Definition: io.c:3969
copy_stream_struct::notimp
const char * notimp
Definition: io.c:9634
rb_io_print
VALUE rb_io_print(int, VALUE *, VALUE)
Definition: io.c:6725
rb_mutex_owned_p
VALUE rb_mutex_owned_p(VALUE self)
Definition: thread.c:4367
rb_io_t::pid
rb_pid_t pid
Definition: io.h:67
rb_check_hash_type
VALUE rb_check_hash_type(VALUE)
Definition: hash.c:461
LONG_MAX
#define LONG_MAX
Definition: ruby.h:201
NEED_NEWLINE_DECORATOR_ON_READ_CHECK
#define NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr)
Definition: io.c:556
rb_io_gets_m
static VALUE rb_io_gets_m(int argc, VALUE *argv, VALUE io)
Definition: io.c:3137
RUBY_FUNC_EXPORTED
#define RUBY_FUNC_EXPORTED
Definition: defines.h:184
rb_io_bufread
ssize_t rb_io_bufread(VALUE io, void *buf, size_t size)
Definition: io.c:2055
buf
unsigned char buf[MIME_BUF_SIZE]
Definition: nkf.c:4308
argf_eof
static VALUE argf_eof(VALUE argf)
Definition: io.c:10618
rb_io_buffer_t::len
int len
Definition: io.h:59
rb_maygvl_fd_fix_cloexec
void rb_maygvl_fd_fix_cloexec(int fd)
Definition: io.c:179
io_setstrbuf
static void io_setstrbuf(VALUE *str, long len)
Definition: io.c:2244
ARGF
#define ARGF
Definition: io.c:351
err
int err
Definition: win32.c:87
rb_thread_check_ints
void rb_thread_check_ints(void)
Definition: thread.c:1090
io_flush_buffer
static int io_flush_buffer(rb_io_t *fptr)
Definition: io.c:1035
argf_of
#define argf_of(obj)
Definition: io.c:350
perm
STATIC void C_block perm[64/CHUNKBITS][1<< CHUNKBITS]
Definition: crypt.c:904
Init_File
void Init_File(void)
Definition: file.c:5488
write_arg
Definition: io.c:1187
rb_f_printf
static VALUE rb_f_printf(int argc, VALUE *argv)
Definition: io.c:6684
rscheck
static void rscheck(const char *rsptr, long rslen, VALUE rs)
Definition: io.c:2750
rb_f_p_arg::argv
VALUE * argv
Definition: io.c:6955
rb_str_setter
void rb_str_setter(VALUE, ID, VALUE *)
Definition: string.c:7615
nogvl_copy_stream_write
static int nogvl_copy_stream_write(struct copy_stream_struct *stp, char *buf, size_t len)
Definition: io.c:9928
ENC_CODERANGE_SET
#define ENC_CODERANGE_SET(obj, cr)
argf_initialize
static VALUE argf_initialize(VALUE argf, VALUE argv)
Definition: io.c:7542
rb_f_syscall
#define rb_f_syscall
Definition: io.c:9049
rb_thread_call_without_gvl
void * rb_thread_call_without_gvl(void *(*func)(void *), void *data1, rb_unblock_function_t *ubf, void *data2)
io_getpartial
static VALUE io_getpartial(int argc, VALUE *argv, VALUE io, int nonblock)
Definition: io.c:2372
bufread_arg
Definition: io.c:2024
ATOMIC_CAS
#define ATOMIC_CAS(var, oldval, newval)
Definition: ruby_atomic.h:105
rb_io_seek_m
static VALUE rb_io_seek_m(int argc, VALUE *argv, VALUE io)
Definition: io.c:1559
ioctl_arg::fd
int fd
Definition: io.c:8499
EOF
#define EOF
Definition: vsnprintf.c:207
rb_str_buf_cat
VALUE rb_str_buf_cat(VALUE, const char *, long)
Definition: string.c:1947
copy_stream_struct::src_fd
int src_fd
Definition: io.c:9627
select_args::read
VALUE read
Definition: io.c:8222
rb_fd_set
#define rb_fd_set(n, f)
io_set_encoding_by_bom
static void io_set_encoding_by_bom(VALUE io)
Definition: io.c:5391
DEFAULT_TEXTMODE
#define DEFAULT_TEXTMODE
Definition: io.c:552
advice_arg_check
static void advice_arg_check(VALUE advice)
Definition: io.c:8334
IO_CBUF_CAPA_MIN
#define IO_CBUF_CAPA_MIN
Definition: io.c:121
rb_find_encoding
rb_encoding * rb_find_encoding(VALUE enc)
Definition: encoding.c:201
rb_obj_as_string
VALUE rb_obj_as_string(VALUE)
Definition: string.c:895
argv
VALUE * argv
Definition: tcltklib.c:1971
rb_enc_ascget
int rb_enc_ascget(const char *p, const char *e, int *len, rb_encoding *enc)
Definition: encoding.c:910
argf_alloc
static VALUE argf_alloc(VALUE klass)
Definition: io.c:7529
NEXT_ARGF_FORWARD
#define NEXT_ARGF_FORWARD(argc, argv)
Definition: io.c:7623
rb_hash_aset
VALUE rb_hash_aset(VALUE, VALUE, VALUE)
prep_io
static VALUE prep_io(int fd, int fmode, VALUE klass, const char *path)
Definition: io.c:7104
rb_define_alias
void rb_define_alias(VALUE klass, const char *name1, const char *name2)
Defines an alias of a method.
Definition: class.c:1539
rb_yield
VALUE rb_yield(VALUE)
Definition: vm_eval.c:934
econv_source_buffer_empty
Definition: ripper.y:246
rb_f_gets
static VALUE rb_f_gets(int argc, VALUE *argv, VALUE recv)
Definition: io.c:7885
rb_str_resize
VALUE rb_str_resize(VALUE, long)
Definition: string.c:1853
memcpy
memcpy(buf+1, str, len)
RTEST
#define RTEST(v)
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:4986
rb_io_t::wbuf
rb_io_buffer_t wbuf
Definition: io.h:72
rb_enc_mbminlen
#define rb_enc_mbminlen(enc)
timeval
Definition: ossl_asn1.c:16
errno
int errno
util.h
copy_stream_body
static VALUE copy_stream_body(VALUE arg)
Definition: io.c:10103
TRUE
#define TRUE
Definition: nkf.h:175
result
q result
Definition: tcltklib.c:7070
rb_thread_atfork
void rb_thread_atfork(void)
Definition: thread.c:3845
rb_thread_current
VALUE rb_thread_current(void)
Definition: thread.c:2350
off_t
#define off_t
Definition: io.c:65
seek_before_access
static VALUE seek_before_access(VALUE argp)
Definition: io.c:9406
S_ISREG
#define S_ISREG(m)
Definition: io.c:872
rb_io_set_pos
static VALUE rb_io_set_pos(VALUE io, VALUE offset)
Definition: io.c:1585
max_file_descriptor
static rb_atomic_t max_file_descriptor
Definition: io.c:162
rb_io_init_copy
static VALUE rb_io_init_copy(VALUE dest, VALUE io)
Definition: io.c:6611
rb_mEnumerable
VALUE rb_mEnumerable
Definition: enum.c:20
binwrite_arg::fptr
rb_io_t * fptr
Definition: io.c:1181
nogvl_copy_stream_read_write
static void nogvl_copy_stream_read_write(struct copy_stream_struct *stp)
Definition: io.c:9954
StringValue
#define StringValue(v)
rb_econv_close
void rb_econv_close(rb_econv_t *ec)
Definition: transcode.c:1702
encname
volatile VALUE encname
Definition: tcltklib.c:10155
io_input_encoding
static rb_encoding * io_input_encoding(rb_io_t *fptr)
Definition: io.c:796
rb_io_memsize
size_t rb_io_memsize(const rb_io_t *)
Definition: io.c:4209
io_close
static VALUE io_close(VALUE io)
Definition: io.c:4285
pipe_list
Definition: io.c:5473
MBCLEN_CHARFOUND_LEN
#define MBCLEN_CHARFOUND_LEN(ret)
rb_sysopen
static int rb_sysopen(VALUE fname, int oflags, mode_t perm)
Definition: io.c:5256
rb_enc_precise_mbclen
int rb_enc_precise_mbclen(const char *p, const char *e, rb_encoding *enc)
Definition: encoding.c:898
IO_RBUF_CAPA_FOR
#define IO_RBUF_CAPA_FOR(fptr)
Definition: io.c:122
argf_rewind
static VALUE argf_rewind(VALUE argf)
Definition: io.c:10550
NEED_READCONV
#define NEED_READCONV(fptr)
Definition: io.c:553
rb_io_pid
static VALUE rb_io_pid(VALUE io)
Definition: io.c:1910
rb_fatal
void rb_fatal(const char *fmt,...)
Definition: error.c:1834
io_s_read
static VALUE io_s_read(struct foreach_arg *arg)
Definition: io.c:9394
rb_eSystemCallError
VALUE rb_eSystemCallError
Definition: error.c:529
afd
Definition: getaddrinfo.c:111
io_flush_buffer_sync2
static void * io_flush_buffer_sync2(void *arg)
Definition: io.c:997
maygvl_copy_stream_continue_p
static int maygvl_copy_stream_continue_p(int has_gvl, struct copy_stream_struct *stp)
Definition: io.c:9653
rb_io_readlines
static VALUE rb_io_readlines(int argc, VALUE *argv, VALUE io)
Definition: io.c:3247
s
register char * s
Definition: os2.c:56
rb_io_get_io
VALUE rb_io_get_io(VALUE)
Definition: io.c:614
rb_str_coderange_scan_restartable
long rb_str_coderange_scan_restartable(const char *, const char *, rb_encoding *, int *)
Definition: string.c:232
rb_io_s_for_fd
static VALUE rb_io_s_for_fd(int argc, VALUE *argv, VALUE klass)
Definition: io.c:7432
argf::encs
struct rb_io_enc_t encs
Definition: io.c:158
CONST_ID
#define CONST_ID(var, str)
rb_f_select
static VALUE rb_f_select(int argc, VALUE *argv, VALUE obj)
Definition: io.c:8468
rb_io_chars
static VALUE rb_io_chars(VALUE io)
Definition: io.c:3520
rb_gc_register_mark_object
void rb_gc_register_mark_object(VALUE)
Definition: gc.c:2980
wsplit_p
static int wsplit_p(rb_io_t *fptr)
Definition: io.c:876
void
VP_EXPORT void
Definition: bigdecimal.c:5083
mode
VALUE mode
Definition: tcltklib.c:1664
rb_io_s_open
static VALUE rb_io_s_open(int argc, VALUE *argv, VALUE klass)
Definition: io.c:6189
rb_f_print
static VALUE rb_f_print(int argc, VALUE *argv)
Definition: io.c:6773
rb_io_ungetbyte
VALUE rb_io_ungetbyte(VALUE, VALUE)
Definition: io.c:3762
argf_lineno_setter
static void argf_lineno_setter(VALUE val, ID id, VALUE *var)
Definition: io.c:7842
strdup
#define strdup(s)
Definition: util.h:69
rb_scan_args
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:1570
argf_read_nonblock
static VALUE argf_read_nonblock(int argc, VALUE *argv, VALUE argf)
Definition: io.c:10778
argf_to_io
static VALUE argf_to_io(VALUE argf)
Definition: io.c:10592
NUM2UINT
#define NUM2UINT(x)
RFile
Definition: ripper.y:934
rb_block_call
VALUE rb_block_call(VALUE, ID, int, VALUE *, VALUE(*)(ANYARGS), VALUE)
Definition: vm_eval.c:1131
length
size_t length
Definition: tcltklib.c:4559
io_unread
static void io_unread(rb_io_t *fptr)
Definition: io.c:678
retval
VALUE retval
Definition: tcltklib.c:7830
rb_io_gets
VALUE rb_io_gets(VALUE)
Definition: io.c:3110
rb_assoc_new
VALUE rb_assoc_new(VALUE car, VALUE cdr)
Definition: array.c:545
internal.h
rb_scan_open_args
static void rb_scan_open_args(int argc, VALUE *argv, VALUE *fname_p, int *oflags_p, int *fmode_p, convconfig_t *convconfig_p, mode_t *perm_p)
Definition: io.c:6116
rb_execarg
Definition: ripper.y:207
FMODE_WSPLIT
#define FMODE_WSPLIT
Definition: io.h:113
rb_execarg::cmd
struct rb_execarg::@77::@79 cmd
rb_execarg::invoke
union rb_execarg::@77 invoke
rb_io_t::tied_io_for_writing
VALUE tied_io_for_writing
Definition: io.h:74
rb_io_close_m
static VALUE rb_io_close_m(VALUE io)
Definition: io.c:4268
argf_lineno_getter
static VALUE argf_lineno_getter(ID id, VALUE *var)
Definition: io.c:7835
rb_write_internal
static ssize_t rb_write_internal(int fd, const void *buf, size_t count)
Definition: io.c:943
argf::init_p
int8_t init_p
Definition: io.c:159
FMODE_TEXTMODE
#define FMODE_TEXTMODE
Definition: io.h:116
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:5105
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:3019
RB_GC_GUARD
#define RB_GC_GUARD(v)
rb_file_open_str
VALUE rb_file_open_str(VALUE, const char *)
Definition: io.c:5460
mode_t
#define mode_t
Definition: win32.h:100
rb_mutex_allow_trap
void rb_mutex_allow_trap(VALUE self, int val)
Definition: thread.c:4535
rb_io_ascii8bit_binmode
VALUE rb_io_ascii8bit_binmode(VALUE)
Definition: io.c:4623
T_FIXNUM
#define T_FIXNUM
rb_mutex_synchronize
VALUE rb_mutex_synchronize(VALUE mutex, VALUE(*func)(VALUE arg), VALUE arg)
Definition: thread.c:4512
argc
int argc
Definition: tcltklib.c:1970
argf_readline
static VALUE argf_readline(int, VALUE *, VALUE)
Definition: io.c:7984
IS_PREP_STDIO
#define IS_PREP_STDIO(f)
Definition: io.c:3965
rb_str_buf_new
VALUE rb_str_buf_new(long)
Definition: string.c:777
rb_io_s_binwrite
static VALUE rb_io_s_binwrite(int argc, VALUE *argv, VALUE io)
Definition: io.c:9616
ex
ssize_t ex
Definition: bigdecimal.c:5087
ONIGENC_CONSTRUCT_MBCLEN_CHARFOUND
#define ONIGENC_CONSTRUCT_MBCLEN_CHARFOUND(n)
strchr
char * strchr(char *, char)
intptr_t
int intptr_t
Definition: win32.h:86
prep_stdio
static VALUE prep_stdio(FILE *f, int fmode, VALUE klass, const char *path)
Definition: io.c:7135
NEED_NEWLINE_DECORATOR_ON_WRITE
#define NEED_NEWLINE_DECORATOR_ON_WRITE(fptr)
Definition: io.c:414
read_internal_arg::str_ptr
char * str_ptr
Definition: io.c:2359
rb_utf8_encindex
int rb_utf8_encindex(void)
Definition: encoding.c:1177
internal_write_func2
static void * internal_write_func2(void *ptr)
Definition: io.c:925
ECONV_STATEFUL_DECORATOR_MASK
#define ECONV_STATEFUL_DECORATOR_MASK
rb_io_getbyte
VALUE rb_io_getbyte(VALUE)
Definition: io.c:3701
rb_rescue2
VALUE rb_rescue2(VALUE(*b_proc)(ANYARGS), VALUE data1, VALUE(*r_proc)(ANYARGS), VALUE data2,...)
Definition: eval.c:701
rb_io_oflags_fmode
int rb_io_oflags_fmode(int oflags)
Definition: io.c:4775
rb_stdin
RUBY_EXTERN VALUE rb_stdin
Definition: ripper.y:1500
rb_io_s_write
static VALUE rb_io_s_write(int argc, VALUE *argv, VALUE io)
Definition: io.c:9600
io_bufread
static long io_bufread(char *ptr, long len, rb_io_t *fptr)
Definition: io.c:1986
copy_stream_struct::fds
rb_fdset_t fds
Definition: io.c:9635
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:2570
rb_ensure
VALUE rb_ensure(VALUE(*b_proc)(ANYARGS), VALUE data1, VALUE(*e_proc)(ANYARGS), VALUE data2)
Definition: eval.c:804
cmd
const char * cmd
Definition: tcltklib.c:278
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:10672
rb_econv_open_exc
VALUE rb_econv_open_exc(const char *senc, const char *denc, int ecflags)
Definition: transcode.c:2028
rb_fd_isset
#define rb_fd_isset(n, f)
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:9672
maygvl_copy_stream_wait_read
static int maygvl_copy_stream_wait_read(int has_gvl, struct copy_stream_struct *stp)
Definition: io.c:9681
do_writeconv
static VALUE do_writeconv(VALUE str, rb_io_t *fptr)
Definition: io.c:1283
io_shift_cbuf
static VALUE io_shift_cbuf(rb_io_t *fptr, int len, VALUE *strp)
Definition: io.c:2217
rb_reserved_fd_p
int rb_reserved_fd_p(int fd)
rb_sys_fail
void rb_sys_fail(const char *mesg)
Definition: error.c:1899
rb_execarg::sh
struct rb_execarg::@77::@78 sh
read_internal_call
static VALUE read_internal_call(VALUE arg)
Definition: io.c:2364
rb_cloexec_fcntl_dupfd
int rb_cloexec_fcntl_dupfd(int fd, int minfd)
Definition: io.c:308
sym_willneed
static VALUE sym_willneed
Definition: io.c:8246
rb_io_autoclose_p
static VALUE rb_io_autoclose_p(VALUE io)
Definition: io.c:7448
io_write_m
static VALUE io_write_m(VALUE io, VALUE str)
Definition: io.c:1409
ruby_verbose
ruby_verbose
Definition: tcltklib.c:5818
rb_jump_tag
void rb_jump_tag(int tag)
Definition: eval.c:666
b
Real * b
Definition: bigdecimal.c:1182
rb_get_argv
VALUE rb_get_argv(void)
Definition: io.c:11452
rb_str_encode
VALUE rb_str_encode(VALUE str, VALUE to, int ecflags, VALUE ecopts)
Definition: transcode.c:2867
read_internal_arg::fd
int fd
Definition: io.c:2358
ptr
return ptr
Definition: tcltklib.c:784
free
#define free(x)
Definition: dln.c:50
c
VpDivd * c
Definition: bigdecimal.c:1205
rb_io_set_encoding
static VALUE rb_io_set_encoding(int argc, VALUE *argv, VALUE io)
Definition: io.c:10359
rb_cIO
RUBY_EXTERN VALUE rb_cIO
Definition: ripper.y:1442
READ_DATA_BUFFERED
#define READ_DATA_BUFFERED(fptr)
Definition: io.c:374
rb_io_close_on_exec_p
#define rb_io_close_on_exec_p
Definition: io.c:3903
T_BIGNUM
#define T_BIGNUM
io_internal_read_struct
Definition: io.c:898
rb_io_binmode
VALUE rb_io_binmode(VALUE)
Definition: io.c:4599
select_args::timeout
struct timeval * timeout
Definition: io.c:8223
bufread_call
static VALUE bufread_call(VALUE arg)
Definition: io.c:2031
rb_define_module_under
VALUE rb_define_module_under(VALUE outer, const char *name)
Definition: class.c:637
strerror
RUBY_EXTERN char * strerror(int)
Definition: strerror.c:11
rb_io_t::readconv
rb_econv_t * readconv
Definition: io.h:89
ENC_CODERANGE_VALID
#define ENC_CODERANGE_VALID
argf_tell
static VALUE argf_tell(VALUE argf)
Definition: io.c:10490
shutdown
#define shutdown(a, b)
Definition: io.c:562
argf_each_byte
static VALUE argf_each_byte(VALUE argf)
Definition: io.c:11061
argf_memsize
static size_t argf_memsize(const void *ptr)
Definition: io.c:7505
rb_write_error2
void rb_write_error2(const char *, long)
Definition: io.c:7050
SEEK_END
#define SEEK_END
Definition: io.c:749
rb_cFile
RUBY_EXTERN VALUE rb_cFile
Definition: ripper.y:1437
do_ioctl
static int do_ioctl(int fd, ioctl_req_t cmd, long narg)
Definition: io.c:8513
recur
#define recur(fmt)
Definition: date_strptime.c:147
foreach_arg::argc
int argc
Definition: io.c:9264
rb_class2name
const char * rb_class2name(VALUE)
Definition: variable.c:389
rb_ivar_set
VALUE rb_ivar_set(VALUE, ID, VALUE)
Definition: variable.c:1128
argf_codepoints
static VALUE argf_codepoints(VALUE argf)
Definition: io.c:11156
sym_extenc
static VALUE sym_extenc
Definition: io.c:149
rb_io_t::write_lock
VALUE write_lock
Definition: io.h:98
pipe_list::next
struct pipe_list * next
Definition: io.c:5475
argf_filename_getter
static VALUE argf_filename_getter(ID id, VALUE *var)
Definition: io.c:11194
rb_econv_check_error
void rb_econv_check_error(rb_econv_t *ec)
Definition: transcode.c:4194
arg
arg
Definition: ripper.y:1315
rb_stderr
RUBY_EXTERN VALUE rb_stderr
Definition: ripper.y:1500
rb_io_binmode_m
static VALUE rb_io_binmode_m(VALUE io)
Definition: io.c:4663
sym_perm
static VALUE sym_perm
Definition: io.c:149
src
VALUE src
Definition: tcltklib.c:7953
rb_io_isatty
static VALUE rb_io_isatty(VALUE io)
Definition: io.c:3854
rb_str_modify
void rb_str_modify(VALUE)
Definition: string.c:1369
NEWOBJ_OF
#define NEWOBJ_OF(obj, type, klass, flags)
rb_str_cat
VALUE rb_str_cat(VALUE, const char *, long)
Definition: string.c:1963
rb_io_read_pending
int rb_io_read_pending(rb_io_t *)
Definition: io.c:817
ENC_CODERANGE_7BIT
#define ENC_CODERANGE_7BIT
rb_enc_get
rb_encoding * rb_enc_get(VALUE obj)
Definition: encoding.c:772
write_arg::io
VALUE io
Definition: io.c:1188
rb_time_interval
struct timeval rb_time_interval(VALUE num)
Definition: time.c:2492
io_s_write0
static VALUE io_s_write0(struct write_arg *arg)
Definition: io.c:9507
rb_insecure_operation
void rb_insecure_operation(void)
Definition: safe.c:101
io_flush_buffer_async2
static VALUE io_flush_buffer_async2(VALUE arg)
Definition: io.c:1016
rb_io_lineno
static VALUE rb_io_lineno(VALUE io)
Definition: io.c:3170
io_writable_length
static long io_writable_length(rb_io_t *fptr, long l)
Definition: io.c:966
rb_io_check_char_readable
void rb_io_check_char_readable(rb_io_t *fptr)
Definition: io.c:753
io_read
static VALUE io_read(int argc, VALUE *argv, VALUE io)
Definition: io.c:2705
size
int size
Definition: encoding.c:52
f
#define f
NUM2LONG
#define NUM2LONG(x)
pipe_atexit
static void pipe_atexit(void)
Definition: io.c:5513
io_new_instance
static VALUE io_new_instance(VALUE args)
Definition: io.c:9053
rb_mutex_new
VALUE rb_mutex_new(void)
Definition: thread.c:4169
rb_econv_t
Definition: transcode.c:111
SYMBOL_P
#define SYMBOL_P(x)
rb_default_rs
RUBY_EXTERN VALUE rb_default_rs
Definition: ripper.y:490
rb_io_putc
static VALUE rb_io_putc(VALUE io, VALUE ch)
Definition: io.c:6798
econv_destination_buffer_full
Definition: ripper.y:245
rb_io_bytes
static VALUE rb_io_bytes(VALUE io)
Definition: io.c:3366
Qundef
#define Qundef
rb_method_basic_definition_p
int rb_method_basic_definition_p(VALUE, ID)
Definition: vm_method.c:1498
rb_exc_new3
VALUE rb_exc_new3(VALUE etype, VALUE str)
Definition: error.c:548
io_fread
static long io_fread(VALUE str, long offset, long size, rb_io_t *fptr)
Definition: io.c:2039
rb_io_fmode_oflags
static int rb_io_fmode_oflags(int fmode)
Definition: io.c:4810
if
if(RB_TYPE_P(r, T_FLOAT))
Definition: bigdecimal.c:1186
check_pipe_command
static VALUE check_pipe_command(VALUE filename_or_command)
Definition: io.c:6238
rb_hash_dup
VALUE rb_hash_dup(VALUE)
Definition: hash.c:240
foreach_arg::io
VALUE io
Definition: io.c:9266
rb_io_s_pipe
static VALUE rb_io_s_pipe(int argc, VALUE *argv, VALUE klass)
Definition: io.c:9197
rb_io_to_io
static VALUE rb_io_to_io(VALUE io)
Definition: io.c:1965
rb_io_inspect
static VALUE rb_io_inspect(VALUE obj)
Definition: io.c:1929
rb_io_buffer_t::off
int off
Definition: io.h:58
rb_funcall3
VALUE rb_funcall3(VALUE, ID, int, const VALUE *)
Calls a method.
Definition: vm_eval.c:820
rb_mod_sys_fail
void rb_mod_sys_fail(VALUE mod, const char *mesg)
Definition: error.c:1911
rb_thread_sleep
void rb_thread_sleep(int)
Definition: thread.c:1115
sym_intenc
static VALUE sym_intenc
Definition: io.c:149
MBCLEN_INVALID_P
#define MBCLEN_INVALID_P(ret)
rb_data_type_struct
Definition: ripper.y:960
rb_io_s_try_convert
static VALUE rb_io_s_try_convert(VALUE dummy, VALUE io)
Definition: io.c:671
rb_thread_execute_interrupts
void rb_thread_execute_interrupts(VALUE th)
Definition: thread.c:1973
rb_check_array_type
VALUE rb_check_array_type(VALUE ary)
Definition: array.c:557
clear_codeconv
static void clear_codeconv(rb_io_t *fptr)
Definition: io.c:4179
rb_io_fptr_cleanup
static void rb_io_fptr_cleanup(rb_io_t *fptr, int noraise)
Definition: io.c:4145
rb_error_arity
void rb_error_arity(int argc, int min, int max)
Definition: vm_insnhelper.c:164
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:4915
TypedData_Make_Struct
#define TypedData_Make_Struct(klass, type, data_type, sval)
rb_str_catf
VALUE rb_str_catf(VALUE str, const char *format,...)
Definition: sprintf.c:1310
rb_syserr_fail_str
void rb_syserr_fail_str(int e, VALUE mesg)
Definition: error.c:1893
rb_thread_call_with_gvl
void * rb_thread_call_with_gvl(void *(*func)(void *), void *data1)
Definition: thread.c:1401
finish_writeconv_arg::noalloc
int noalloc
Definition: io.c:4033
rb_w32_write_console
long rb_w32_write_console(uintptr_t, int)
Definition: win32.c:6145
ECONV_PARTIAL_INPUT
#define ECONV_PARTIAL_INPUT
rb_fork_ruby
rb_pid_t rb_fork_ruby(int *status)
rb_cObject
RUBY_EXTERN VALUE rb_cObject
Definition: ripper.y:1426
is_socket
#define is_socket(fd, path)
Definition: io.c:568
ALLOC_N
#define ALLOC_N(type, n)
LONG2FIX
#define LONG2FIX(i)
econv_undefined_conversion
Definition: ripper.y:244
rb_thread_fd_select
int rb_thread_fd_select(int, rb_fdset_t *, rb_fdset_t *, rb_fdset_t *, struct timeval *)
Definition: thread.c:3488
rb_io_flush
VALUE rb_io_flush(VALUE)
Definition: io.c:1470
RBASIC
#define RBASIC(obj)
rb_econv_result_t
rb_econv_result_t
Definition: ripper.y:242
argf_each_char
static VALUE argf_each_char(VALUE argf)
Definition: io.c:11101
rb_io_t::pathv
VALUE pathv
Definition: io.h:69
rb_io_advise
static VALUE rb_io_advise(int argc, VALUE *argv, VALUE io)
Definition: io.c:8393
O_NONBLOCK
#define O_NONBLOCK
Definition: win32.h:591
rb_output_fs
VALUE rb_output_fs
Definition: ripper.y:488
rb_io_getc
static VALUE rb_io_getc(VALUE io)
Definition: io.c:3652
rb_econv_make_exception
VALUE rb_econv_make_exception(rb_econv_t *ec)
Definition: transcode.c:4188
io_binwrite
static long io_binwrite(VALUE str, const char *ptr, long len, rb_io_t *fptr, int nosync)
Definition: io.c:1202
rb_io_t::finalize
void(* finalize)(struct rb_io_t *, int)
Definition: io.h:70
klass
klass
Definition: tcltklib.c:3504
UINT2NUM
#define UINT2NUM(x)
seek_arg::offset
VALUE offset
Definition: io.c:9401
INT2NUM
#define INT2NUM(x)
rb_execarg::use_shell
int use_shell
Definition: ripper.y:208
argf_closed
static VALUE argf_closed(VALUE argf)
Definition: io.c:11326
list
struct rb_encoding_entry * list
Definition: encoding.c:50
rb_define_variable
void rb_define_variable(const char *, VALUE *)
Definition: variable.c:594
STRNCASECMP
#define STRNCASECMP(s1, s2, n)
READ_CHECK
#define READ_CHECK(fptr)
Definition: io.c:387
EWOULDBLOCK
#define EWOULDBLOCK
Definition: rubysocket.h:90
rb_io_s_read
static VALUE rb_io_s_read(int argc, VALUE *argv, VALUE io)
Definition: io.c:9450
rb_respond_to
int rb_respond_to(VALUE, ID)
Definition: vm_method.c:1564
fsync
#define fsync
Definition: win32.h:202
rb_fdopen
FILE * rb_fdopen(int, const char *)
Definition: io.c:5279
rb_rs
RUBY_EXTERN VALUE rb_rs
Definition: ripper.y:489
flush_before_seek
static rb_io_t * flush_before_seek(rb_io_t *fptr)
Definition: io.c:734
rb_open_file
static VALUE rb_open_file(int argc, VALUE *argv, VALUE io)
Definition: io.c:6138
OFFT2NUM
#define OFFT2NUM(v)
rb_execarg_addopt
int rb_execarg_addopt(VALUE execarg_obj, VALUE key, VALUE val)
Definition: process.c:1606
rb_cloexec_dup2
int rb_cloexec_dup2(int oldfd, int newfd)
Definition: io.c:232
rb_ary_dup
VALUE rb_ary_dup(VALUE ary)
Definition: array.c:1778
dup2
RUBY_EXTERN int dup2(int, int)
Definition: dup2.c:27
io
gz io
Definition: zlib.c:2263
rb_notimplement
void rb_notimplement(void)
Definition: error.c:1826
rb_io_t::rb_io_enc_t::ecflags
int ecflags
Definition: io.h:85
rb_define_virtual_variable
void rb_define_virtual_variable(const char *, VALUE(*)(ANYARGS), void(*)(ANYARGS))
Definition: variable.c:606
sym_binmode
static VALUE sym_binmode
Definition: io.c:150
rb_econv_asciicompat_encoding
const char * rb_econv_asciicompat_encoding(const char *encname)
Definition: transcode.c:1786
rb_thread_fd_close
void rb_thread_fd_close(int)
Definition: thread.c:2078
rb_ary_concat
VALUE rb_ary_concat(VALUE x, VALUE y)
Definition: array.c:3382
remain_size
static long remain_size(rb_io_t *fptr)
Definition: io.c:2067
rb_exec_recursive
VALUE rb_exec_recursive(VALUE(*)(VALUE, VALUE, int), VALUE, VALUE)
Definition: thread.c:4852
binwrite_arg::length
long length
Definition: io.c:1184
argf_argv_getter
static VALUE argf_argv_getter(ID id, VALUE *var)
Definition: io.c:11446
finish_writeconv_arg::fptr
rb_io_t * fptr
Definition: io.c:4032
rb_ary_join
VALUE rb_ary_join(VALUE ary, VALUE sep)
Definition: array.c:1886
rb_eNotImpError
VALUE rb_eNotImpError
Definition: error.c:521
rb_io_stdio_file
FILE * rb_io_stdio_file(rb_io_t *fptr)
Definition: io.c:7154
rb_atomic_t
int rb_atomic_t
Definition: ruby_atomic.h:93
rb_ary_new2
VALUE rb_ary_new2(long capa)
Definition: array.c:417
io_reopen
static VALUE io_reopen(VALUE io, VALUE nfile)
Definition: io.c:6419
sysopen_func
static void * sysopen_func(void *ptr)
Definition: io.c:5238
rb_io_readline
static VALUE rb_io_readline(int argc, VALUE *argv, VALUE io)
Definition: io.c:3218
rb_str_new
VALUE rb_str_new(const char *, long)
Definition: string.c:425
FMODE_PREP
#define FMODE_PREP
Definition: io.c:3964
rb_safe_level
#define rb_safe_level()
Definition: tcltklib.c:94
rb_write_error
void rb_write_error(const char *)
Definition: io.c:7064
ioctl.h
ioctl_narg_len
static long ioctl_narg_len(ioctl_req_t cmd)
Definition: io.c:8551
internal_read_func
static VALUE internal_read_func(void *ptr)
Definition: io.c:911
ECONV_NEWLINE_DECORATOR_READ_MASK
#define ECONV_NEWLINE_DECORATOR_READ_MASK
rb_execarg_setenv
void rb_execarg_setenv(VALUE execarg_obj, VALUE env)
Definition: process.c:2228
sysopen_struct::oflags
int oflags
Definition: io.c:5233
rb_io_check_writable
void rb_io_check_writable(rb_io_t *)
Definition: io.c:805
res
Real * res
Definition: bigdecimal.c:1233
rb_io_initialize
static VALUE rb_io_initialize(int argc, VALUE *argv, VALUE io)
Definition: io.c:7310
make_writeconv
static void make_writeconv(rb_io_t *fptr)
Definition: io.c:1125
ECONV_NEWLINE_DECORATOR_WRITE_MASK
#define ECONV_NEWLINE_DECORATOR_WRITE_MASK
rb_enc_asciicompat
#define rb_enc_asciicompat(enc)
NUM2MODET
#define NUM2MODET(v)
Definition: ruby.h:347
NUM2INT
#define NUM2INT(x)
SIGNED_VALUE
#define SIGNED_VALUE
rb_hash_new
VALUE rb_hash_new(void)
Definition: hash.c:234
rb_io_readbyte
static VALUE rb_io_readbyte(VALUE io)
Definition: io.c:3734
rb_obj_alloc
VALUE rb_obj_alloc(VALUE)
Definition: object.c:1721
rb_id2name
const char * rb_id2name(ID id)
Definition: ripper.c:17005
READ_CHAR_PENDING_PTR
#define READ_CHAR_PENDING_PTR(fptr)
Definition: io.c:378
rb_cloexec_open
int rb_cloexec_open(const char *pathname, int flags, mode_t mode)
Definition: io.c:209
FMODE_SYNC
#define FMODE_SYNC
Definition: io.h:107
FMODE_TTY
#define FMODE_TTY
Definition: io.h:108
MakeOpenFile
#define MakeOpenFile(obj, fp)
Definition: io.h:129
io_internal_read_struct::capa
size_t capa
Definition: io.c:901
SHUT_WR
#define SHUT_WR
SHUT_RD
#define SHUT_RD
MORE_CHAR_SUSPENDED
#define MORE_CHAR_SUSPENDED
Definition: io.c:2130
cnt
int cnt
Definition: tcltklib.c:6149
rb_io_close
VALUE rb_io_close(VALUE)
Definition: io.c:4221
sym_sequential
static VALUE sym_sequential
Definition: io.c:8246
rb_fd_init
#define rb_fd_init(f)
OBJ_UNTRUSTED
#define OBJ_UNTRUSTED(x)
rb_io_t::rbuf
rb_io_buffer_t rbuf
Definition: io.h:72
argf::inplace
char * inplace
Definition: io.c:157
rb_io_s_copy_stream
static VALUE rb_io_s_copy_stream(int argc, VALUE *argv, VALUE io)
Definition: io.c:10268
e
BDIGIT e
Definition: bigdecimal.c:5085
clear_writeconv
static void clear_writeconv(rb_io_t *fptr)
Definition: io.c:4169
convconfig_t
struct rb_io_enc_t convconfig_t
Definition: io.c:5053
fill_cbuf
static VALUE fill_cbuf(rb_io_t *fptr, int ec_flags)
Definition: io.c:2133
rb_hash_aref
VALUE rb_hash_aref(VALUE, VALUE)
Definition: hash.c:560
rb_funcall2
VALUE rb_funcall2(VALUE, ID, int, const VALUE *)
Calls a method.
Definition: vm_eval.c:805
NUM2CHR
#define NUM2CHR(x)
VALUE
unsigned long VALUE
Definition: ripper.y:104
rb_io_reopen
static VALUE rb_io_reopen(int argc, VALUE *argv, VALUE file)
Definition: io.c:6525
rb_ascii8bit_encoding
rb_encoding * rb_ascii8bit_encoding(void)
Definition: encoding.c:1153
read_buffered_data
static long read_buffered_data(char *ptr, long len, rb_io_t *fptr)
Definition: io.c:1972
sym_dontneed
static VALUE sym_dontneed
Definition: io.c:8246
rb_eEOFError
RUBY_EXTERN VALUE rb_eEOFError
Definition: ripper.y:1471
rb_warning
void rb_warning(const char *fmt,...)
Definition: error.c:229
rb_enc_find_index
int rb_enc_find_index(const char *name)
Definition: encoding.c:635
rb_io_fsync
#define rb_io_fsync
Definition: io.c:1814
fileno
#define fileno(p)
Definition: vsnprintf.c:223
copy_stream_struct::th
VALUE th
Definition: io.c:9636
sym_open_args
static VALUE sym_open_args
Definition: io.c:149
ECONV_DEFAULT_NEWLINE_DECORATOR
#define ECONV_DEFAULT_NEWLINE_DECORATOR
rb_uninterruptible
VALUE rb_uninterruptible(VALUE(*b_proc)(ANYARGS), VALUE data)
Definition: thread.c:5182
NEED_NEWLINE_DECORATOR_ON_READ
#define NEED_NEWLINE_DECORATOR_ON_READ(fptr)
Definition: io.c:413
rb_io_t::stdio_file
FILE * stdio_file
Definition: io.h:65
rb_io_fileno
static VALUE rb_io_fileno(VALUE io)
Definition: io.c:1878
ruby_get_inplace_mode
const char * ruby_get_inplace_mode(void)
Definition: io.c:11412
sym_normal
static VALUE sym_normal
Definition: io.c:8246
rb_stdio_set_default_encoding
void rb_stdio_set_default_encoding(void)
Definition: io.c:10375
MODE_BTMODE
#define MODE_BTMODE(a, b, c)
Definition: io.c:1280
argf::filename
VALUE filename
Definition: io.c:153
id_readpartial
static ID id_readpartial
Definition: io.c:148
rb_f_p_arg
Definition: io.c:6953
rb_f_p
static VALUE rb_f_p(int argc, VALUE *argv, VALUE self)
Definition: io.c:7001
argf_forward
static VALUE argf_forward(int argc, VALUE *argv, VALUE argf)
Definition: io.c:7611
ecopts
gz ecopts
Definition: zlib.c:2277
pipe_open_s
static VALUE pipe_open_s(VALUE prog, const char *modestr, int fmode, convconfig_t *convconfig)
Definition: io.c:5947
rb_f_readline
static VALUE rb_f_readline(int argc, VALUE *argv, VALUE recv)
Definition: io.c:7958
rb_w32_fd_is_text
char rb_w32_fd_is_text(int)
Definition: win32.c:6568
io_seek
#define io_seek(fptr, ofs, whence)
Definition: io.c:743
argf_fileno
static VALUE argf_fileno(VALUE argf)
Definition: io.c:10570
select_args::write
VALUE write
Definition: io.c:8222
OBJ_TAINT
#define OBJ_TAINT(x)
rb_read_internal
static ssize_t rb_read_internal(int fd, void *buf, size_t count)
Definition: io.c:932
argf_to_s
static VALUE argf_to_s(VALUE argf)
Definition: io.c:11340
io_alloc
static VALUE io_alloc(VALUE klass)
Definition: io.c:862
RUBY_METHOD_FUNC
#define RUBY_METHOD_FUNC(func)
foreach_arg::argv
VALUE * argv
Definition: io.c:9265
rb_intern
#define rb_intern(str)
READ_CHAR_PENDING_COUNT
#define READ_CHAR_PENDING_COUNT(fptr)
Definition: io.c:377
rb_io_getline_1
static VALUE rb_io_getline_1(VALUE rs, long limit, VALUE io)
Definition: io.c:2989
rb_io_t::lineno
int lineno
Definition: io.h:68
v
BDIGIT v
Definition: bigdecimal.c:5656
fstat
#define fstat(fd, st)
Definition: win32.h:194
rb_ioctl
static VALUE rb_ioctl(VALUE io, VALUE req, VALUE arg)
Definition: io.c:8752
stat
#define stat(path, st)
Definition: win32.h:193
io_read_nonblock
static VALUE io_read_nonblock(int argc, VALUE *argv, VALUE io)
Definition: io.c:2546
rb_io_set_write_io
VALUE rb_io_set_write_io(VALUE io, VALUE w)
Definition: io.c:638
nogvl_copy_stream_func
static void * nogvl_copy_stream_func(void *arg)
Definition: io.c:10011
select_args::except
VALUE except
Definition: io.c:8222
rb_io_oflags_modestr
static const char * rb_io_oflags_modestr(int oflags)
Definition: io.c:4851
rb_io_sync
#define rb_io_sync
Definition: io.c:1815
DEFULT_IOCTL_NARG_LEN
#define DEFULT_IOCTL_NARG_LEN
Definition: io.c:8527
env
#define env
sysopen_struct::perm
mode_t perm
Definition: io.c:5234
rb_econv_putbackable
int rb_econv_putbackable(rb_econv_t *ec)
Definition: transcode.c:1742
NULL
#define NULL
Definition: _sdbm.c:103
argf_file
static VALUE argf_file(VALUE argf)
Definition: io.c:11218
copy_stream_finalize
static VALUE copy_stream_finalize(VALUE arg)
Definition: io.c:10219
name
const char * name
Definition: nkf.c:208
io_getc
static VALUE io_getc(rb_io_t *fptr, rb_encoding *enc)
Definition: io.c:3375
foreach_arg
Definition: io.c:9263
rb_io_wait_readable
int rb_io_wait_readable(int)
Definition: io.c:1064
READ_CHAR_PENDING
#define READ_CHAR_PENDING(fptr)
Definition: io.c:376
rb_check_string_type
VALUE rb_check_string_type(VALUE)
Definition: string.c:1508
argf_free
static void argf_free(void *ptr)
Definition: io.c:7497
READ_DATA_PENDING_PTR
#define READ_DATA_PENDING_PTR(fptr)
Definition: io.c:373
extract_binmode
static void extract_binmode(VALUE opthash, int *fmode)
Definition: io.c:5080
argf_close_m
static VALUE argf_close_m(VALUE argf)
Definition: io.c:11307
rb_write_error_str
void rb_write_error_str(VALUE mesg)
Definition: io.c:7070
binwrite_arg
Definition: io.c:1180
rb_enc_str_coderange
int rb_enc_str_coderange(VALUE)
Definition: string.c:327
id_flush
static ID id_flush
Definition: io.c:148
sysopen_struct
Definition: io.c:5231
select_end
static VALUE select_end(VALUE arg)
Definition: io.c:8236
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:4885
rb_class_new
VALUE rb_class_new(VALUE super)
Creates a new class.
Definition: class.c:117
rb_define_method
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1344
retry
int retry
Definition: tcltklib.c:10151
NOFILE
#define NOFILE
Definition: io.c:76
rb_io_each_codepoint
static VALUE rb_io_each_codepoint(VALUE io)
Definition: io.c:3545
pipe_del_fptr
static void pipe_del_fptr(rb_io_t *fptr)
Definition: io.c:5490
next_argv
#define next_argv()
Definition: io.c:7616
rb_thread_fd_writable
int rb_thread_fd_writable(int)
Definition: thread.c:3437
dst
char * dst
Definition: tcltklib.c:9868
rb_warn
void rb_warn(const char *fmt,...)
Definition: error.c:216
rb_io_check_closed
void rb_io_check_closed(rb_io_t *)
Definition: io.c:604
rb_io_s_foreach
static VALUE rb_io_s_foreach(int argc, VALUE *argv, VALUE self)
Definition: io.c:9344
pipe_list::fptr
rb_io_t * fptr
Definition: io.c:5474
rb_econv_putback
void rb_econv_putback(rb_econv_t *ec, unsigned char *p, int n)
Definition: transcode.c:1753
rb_econv_str_convert
VALUE rb_econv_str_convert(rb_econv_t *ec, VALUE src, int flags)
Definition: transcode.c:1869
SEEK_SET
#define SEEK_SET
Definition: io.c:747
rb_eArgError
VALUE rb_eArgError
Definition: error.c:512
rb_io_open
static VALUE rb_io_open(VALUE filename, VALUE vmode, VALUE vperm, VALUE opt)
Definition: io.c:6389
rb_convert_type
VALUE rb_convert_type(VALUE, int, const char *, const char *)
Definition: object.c:2368
O_BINARY
#define O_BINARY
Definition: _sdbm.c:89
seek_arg::mode
int mode
Definition: io.c:9402
econv_incomplete_input
Definition: ripper.y:249
rb_check_convert_type
VALUE rb_check_convert_type(VALUE, int, const char *, const char *)
Definition: object.c:2383
argf_initialize_copy
static VALUE argf_initialize_copy(VALUE argf, VALUE orig)
Definition: io.c:7552
argf_getc
static VALUE argf_getc(VALUE argf)
Definition: io.c:10848
ECONV_UNIVERSAL_NEWLINE_DECORATOR
#define ECONV_UNIVERSAL_NEWLINE_DECORATOR
maygvl_close
static int maygvl_close(int fd, int keepgvl)
Definition: io.c:4052
dummy
int dummy
Definition: tcltklib.c:4483
argf_skip
static VALUE argf_skip(VALUE argf)
Definition: io.c:11279
rb_io_fdopen
VALUE rb_io_fdopen(int, int, const char *)
Definition: io.c:7126
SEEK_CUR
#define SEEK_CUR
Definition: io.c:748
SET_BINARY_MODE
#define SET_BINARY_MODE(fptr)
Definition: io.c:555
strrchr
char * strrchr(const char *, const char)
rb_io_addstr
VALUE rb_io_addstr(VALUE, VALUE)
Definition: io.c:1437
seek_arg::io
VALUE io
Definition: io.c:9400
maygvl_fclose
static int maygvl_fclose(FILE *file, int keepgvl)
Definition: io.c:4073
rb_io_t::writeconv
rb_econv_t * writeconv
Definition: io.h:92
argf_forward_call
static VALUE argf_forward_call(VALUE arg)
Definition: io.c:10723
rb_read_check
void rb_read_check(FILE *fp)
Definition: io.c:826
rb_io_write
VALUE rb_io_write(VALUE, VALUE)
Definition: io.c:1415
flock
Definition: ioctl.h:6
io_fillbuf
static int io_fillbuf(rb_io_t *fptr)
Definition: io.c:1640
seek_arg
Definition: io.c:9399
rb_inspect
VALUE rb_inspect(VALUE)
Definition: object.c:402
read_internal_arg
Definition: io.c:2357
rb_thread_interrupted
int rb_thread_interrupted(VALUE thval)
Definition: thread.c:1107
rb_enc_from_index
rb_encoding * rb_enc_from_index(int index)
Definition: encoding.c:548
OnigEncodingTypeST
Definition: ripper.y:161
unsupported_encoding
static void unsupported_encoding(const char *name)
Definition: io.c:4909
rb_io_s_new
static VALUE rb_io_s_new(int argc, VALUE *argv, VALUE klass)
Definition: io.c:7411
rb_execarg_fixup
void rb_execarg_fixup(VALUE execarg_obj)
Definition: process.c:2254
clear_readconv
static void clear_readconv(rb_io_t *fptr)
Definition: io.c:4156
len
size_t len
Definition: tcltklib.c:3568
rb_eof_error
void rb_eof_error(void)
Definition: io.c:581
rb_str_set_len
void rb_str_set_len(VALUE, long)
Definition: string.c:1837