Ruby 2.0.0p247(2013-06-27revision41674)

- 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 static long
2025 io_fread(VALUE str, long offset, long size, rb_io_t *fptr)
2026 {
2027 long len;
2028
2029 io_setstrbuf(&str, offset + size);
2030 rb_str_locktmp(str);
2031 len = io_bufread(RSTRING_PTR(str) + offset, size, fptr);
2032 rb_str_unlocktmp(str);
2033 if (len < 0) rb_sys_fail_path(fptr->pathv);
2034 return len;
2035 }
2036
2037 ssize_t
2038 rb_io_bufread(VALUE io, void *buf, size_t size)
2039 {
2040 rb_io_t *fptr;
2041
2042 GetOpenFile(io, fptr);
2043 rb_io_check_readable(fptr);
2044 return (ssize_t)io_bufread(buf, (long)size, fptr);
2045 }
2046
2047 #define SMALLBUF 100
2048
2049 static long
2050 remain_size(rb_io_t *fptr)
2051 {
2052 struct stat st;
2053 off_t siz = READ_DATA_PENDING_COUNT(fptr);
2054 off_t pos;
2055
2056 if (fstat(fptr->fd, &st) == 0 && S_ISREG(st.st_mode)
2057 #if defined(__BEOS__) || defined(__HAIKU__)
2058 && (st.st_dev > 3)
2059 #endif
2060 )
2061 {
2062 if (io_fflush(fptr) < 0)
2063 rb_sys_fail(0);
2064 pos = lseek(fptr->fd, 0, SEEK_CUR);
2065 if (st.st_size >= pos && pos >= 0) {
2066 siz += st.st_size - pos;
2067 if (siz > LONG_MAX) {
2068 rb_raise(rb_eIOError, "file too big for single read");
2069 }
2070 }
2071 }
2072 else {
2073 siz += BUFSIZ;
2074 }
2075 return (long)siz;
2076 }
2077
2078 static VALUE
2079 io_enc_str(VALUE str, rb_io_t *fptr)
2080 {
2081 OBJ_TAINT(str);
2082 rb_enc_associate(str, io_read_encoding(fptr));
2083 return str;
2084 }
2085
2086 static void
2087 make_readconv(rb_io_t *fptr, int size)
2088 {
2089 if (!fptr->readconv) {
2090 int ecflags;
2091 VALUE ecopts;
2092 const char *sname, *dname;
2093 ecflags = fptr->encs.ecflags & ~ECONV_NEWLINE_DECORATOR_WRITE_MASK;
2094 ecopts = fptr->encs.ecopts;
2095 if (fptr->encs.enc2) {
2096 sname = rb_enc_name(fptr->encs.enc2);
2097 dname = rb_enc_name(fptr->encs.enc);
2098 }
2099 else {
2100 sname = dname = "";
2101 }
2102 fptr->readconv = rb_econv_open_opts(sname, dname, ecflags, ecopts);
2103 if (!fptr->readconv)
2104 rb_exc_raise(rb_econv_open_exc(sname, dname, ecflags));
2105 fptr->cbuf.off = 0;
2106 fptr->cbuf.len = 0;
2107 if (size < IO_CBUF_CAPA_MIN) size = IO_CBUF_CAPA_MIN;
2108 fptr->cbuf.capa = size;
2109 fptr->cbuf.ptr = ALLOC_N(char, fptr->cbuf.capa);
2110 }
2111 }
2112
2113 #define MORE_CHAR_SUSPENDED Qtrue
2114 #define MORE_CHAR_FINISHED Qnil
2115 static VALUE
2116 fill_cbuf(rb_io_t *fptr, int ec_flags)
2117 {
2118 const unsigned char *ss, *sp, *se;
2119 unsigned char *ds, *dp, *de;
2120 rb_econv_result_t res;
2121 int putbackable;
2122 int cbuf_len0;
2123 VALUE exc;
2124
2125 ec_flags |= ECONV_PARTIAL_INPUT;
2126
2127 if (fptr->cbuf.len == fptr->cbuf.capa)
2128 return MORE_CHAR_SUSPENDED; /* cbuf full */
2129 if (fptr->cbuf.len == 0)
2130 fptr->cbuf.off = 0;
2131 else if (fptr->cbuf.off + fptr->cbuf.len == fptr->cbuf.capa) {
2132 memmove(fptr->cbuf.ptr, fptr->cbuf.ptr+fptr->cbuf.off, fptr->cbuf.len);
2133 fptr->cbuf.off = 0;
2134 }
2135
2136 cbuf_len0 = fptr->cbuf.len;
2137
2138 while (1) {
2139 ss = sp = (const unsigned char *)fptr->rbuf.ptr + fptr->rbuf.off;
2140 se = sp + fptr->rbuf.len;
2141 ds = dp = (unsigned char *)fptr->cbuf.ptr + fptr->cbuf.off + fptr->cbuf.len;
2142 de = (unsigned char *)fptr->cbuf.ptr + fptr->cbuf.capa;
2143 res = rb_econv_convert(fptr->readconv, &sp, se, &dp, de, ec_flags);
2144 fptr->rbuf.off += (int)(sp - ss);
2145 fptr->rbuf.len -= (int)(sp - ss);
2146 fptr->cbuf.len += (int)(dp - ds);
2147
2148 putbackable = rb_econv_putbackable(fptr->readconv);
2149 if (putbackable) {
2150 rb_econv_putback(fptr->readconv, (unsigned char *)fptr->rbuf.ptr + fptr->rbuf.off - putbackable, putbackable);
2151 fptr->rbuf.off -= putbackable;
2152 fptr->rbuf.len += putbackable;
2153 }
2154
2155 exc = rb_econv_make_exception(fptr->readconv);
2156 if (!NIL_P(exc))
2157 return exc;
2158
2159 if (cbuf_len0 != fptr->cbuf.len)
2160 return MORE_CHAR_SUSPENDED;
2161
2162 if (res == econv_finished) {
2163 return MORE_CHAR_FINISHED;
2164 }
2165
2166 if (res == econv_source_buffer_empty) {
2167 if (fptr->rbuf.len == 0) {
2168 READ_CHECK(fptr);
2169 if (io_fillbuf(fptr) == -1) {
2170 if (!fptr->readconv) {
2171 return MORE_CHAR_FINISHED;
2172 }
2173 ds = dp = (unsigned char *)fptr->cbuf.ptr + fptr->cbuf.off + fptr->cbuf.len;
2174 de = (unsigned char *)fptr->cbuf.ptr + fptr->cbuf.capa;
2175 res = rb_econv_convert(fptr->readconv, NULL, NULL, &dp, de, 0);
2176 fptr->cbuf.len += (int)(dp - ds);
2177 rb_econv_check_error(fptr->readconv);
2178 break;
2179 }
2180 }
2181 }
2182 }
2183 if (cbuf_len0 != fptr->cbuf.len)
2184 return MORE_CHAR_SUSPENDED;
2185
2186 return MORE_CHAR_FINISHED;
2187 }
2188
2189 static VALUE
2190 more_char(rb_io_t *fptr)
2191 {
2192 VALUE v;
2193 v = fill_cbuf(fptr, ECONV_AFTER_OUTPUT);
2194 if (v != MORE_CHAR_SUSPENDED && v != MORE_CHAR_FINISHED)
2195 rb_exc_raise(v);
2196 return v;
2197 }
2198
2199 static VALUE
2200 io_shift_cbuf(rb_io_t *fptr, int len, VALUE *strp)
2201 {
2202 VALUE str = Qnil;
2203 if (strp) {
2204 str = *strp;
2205 if (NIL_P(str)) {
2206 *strp = str = rb_str_new(fptr->cbuf.ptr+fptr->cbuf.off, len);
2207 }
2208 else {
2209 rb_str_cat(str, fptr->cbuf.ptr+fptr->cbuf.off, len);
2210 }
2211 OBJ_TAINT(str);
2212 rb_enc_associate(str, fptr->encs.enc);
2213 }
2214 fptr->cbuf.off += len;
2215 fptr->cbuf.len -= len;
2216 /* xxx: set coderange */
2217 if (fptr->cbuf.len == 0)
2218 fptr->cbuf.off = 0;
2219 else if (fptr->cbuf.capa/2 < fptr->cbuf.off) {
2220 memmove(fptr->cbuf.ptr, fptr->cbuf.ptr+fptr->cbuf.off, fptr->cbuf.len);
2221 fptr->cbuf.off = 0;
2222 }
2223 return str;
2224 }
2225
2226 static void
2227 io_setstrbuf(VALUE *str, long len)
2228 {
2229 #ifdef _WIN32
2230 len = (len + 1) & ~1L; /* round up for wide char */
2231 #endif
2232 if (NIL_P(*str)) {
2233 *str = rb_str_new(0, 0);
2234 }
2235 else {
2236 VALUE s = StringValue(*str);
2237 long clen = RSTRING_LEN(s);
2238 if (clen >= len) {
2239 if (clen != len) {
2240 rb_str_modify(s);
2241 rb_str_set_len(s, len);
2242 }
2243 return;
2244 }
2245 len -= clen;
2246 }
2247 rb_str_modify_expand(*str, len);
2248 }
2249
2250 static void
2251 io_set_read_length(VALUE str, long n)
2252 {
2253 if (RSTRING_LEN(str) != n) {
2254 rb_str_modify(str);
2255 rb_str_set_len(str, n);
2256 }
2257 }
2258
2259 static VALUE
2260 read_all(rb_io_t *fptr, long siz, VALUE str)
2261 {
2262 long bytes;
2263 long n;
2264 long pos;
2265 rb_encoding *enc;
2266 int cr;
2267
2268 if (NEED_READCONV(fptr)) {
2269 SET_BINARY_MODE(fptr);
2270 io_setstrbuf(&str,0);
2271 make_readconv(fptr, 0);
2272 while (1) {
2273 VALUE v;
2274 if (fptr->cbuf.len) {
2275 io_shift_cbuf(fptr, fptr->cbuf.len, &str);
2276 }
2277 v = fill_cbuf(fptr, 0);
2278 if (v != MORE_CHAR_SUSPENDED && v != MORE_CHAR_FINISHED) {
2279 if (fptr->cbuf.len) {
2280 io_shift_cbuf(fptr, fptr->cbuf.len, &str);
2281 }
2282 rb_exc_raise(v);
2283 }
2284 if (v == MORE_CHAR_FINISHED) {
2285 clear_readconv(fptr);
2286 return io_enc_str(str, fptr);
2287 }
2288 }
2289 }
2290
2291 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
2292 bytes = 0;
2293 pos = 0;
2294
2295 enc = io_read_encoding(fptr);
2296 cr = 0;
2297
2298 if (siz == 0) siz = BUFSIZ;
2299 io_setstrbuf(&str,siz);
2300 for (;;) {
2301 READ_CHECK(fptr);
2302 n = io_fread(str, bytes, siz - bytes, fptr);
2303 if (n == 0 && bytes == 0) {
2304 rb_str_set_len(str, 0);
2305 break;
2306 }
2307 bytes += n;
2308 rb_str_set_len(str, bytes);
2309 if (cr != ENC_CODERANGE_BROKEN)
2310 pos += rb_str_coderange_scan_restartable(RSTRING_PTR(str) + pos, RSTRING_PTR(str) + bytes, enc, &cr);
2311 if (bytes < siz) break;
2312 siz += BUFSIZ;
2313 rb_str_modify_expand(str, BUFSIZ);
2314 }
2315 str = io_enc_str(str, fptr);
2316 ENC_CODERANGE_SET(str, cr);
2317 return str;
2318 }
2319
2320 void
2321 rb_io_set_nonblock(rb_io_t *fptr)
2322 {
2323 int oflags;
2324 #ifdef F_GETFL
2325 oflags = fcntl(fptr->fd, F_GETFL);
2326 if (oflags == -1) {
2327 rb_sys_fail_path(fptr->pathv);
2328 }
2329 #else
2330 oflags = 0;
2331 #endif
2332 if ((oflags & O_NONBLOCK) == 0) {
2333 oflags |= O_NONBLOCK;
2334 if (fcntl(fptr->fd, F_SETFL, oflags) == -1) {
2335 rb_sys_fail_path(fptr->pathv);
2336 }
2337 }
2338 }
2339
2340 static VALUE
2341 io_getpartial(int argc, VALUE *argv, VALUE io, int nonblock)
2342 {
2343 rb_io_t *fptr;
2344 VALUE length, str;
2345 long n, len;
2346
2347 rb_scan_args(argc, argv, "11", &length, &str);
2348
2349 if ((len = NUM2LONG(length)) < 0) {
2350 rb_raise(rb_eArgError, "negative length %ld given", len);
2351 }
2352
2353 io_setstrbuf(&str,len);
2354 OBJ_TAINT(str);
2355
2356 GetOpenFile(io, fptr);
2357 rb_io_check_byte_readable(fptr);
2358
2359 if (len == 0)
2360 return str;
2361
2362 if (!nonblock)
2363 READ_CHECK(fptr);
2364 n = read_buffered_data(RSTRING_PTR(str), len, fptr);
2365 if (n <= 0) {
2366 again:
2367 if (nonblock) {
2368 rb_io_set_nonblock(fptr);
2369 }
2370 io_setstrbuf(&str, len);
2371 rb_str_locktmp(str);
2372 n = rb_read_internal(fptr->fd, RSTRING_PTR(str), len);
2373 rb_str_unlocktmp(str);
2374 if (n < 0) {
2375 if (!nonblock && rb_io_wait_readable(fptr->fd))
2376 goto again;
2377 if (nonblock && (errno == EWOULDBLOCK || errno == EAGAIN))
2378 rb_mod_sys_fail(rb_mWaitReadable, "read would block");
2379 rb_sys_fail_path(fptr->pathv);
2380 }
2381 }
2382 io_set_read_length(str, n);
2383
2384 if (n == 0)
2385 return Qnil;
2386 else
2387 return str;
2388 }
2389
2390 /*
2391 * call-seq:
2392 * ios.readpartial(maxlen) -> string
2393 * ios.readpartial(maxlen, outbuf) -> outbuf
2394 *
2395 * Reads at most <i>maxlen</i> bytes from the I/O stream.
2396 * It blocks only if <em>ios</em> has no data immediately available.
2397 * It doesn't block if some data available.
2398 * If the optional <i>outbuf</i> argument is present,
2399 * it must reference a String, which will receive the data.
2400 * The <i>outbuf</i> will contain only the received data after the method call
2401 * even if it is not empty at the beginning.
2402 * It raises <code>EOFError</code> on end of file.
2403 *
2404 * readpartial is designed for streams such as pipe, socket, tty, etc.
2405 * It blocks only when no data immediately available.
2406 * This means that it blocks only when following all conditions hold.
2407 * * the byte buffer in the IO object is empty.
2408 * * the content of the stream is empty.
2409 * * the stream is not reached to EOF.
2410 *
2411 * When readpartial blocks, it waits data or EOF on the stream.
2412 * If some data is reached, readpartial returns with the data.
2413 * If EOF is reached, readpartial raises EOFError.
2414 *
2415 * When readpartial doesn't blocks, it returns or raises immediately.
2416 * If the byte buffer is not empty, it returns the data in the buffer.
2417 * Otherwise if the stream has some content,
2418 * it returns the data in the stream.
2419 * Otherwise if the stream is reached to EOF, it raises EOFError.
2420 *
2421 * r, w = IO.pipe # buffer pipe content
2422 * w << "abc" # "" "abc".
2423 * r.readpartial(4096) #=> "abc" "" ""
2424 * r.readpartial(4096) # blocks because buffer and pipe is empty.
2425 *
2426 * r, w = IO.pipe # buffer pipe content
2427 * w << "abc" # "" "abc"
2428 * w.close # "" "abc" EOF
2429 * r.readpartial(4096) #=> "abc" "" EOF
2430 * r.readpartial(4096) # raises EOFError
2431 *
2432 * r, w = IO.pipe # buffer pipe content
2433 * w << "abc\ndef\n" # "" "abc\ndef\n"
2434 * r.gets #=> "abc\n" "def\n" ""
2435 * w << "ghi\n" # "def\n" "ghi\n"
2436 * r.readpartial(4096) #=> "def\n" "" "ghi\n"
2437 * r.readpartial(4096) #=> "ghi\n" "" ""
2438 *
2439 * Note that readpartial behaves similar to sysread.
2440 * The differences are:
2441 * * If the byte buffer is not empty, read from the byte buffer instead of "sysread for buffered IO (IOError)".
2442 * * It doesn't cause Errno::EWOULDBLOCK and Errno::EINTR. When readpartial meets EWOULDBLOCK and EINTR by read system call, readpartial retry the system call.
2443 *
2444 * The later means that readpartial is nonblocking-flag insensitive.
2445 * It blocks on the situation IO#sysread causes Errno::EWOULDBLOCK as if the fd is blocking mode.
2446 *
2447 */
2448
2449 static VALUE
2450 io_readpartial(int argc, VALUE *argv, VALUE io)
2451 {
2452 VALUE ret;
2453
2454 ret = io_getpartial(argc, argv, io, 0);
2455 if (NIL_P(ret))
2456 rb_eof_error();
2457 return ret;
2458 }
2459
2460 /*
2461 * call-seq:
2462 * ios.read_nonblock(maxlen) -> string
2463 * ios.read_nonblock(maxlen, outbuf) -> outbuf
2464 *
2465 * Reads at most <i>maxlen</i> bytes from <em>ios</em> using
2466 * the read(2) system call after O_NONBLOCK is set for
2467 * the underlying file descriptor.
2468 *
2469 * If the optional <i>outbuf</i> argument is present,
2470 * it must reference a String, which will receive the data.
2471 * The <i>outbuf</i> will contain only the received data after the method call
2472 * even if it is not empty at the beginning.
2473 *
2474 * read_nonblock just calls the read(2) system call.
2475 * It causes all errors the read(2) system call causes: Errno::EWOULDBLOCK, Errno::EINTR, etc.
2476 * The caller should care such errors.
2477 *
2478 * If the exception is Errno::EWOULDBLOCK or Errno::AGAIN,
2479 * it is extended by IO::WaitReadable.
2480 * So IO::WaitReadable can be used to rescue the exceptions for retrying read_nonblock.
2481 *
2482 * read_nonblock causes EOFError on EOF.
2483 *
2484 * If the read byte buffer is not empty,
2485 * read_nonblock reads from the buffer like readpartial.
2486 * In this case, the read(2) system call is not called.
2487 *
2488 * When read_nonblock raises an exception kind of IO::WaitReadable,
2489 * read_nonblock should not be called
2490 * until io is readable for avoiding busy loop.
2491 * This can be done as follows.
2492 *
2493 * # emulates blocking read (readpartial).
2494 * begin
2495 * result = io.read_nonblock(maxlen)
2496 * rescue IO::WaitReadable
2497 * IO.select([io])
2498 * retry
2499 * end
2500 *
2501 * Although IO#read_nonblock doesn't raise IO::WaitWritable.
2502 * OpenSSL::Buffering#read_nonblock can raise IO::WaitWritable.
2503 * If IO and SSL should be used polymorphically,
2504 * IO::WaitWritable should be rescued too.
2505 * See the document of OpenSSL::Buffering#read_nonblock for sample code.
2506 *
2507 * Note that this method is identical to readpartial
2508 * except the non-blocking flag is set.
2509 */
2510
2511 static VALUE
2512 io_read_nonblock(int argc, VALUE *argv, VALUE io)
2513 {
2514 VALUE ret;
2515
2516 ret = io_getpartial(argc, argv, io, 1);
2517 if (NIL_P(ret))
2518 rb_eof_error();
2519 return ret;
2520 }
2521
2522 /*
2523 * call-seq:
2524 * ios.write_nonblock(string) -> integer
2525 *
2526 * Writes the given string to <em>ios</em> using
2527 * the write(2) system call after O_NONBLOCK is set for
2528 * the underlying file descriptor.
2529 *
2530 * It returns the number of bytes written.
2531 *
2532 * write_nonblock just calls the write(2) system call.
2533 * It causes all errors the write(2) system call causes: Errno::EWOULDBLOCK, Errno::EINTR, etc.
2534 * The result may also be smaller than string.length (partial write).
2535 * The caller should care such errors and partial write.
2536 *
2537 * If the exception is Errno::EWOULDBLOCK or Errno::AGAIN,
2538 * it is extended by IO::WaitWritable.
2539 * So IO::WaitWritable can be used to rescue the exceptions for retrying write_nonblock.
2540 *
2541 * # Creates a pipe.
2542 * r, w = IO.pipe
2543 *
2544 * # write_nonblock writes only 65536 bytes and return 65536.
2545 * # (The pipe size is 65536 bytes on this environment.)
2546 * s = "a" * 100000
2547 * p w.write_nonblock(s) #=> 65536
2548 *
2549 * # write_nonblock cannot write a byte and raise EWOULDBLOCK (EAGAIN).
2550 * p w.write_nonblock("b") # Resource temporarily unavailable (Errno::EAGAIN)
2551 *
2552 * If the write buffer is not empty, it is flushed at first.
2553 *
2554 * When write_nonblock raises an exception kind of IO::WaitWritable,
2555 * write_nonblock should not be called
2556 * until io is writable for avoiding busy loop.
2557 * This can be done as follows.
2558 *
2559 * begin
2560 * result = io.write_nonblock(string)
2561 * rescue IO::WaitWritable, Errno::EINTR
2562 * IO.select(nil, [io])
2563 * retry
2564 * end
2565 *
2566 * Note that this doesn't guarantee to write all data in string.
2567 * The length written is reported as result and it should be checked later.
2568 *
2569 * On some platforms such as Windows, write_nonblock is not supported
2570 * according to the kind of the IO object.
2571 * In such cases, write_nonblock raises <code>Errno::EBADF</code>.
2572 *
2573 */
2574
2575 static VALUE
2576 rb_io_write_nonblock(VALUE io, VALUE str)
2577 {
2578 rb_io_t *fptr;
2579 long n;
2580
2581 rb_secure(4);
2582 if (!RB_TYPE_P(str, T_STRING))
2583 str = rb_obj_as_string(str);
2584
2585 io = GetWriteIO(io);
2586 GetOpenFile(io, fptr);
2587 rb_io_check_writable(fptr);
2588
2589 if (io_fflush(fptr) < 0)
2590 rb_sys_fail(0);
2591
2592 rb_io_set_nonblock(fptr);
2593 n = write(fptr->fd, RSTRING_PTR(str), RSTRING_LEN(str));
2594
2595 if (n == -1) {
2596 if (errno == EWOULDBLOCK || errno == EAGAIN)
2597 rb_mod_sys_fail(rb_mWaitWritable, "write would block");
2598 rb_sys_fail_path(fptr->pathv);
2599 }
2600
2601 return LONG2FIX(n);
2602 }
2603
2604 /*
2605 * call-seq:
2606 * ios.read([length [, outbuf]]) -> string, outbuf, or nil
2607 *
2608 * Reads <i>length</i> bytes from the I/O stream.
2609 *
2610 * <i>length</i> must be a non-negative integer or <code>nil</code>.
2611 *
2612 * If <i>length</i> is a positive integer,
2613 * it try to read <i>length</i> bytes without any conversion (binary mode).
2614 * It returns <code>nil</code> or a string whose length is 1 to <i>length</i> bytes.
2615 * <code>nil</code> means it met EOF at beginning.
2616 * The 1 to <i>length</i>-1 bytes string means it met EOF after reading the result.
2617 * The <i>length</i> bytes string means it doesn't meet EOF.
2618 * The resulted string is always ASCII-8BIT encoding.
2619 *
2620 * If <i>length</i> is omitted or is <code>nil</code>,
2621 * it reads until EOF and the encoding conversion is applied.
2622 * It returns a string even if EOF is met at beginning.
2623 *
2624 * If <i>length</i> is zero, it returns <code>""</code>.
2625 *
2626 * If the optional <i>outbuf</i> argument is present, it must reference
2627 * a String, which will receive the data.
2628 * The <i>outbuf</i> will contain only the received data after the method call
2629 * even if it is not empty at the beginning.
2630 *
2631 * At end of file, it returns <code>nil</code> or <code>""</code>
2632 * depend on <i>length</i>.
2633 * <code><i>ios</i>.read()</code> and
2634 * <code><i>ios</i>.read(nil)</code> returns <code>""</code>.
2635 * <code><i>ios</i>.read(<i>positive-integer</i>)</code> returns <code>nil</code>.
2636 *
2637 * f = File.new("testfile")
2638 * f.read(16) #=> "This is line one"
2639 *
2640 * # reads whole file
2641 * open("file") {|f|
2642 * data = f.read # This returns a string even if the file is empty.
2643 * ...
2644 * }
2645 *
2646 * # iterate over fixed length records.
2647 * open("fixed-record-file") {|f|
2648 * while record = f.read(256)
2649 * ...
2650 * end
2651 * }
2652 *
2653 * # iterate over variable length records.
2654 * # record is prefixed by 32-bit length.
2655 * open("variable-record-file") {|f|
2656 * while len = f.read(4)
2657 * len = len.unpack("N")[0] # 32-bit length
2658 * record = f.read(len) # This returns a string even if len is 0.
2659 * end
2660 * }
2661 *
2662 * Note that this method behaves like fread() function in C.
2663 * This means it retry to invoke read(2) system call to read data with the specified length (or until EOF).
2664 * This behavior is preserved even if <i>ios</i> is non-blocking mode.
2665 * (This method is non-blocking flag insensitive as other methods.)
2666 * If you need the behavior like single read(2) system call,
2667 * consider readpartial, read_nonblock and sysread.
2668 */
2669
2670 static VALUE
2671 io_read(int argc, VALUE *argv, VALUE io)
2672 {
2673 rb_io_t *fptr;
2674 long n, len;
2675 VALUE length, str;
2676 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
2677 int previous_mode;
2678 #endif
2679
2680 rb_scan_args(argc, argv, "02", &length, &str);
2681
2682 if (NIL_P(length)) {
2683 GetOpenFile(io, fptr);
2684 rb_io_check_char_readable(fptr);
2685 return read_all(fptr, remain_size(fptr), str);
2686 }
2687 len = NUM2LONG(length);
2688 if (len < 0) {
2689 rb_raise(rb_eArgError, "negative length %ld given", len);
2690 }
2691
2692 io_setstrbuf(&str,len);
2693
2694 GetOpenFile(io, fptr);
2695 rb_io_check_byte_readable(fptr);
2696 if (len == 0) return str;
2697
2698 READ_CHECK(fptr);
2699 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
2700 previous_mode = set_binary_mode_with_seek_cur(fptr);
2701 #endif
2702 n = io_fread(str, 0, len, fptr);
2703 io_set_read_length(str, n);
2704 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
2705 if (previous_mode == O_TEXT) {
2706 setmode(fptr->fd, O_TEXT);
2707 }
2708 #endif
2709 if (n == 0) return Qnil;
2710 OBJ_TAINT(str);
2711
2712 return str;
2713 }
2714
2715 static void
2716 rscheck(const char *rsptr, long rslen, VALUE rs)
2717 {
2718 if (!rs) return;
2719 if (RSTRING_PTR(rs) != rsptr && RSTRING_LEN(rs) != rslen)
2720 rb_raise(rb_eRuntimeError, "rs modified");
2721 }
2722
2723 static int
2724 appendline(rb_io_t *fptr, int delim, VALUE *strp, long *lp)
2725 {
2726 VALUE str = *strp;
2727 long limit = *lp;
2728
2729 if (NEED_READCONV(fptr)) {
2730 SET_BINARY_MODE(fptr);
2731 make_readconv(fptr, 0);
2732 do {
2733 const char *p, *e;
2734 int searchlen;
2735 if (fptr->cbuf.len) {
2736 p = fptr->cbuf.ptr+fptr->cbuf.off;
2737 searchlen = fptr->cbuf.len;
2738 if (0 < limit && limit < searchlen)
2739 searchlen = (int)limit;
2740 e = memchr(p, delim, searchlen);
2741 if (e) {
2742 int len = (int)(e-p+1);
2743 if (NIL_P(str))
2744 *strp = str = rb_str_new(p, len);
2745 else
2746 rb_str_buf_cat(str, p, len);
2747 fptr->cbuf.off += len;
2748 fptr->cbuf.len -= len;
2749 limit -= len;
2750 *lp = limit;
2751 return delim;
2752 }
2753
2754 if (NIL_P(str))
2755 *strp = str = rb_str_new(p, searchlen);
2756 else
2757 rb_str_buf_cat(str, p, searchlen);
2758 fptr->cbuf.off += searchlen;
2759 fptr->cbuf.len -= searchlen;
2760 limit -= searchlen;
2761
2762 if (limit == 0) {
2763 *lp = limit;
2764 return (unsigned char)RSTRING_PTR(str)[RSTRING_LEN(str)-1];
2765 }
2766 }
2767 } while (more_char(fptr) != MORE_CHAR_FINISHED);
2768 clear_readconv(fptr);
2769 *lp = limit;
2770 return EOF;
2771 }
2772
2773 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
2774 do {
2775 long pending = READ_DATA_PENDING_COUNT(fptr);
2776 if (pending > 0) {
2777 const char *p = READ_DATA_PENDING_PTR(fptr);
2778 const char *e;
2779 long last;
2780
2781 if (limit > 0 && pending > limit) pending = limit;
2782 e = memchr(p, delim, pending);
2783 if (e) pending = e - p + 1;
2784 if (!NIL_P(str)) {
2785 last = RSTRING_LEN(str);
2786 rb_str_resize(str, last + pending);
2787 }
2788 else {
2789 last = 0;
2790 *strp = str = rb_str_buf_new(pending);
2791 rb_str_set_len(str, pending);
2792 }
2793 read_buffered_data(RSTRING_PTR(str) + last, pending, fptr); /* must not fail */
2794 limit -= pending;
2795 *lp = limit;
2796 if (e) return delim;
2797 if (limit == 0)
2798 return (unsigned char)RSTRING_PTR(str)[RSTRING_LEN(str)-1];
2799 }
2800 READ_CHECK(fptr);
2801 } while (io_fillbuf(fptr) >= 0);
2802 *lp = limit;
2803 return EOF;
2804 }
2805
2806 static inline int
2807 swallow(rb_io_t *fptr, int term)
2808 {
2809 if (NEED_READCONV(fptr)) {
2810 rb_encoding *enc = io_read_encoding(fptr);
2811 int needconv = rb_enc_mbminlen(enc) != 1;
2812 SET_BINARY_MODE(fptr);
2813 make_readconv(fptr, 0);
2814 do {
2815 size_t cnt;
2816 while ((cnt = READ_CHAR_PENDING_COUNT(fptr)) > 0) {
2817 const char *p = READ_CHAR_PENDING_PTR(fptr);
2818 int i;
2819 if (!needconv) {
2820 if (*p != term) return TRUE;
2821 i = (int)cnt;
2822 while (--i && *++p == term);
2823 }
2824 else {
2825 const char *e = p + cnt;
2826 if (rb_enc_ascget(p, e, &i, enc) != term) return TRUE;
2827 while ((p += i) < e && rb_enc_ascget(p, e, &i, enc) == term);
2828 i = (int)(e - p);
2829 }
2830 io_shift_cbuf(fptr, (int)cnt - i, NULL);
2831 }
2832 } while (more_char(fptr) != MORE_CHAR_FINISHED);
2833 return FALSE;
2834 }
2835
2836 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
2837 do {
2838 size_t cnt;
2839 while ((cnt = READ_DATA_PENDING_COUNT(fptr)) > 0) {
2840 char buf[1024];
2841 const char *p = READ_DATA_PENDING_PTR(fptr);
2842 int i;
2843 if (cnt > sizeof buf) cnt = sizeof buf;
2844 if (*p != term) return TRUE;
2845 i = (int)cnt;
2846 while (--i && *++p == term);
2847 if (!read_buffered_data(buf, cnt - i, fptr)) /* must not fail */
2848 rb_sys_fail_path(fptr->pathv);
2849 }
2850 READ_CHECK(fptr);
2851 } while (io_fillbuf(fptr) == 0);
2852 return FALSE;
2853 }
2854
2855 static VALUE
2856 rb_io_getline_fast(rb_io_t *fptr, rb_encoding *enc, VALUE io)
2857 {
2858 VALUE str = Qnil;
2859 int len = 0;
2860 long pos = 0;
2861 int cr = 0;
2862
2863 for (;;) {
2864 int pending = READ_DATA_PENDING_COUNT(fptr);
2865
2866 if (pending > 0) {
2867 const char *p = READ_DATA_PENDING_PTR(fptr);
2868 const char *e;
2869
2870 e = memchr(p, '\n', pending);
2871 if (e) {
2872 pending = (int)(e - p + 1);
2873 }
2874 if (NIL_P(str)) {
2875 str = rb_str_new(p, pending);
2876 fptr->rbuf.off += pending;
2877 fptr->rbuf.len -= pending;
2878 }
2879 else {
2880 rb_str_resize(str, len + pending);
2881 read_buffered_data(RSTRING_PTR(str)+len, pending, fptr);
2882 }
2883 len += pending;
2884 if (cr != ENC_CODERANGE_BROKEN)
2885 pos += rb_str_coderange_scan_restartable(RSTRING_PTR(str) + pos, RSTRING_PTR(str) + len, enc, &cr);
2886 if (e) break;
2887 }
2888 READ_CHECK(fptr);
2889 if (io_fillbuf(fptr) < 0) {
2890 if (NIL_P(str)) return Qnil;
2891 break;
2892 }
2893 }
2894
2895 str = io_enc_str(str, fptr);
2896 ENC_CODERANGE_SET(str, cr);
2897 fptr->lineno++;
2898 if (io == ARGF.current_file) {
2899 ARGF.lineno++;
2900 ARGF.last_lineno = ARGF.lineno;
2901 }
2902 else {
2903 ARGF.last_lineno = fptr->lineno;
2904 }
2905
2906 return str;
2907 }
2908
2909 static void
2910 prepare_getline_args(int argc, VALUE *argv, VALUE *rsp, long *limit, VALUE io)
2911 {
2912 VALUE rs = rb_rs, lim = Qnil;
2913 rb_io_t *fptr;
2914
2915 if (argc == 1) {
2916 VALUE tmp = Qnil;
2917
2918 if (NIL_P(argv[0]) || !NIL_P(tmp = rb_check_string_type(argv[0]))) {
2919 rs = tmp;
2920 }
2921 else {
2922 lim = argv[0];
2923 }
2924 }
2925 else if (2 <= argc) {
2926 rb_scan_args(argc, argv, "2", &rs, &lim);
2927 if (!NIL_P(rs))
2928 StringValue(rs);
2929 }
2930 if (!NIL_P(rs)) {
2931 rb_encoding *enc_rs, *enc_io;
2932
2933 GetOpenFile(io, fptr);
2934 enc_rs = rb_enc_get(rs);
2935 enc_io = io_read_encoding(fptr);
2936 if (enc_io != enc_rs &&
2937 (rb_enc_str_coderange(rs) != ENC_CODERANGE_7BIT ||
2938 (RSTRING_LEN(rs) > 0 && !rb_enc_asciicompat(enc_io)))) {
2939 if (rs == rb_default_rs) {
2940 rs = rb_enc_str_new(0, 0, enc_io);
2941 rb_str_buf_cat_ascii(rs, "\n");
2942 }
2943 else {
2944 rb_raise(rb_eArgError, "encoding mismatch: %s IO with %s RS",
2945 rb_enc_name(enc_io),
2946 rb_enc_name(enc_rs));
2947 }
2948 }
2949 }
2950 *rsp = rs;
2951 *limit = NIL_P(lim) ? -1L : NUM2LONG(lim);
2952 }
2953
2954 static VALUE
2955 rb_io_getline_1(VALUE rs, long limit, VALUE io)
2956 {
2957 VALUE str = Qnil;
2958 rb_io_t *fptr;
2959 int nolimit = 0;
2960 rb_encoding *enc;
2961
2962 GetOpenFile(io, fptr);
2963 rb_io_check_char_readable(fptr);
2964 if (NIL_P(rs) && limit < 0) {
2965 str = read_all(fptr, 0, Qnil);
2966 if (RSTRING_LEN(str) == 0) return Qnil;
2967 }
2968 else if (limit == 0) {
2969 return rb_enc_str_new(0, 0, io_read_encoding(fptr));
2970 }
2971 else if (rs == rb_default_rs && limit < 0 && !NEED_READCONV(fptr) &&
2972 rb_enc_asciicompat(enc = io_read_encoding(fptr))) {
2973 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
2974 return rb_io_getline_fast(fptr, enc, io);
2975 }
2976 else {
2977 int c, newline = -1;
2978 const char *rsptr = 0;
2979 long rslen = 0;
2980 int rspara = 0;
2981 int extra_limit = 16;
2982
2983 SET_BINARY_MODE(fptr);
2984 enc = io_read_encoding(fptr);
2985
2986 if (!NIL_P(rs)) {
2987 rslen = RSTRING_LEN(rs);
2988 if (rslen == 0) {
2989 rsptr = "\n\n";
2990 rslen = 2;
2991 rspara = 1;
2992 swallow(fptr, '\n');
2993 rs = 0;
2994 if (!rb_enc_asciicompat(enc)) {
2995 rs = rb_usascii_str_new(rsptr, rslen);
2996 rs = rb_str_encode(rs, rb_enc_from_encoding(enc), 0, Qnil);
2997 OBJ_FREEZE(rs);
2998 rsptr = RSTRING_PTR(rs);
2999 rslen = RSTRING_LEN(rs);
3000 }
3001 }
3002 else {
3003 rsptr = RSTRING_PTR(rs);
3004 }
3005 newline = (unsigned char)rsptr[rslen - 1];
3006 }
3007
3008 /* MS - Optimisation */
3009 while ((c = appendline(fptr, newline, &str, &limit)) != EOF) {
3010 const char *s, *p, *pp, *e;
3011
3012 if (c == newline) {
3013 if (RSTRING_LEN(str) < rslen) continue;
3014 s = RSTRING_PTR(str);
3015 e = s + RSTRING_LEN(str);
3016 p = e - rslen;
3017 pp = rb_enc_left_char_head(s, p, e, enc);
3018 if (pp != p) continue;
3019 if (!rspara) rscheck(rsptr, rslen, rs);
3020 if (memcmp(p, rsptr, rslen) == 0) break;
3021 }
3022 if (limit == 0) {
3023 s = RSTRING_PTR(str);
3024 p = s + RSTRING_LEN(str);
3025 pp = rb_enc_left_char_head(s, p-1, p, enc);
3026 if (extra_limit &&
3027 MBCLEN_NEEDMORE_P(rb_enc_precise_mbclen(pp, p, enc))) {
3028 /* relax the limit while incomplete character.
3029 * extra_limit limits the relax length */
3030 limit = 1;
3031 extra_limit--;
3032 }
3033 else {
3034 nolimit = 1;
3035 break;
3036 }
3037 }
3038 }
3039
3040 if (rspara) {
3041 if (c != EOF) {
3042 swallow(fptr, '\n');
3043 }
3044 }
3045 if (!NIL_P(str))
3046 str = io_enc_str(str, fptr);
3047 }
3048
3049 if (!NIL_P(str)) {
3050 if (!nolimit) {
3051 fptr->lineno++;
3052 if (io == ARGF.current_file) {
3053 ARGF.lineno++;
3054 ARGF.last_lineno = ARGF.lineno;
3055 }
3056 else {
3057 ARGF.last_lineno = fptr->lineno;
3058 }
3059 }
3060 }
3061
3062 return str;
3063 }
3064
3065 static VALUE
3066 rb_io_getline(int argc, VALUE *argv, VALUE io)
3067 {
3068 VALUE rs;
3069 long limit;
3070
3071 prepare_getline_args(argc, argv, &rs, &limit, io);
3072 return rb_io_getline_1(rs, limit, io);
3073 }
3074
3075 VALUE
3076 rb_io_gets(VALUE io)
3077 {
3078 return rb_io_getline_1(rb_default_rs, -1, io);
3079 }
3080
3081 /*
3082 * call-seq:
3083 * ios.gets(sep=$/) -> string or nil
3084 * ios.gets(limit) -> string or nil
3085 * ios.gets(sep, limit) -> string or nil
3086 *
3087 * Reads the next ``line'' from the I/O stream; lines are separated by
3088 * <i>sep</i>. A separator of <code>nil</code> reads the entire
3089 * contents, and a zero-length separator reads the input a paragraph at
3090 * a time (two successive newlines in the input separate paragraphs).
3091 * The stream must be opened for reading or an <code>IOError</code>
3092 * will be raised. The line read in will be returned and also assigned
3093 * to <code>$_</code>. Returns <code>nil</code> if called at end of
3094 * file. If the first argument is an integer, or optional second
3095 * argument is given, the returning string would not be longer than the
3096 * given value in bytes.
3097 *
3098 * File.new("testfile").gets #=> "This is line one\n"
3099 * $_ #=> "This is line one\n"
3100 */
3101
3102 static VALUE
3103 rb_io_gets_m(int argc, VALUE *argv, VALUE io)
3104 {
3105 VALUE str;
3106
3107 str = rb_io_getline(argc, argv, io);
3108 rb_lastline_set(str);
3109
3110 return str;
3111 }
3112
3113 /*
3114 * call-seq:
3115 * ios.lineno -> integer
3116 *
3117 * Returns the current line number in <em>ios</em>. The stream must be
3118 * opened for reading. <code>lineno</code> counts the number of times
3119 * #gets is called rather than the number of newlines encountered. The two
3120 * values will differ if #gets is called with a separator other than newline.
3121 *
3122 * Methods that use <code>$/</code> like #each, #lines and #readline will
3123 * also increment <code>lineno</code>.
3124 *
3125 * See also the <code>$.</code> variable.
3126 *
3127 * f = File.new("testfile")
3128 * f.lineno #=> 0
3129 * f.gets #=> "This is line one\n"
3130 * f.lineno #=> 1
3131 * f.gets #=> "This is line two\n"
3132 * f.lineno #=> 2
3133 */
3134
3135 static VALUE
3136 rb_io_lineno(VALUE io)
3137 {
3138 rb_io_t *fptr;
3139
3140 GetOpenFile(io, fptr);
3141 rb_io_check_char_readable(fptr);
3142 return INT2NUM(fptr->lineno);
3143 }
3144
3145 /*
3146 * call-seq:
3147 * ios.lineno = integer -> integer
3148 *
3149 * Manually sets the current line number to the given value.
3150 * <code>$.</code> is updated only on the next read.
3151 *
3152 * f = File.new("testfile")
3153 * f.gets #=> "This is line one\n"
3154 * $. #=> 1
3155 * f.lineno = 1000
3156 * f.lineno #=> 1000
3157 * $. #=> 1 # lineno of last read
3158 * f.gets #=> "This is line two\n"
3159 * $. #=> 1001 # lineno of last read
3160 */
3161
3162 static VALUE
3163 rb_io_set_lineno(VALUE io, VALUE lineno)
3164 {
3165 rb_io_t *fptr;
3166
3167 GetOpenFile(io, fptr);
3168 rb_io_check_char_readable(fptr);
3169 fptr->lineno = NUM2INT(lineno);
3170 return lineno;
3171 }
3172
3173 /*
3174 * call-seq:
3175 * ios.readline(sep=$/) -> string
3176 * ios.readline(limit) -> string
3177 * ios.readline(sep, limit) -> string
3178 *
3179 * Reads a line as with <code>IO#gets</code>, but raises an
3180 * <code>EOFError</code> on end of file.
3181 */
3182
3183 static VALUE
3184 rb_io_readline(int argc, VALUE *argv, VALUE io)
3185 {
3186 VALUE line = rb_io_gets_m(argc, argv, io);
3187
3188 if (NIL_P(line)) {
3189 rb_eof_error();
3190 }
3191 return line;
3192 }
3193
3194 /*
3195 * call-seq:
3196 * ios.readlines(sep=$/) -> array
3197 * ios.readlines(limit) -> array
3198 * ios.readlines(sep, limit) -> array
3199 *
3200 * Reads all of the lines in <em>ios</em>, and returns them in
3201 * <i>anArray</i>. Lines are separated by the optional <i>sep</i>. If
3202 * <i>sep</i> is <code>nil</code>, the rest of the stream is returned
3203 * as a single record. If the first argument is an integer, or
3204 * optional second argument is given, the returning string would not be
3205 * longer than the given value in bytes. The stream must be opened for
3206 * reading or an <code>IOError</code> will be raised.
3207 *
3208 * f = File.new("testfile")
3209 * f.readlines[0] #=> "This is line one\n"
3210 */
3211
3212 static VALUE
3213 rb_io_readlines(int argc, VALUE *argv, VALUE io)
3214 {
3215 VALUE line, ary, rs;
3216 long limit;
3217
3218 prepare_getline_args(argc, argv, &rs, &limit, io);
3219 if (limit == 0)
3220 rb_raise(rb_eArgError, "invalid limit: 0 for readlines");
3221 ary = rb_ary_new();
3222 while (!NIL_P(line = rb_io_getline_1(rs, limit, io))) {
3223 rb_ary_push(ary, line);
3224 }
3225 return ary;
3226 }
3227
3228 /*
3229 * call-seq:
3230 * ios.each(sep=$/) {|line| block } -> ios
3231 * ios.each(limit) {|line| block } -> ios
3232 * ios.each(sep,limit) {|line| block } -> ios
3233 * ios.each(...) -> an_enumerator
3234 *
3235 * ios.each_line(sep=$/) {|line| block } -> ios
3236 * ios.each_line(limit) {|line| block } -> ios
3237 * ios.each_line(sep,limit) {|line| block } -> ios
3238 * ios.each_line(...) -> an_enumerator
3239 *
3240 * Executes the block for every line in <em>ios</em>, where lines are
3241 * separated by <i>sep</i>. <em>ios</em> must be opened for
3242 * reading or an <code>IOError</code> will be raised.
3243 *
3244 * If no block is given, an enumerator is returned instead.
3245 *
3246 * f = File.new("testfile")
3247 * f.each {|line| puts "#{f.lineno}: #{line}" }
3248 *
3249 * <em>produces:</em>
3250 *
3251 * 1: This is line one
3252 * 2: This is line two
3253 * 3: This is line three
3254 * 4: And so on...
3255 */
3256
3257 static VALUE
3258 rb_io_each_line(int argc, VALUE *argv, VALUE io)
3259 {
3260 VALUE str, rs;
3261 long limit;
3262
3263 RETURN_ENUMERATOR(io, argc, argv);
3264 prepare_getline_args(argc, argv, &rs, &limit, io);
3265 if (limit == 0)
3266 rb_raise(rb_eArgError, "invalid limit: 0 for each_line");
3267 while (!NIL_P(str = rb_io_getline_1(rs, limit, io))) {
3268 rb_yield(str);
3269 }
3270 return io;
3271 }
3272
3273 /*
3274 * This is a deprecated alias for <code>each_line</code>.
3275 */
3276
3277 static VALUE
3278 rb_io_lines(int argc, VALUE *argv, VALUE io)
3279 {
3280 rb_warn("IO#lines is deprecated; use #each_line instead");
3281 if (!rb_block_given_p())
3282 return rb_enumeratorize(io, ID2SYM(rb_intern("each_line")), argc, argv);
3283 return rb_io_each_line(argc, argv, io);
3284 }
3285
3286 /*
3287 * call-seq:
3288 * ios.each_byte {|byte| block } -> ios
3289 * ios.each_byte -> an_enumerator
3290 *
3291 * Calls the given block once for each byte (0..255) in <em>ios</em>,
3292 * passing the byte as an argument. The stream must be opened for
3293 * reading or an <code>IOError</code> will be raised.
3294 *
3295 * If no block is given, an enumerator is returned instead.
3296 *
3297 * f = File.new("testfile")
3298 * checksum = 0
3299 * f.each_byte {|x| checksum ^= x } #=> #<File:testfile>
3300 * checksum #=> 12
3301 */
3302
3303 static VALUE
3304 rb_io_each_byte(VALUE io)
3305 {
3306 rb_io_t *fptr;
3307
3308 RETURN_ENUMERATOR(io, 0, 0);
3309 GetOpenFile(io, fptr);
3310
3311 for (;;) {
3312 while (fptr->rbuf.len > 0) {
3313 char *p = fptr->rbuf.ptr + fptr->rbuf.off++;
3314 fptr->rbuf.len--;
3315 rb_yield(INT2FIX(*p & 0xff));
3316 errno = 0;
3317 }
3318 rb_io_check_byte_readable(fptr);
3319 READ_CHECK(fptr);
3320 if (io_fillbuf(fptr) < 0) {
3321 break;
3322 }
3323 }
3324 return io;
3325 }
3326
3327 /*
3328 * This is a deprecated alias for <code>each_byte</code>.
3329 */
3330
3331 static VALUE
3332 rb_io_bytes(VALUE io)
3333 {
3334 rb_warn("IO#bytes is deprecated; use #each_byte instead");
3335 if (!rb_block_given_p())
3336 return rb_enumeratorize(io, ID2SYM(rb_intern("each_byte")), 0, 0);
3337 return rb_io_each_byte(io);
3338 }
3339
3340 static VALUE
3341 io_getc(rb_io_t *fptr, rb_encoding *enc)
3342 {
3343 int r, n, cr = 0;
3344 VALUE str;
3345
3346 if (NEED_READCONV(fptr)) {
3347 VALUE str = Qnil;
3348 rb_encoding *read_enc = io_read_encoding(fptr);
3349
3350 SET_BINARY_MODE(fptr);
3351 make_readconv(fptr, 0);
3352
3353 while (1) {
3354 if (fptr->cbuf.len) {
3355 r = rb_enc_precise_mbclen(fptr->cbuf.ptr+fptr->cbuf.off,
3356 fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
3357 read_enc);
3358 if (!MBCLEN_NEEDMORE_P(r))
3359 break;
3360 if (fptr->cbuf.len == fptr->cbuf.capa) {
3361 rb_raise(rb_eIOError, "too long character");
3362 }
3363 }
3364
3365 if (more_char(fptr) == MORE_CHAR_FINISHED) {
3366 if (fptr->cbuf.len == 0) {
3367 clear_readconv(fptr);
3368 return Qnil;
3369 }
3370 /* return an unit of an incomplete character just before EOF */
3371 str = rb_enc_str_new(fptr->cbuf.ptr+fptr->cbuf.off, 1, read_enc);
3372 fptr->cbuf.off += 1;
3373 fptr->cbuf.len -= 1;
3374 if (fptr->cbuf.len == 0) clear_readconv(fptr);
3375 ENC_CODERANGE_SET(str, ENC_CODERANGE_BROKEN);
3376 return str;
3377 }
3378 }
3379 if (MBCLEN_INVALID_P(r)) {
3380 r = rb_enc_mbclen(fptr->cbuf.ptr+fptr->cbuf.off,
3381 fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
3382 read_enc);
3383 io_shift_cbuf(fptr, r, &str);
3384 cr = ENC_CODERANGE_BROKEN;
3385 }
3386 else {
3387 io_shift_cbuf(fptr, MBCLEN_CHARFOUND_LEN(r), &str);
3388 cr = ENC_CODERANGE_VALID;
3389 if (MBCLEN_CHARFOUND_LEN(r) == 1 && rb_enc_asciicompat(read_enc) &&
3390 ISASCII(RSTRING_PTR(str)[0])) {
3391 cr = ENC_CODERANGE_7BIT;
3392 }
3393 }
3394 str = io_enc_str(str, fptr);
3395 ENC_CODERANGE_SET(str, cr);
3396 return str;
3397 }
3398
3399 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
3400 if (io_fillbuf(fptr) < 0) {
3401 return Qnil;
3402 }
3403 if (rb_enc_asciicompat(enc) && ISASCII(fptr->rbuf.ptr[fptr->rbuf.off])) {
3404 str = rb_str_new(fptr->rbuf.ptr+fptr->rbuf.off, 1);
3405 fptr->rbuf.off += 1;
3406 fptr->rbuf.len -= 1;
3407 cr = ENC_CODERANGE_7BIT;
3408 }
3409 else {
3410 r = rb_enc_precise_mbclen(fptr->rbuf.ptr+fptr->rbuf.off, fptr->rbuf.ptr+fptr->rbuf.off+fptr->rbuf.len, enc);
3411 if (MBCLEN_CHARFOUND_P(r) &&
3412 (n = MBCLEN_CHARFOUND_LEN(r)) <= fptr->rbuf.len) {
3413 str = rb_str_new(fptr->rbuf.ptr+fptr->rbuf.off, n);
3414 fptr->rbuf.off += n;
3415 fptr->rbuf.len -= n;
3416 cr = ENC_CODERANGE_VALID;
3417 }
3418 else if (MBCLEN_NEEDMORE_P(r)) {
3419 str = rb_str_new(fptr->rbuf.ptr+fptr->rbuf.off, fptr->rbuf.len);
3420 fptr->rbuf.len = 0;
3421 getc_needmore:
3422 if (io_fillbuf(fptr) != -1) {
3423 rb_str_cat(str, fptr->rbuf.ptr+fptr->rbuf.off, 1);
3424 fptr->rbuf.off++;
3425 fptr->rbuf.len--;
3426 r = rb_enc_precise_mbclen(RSTRING_PTR(str), RSTRING_PTR(str)+RSTRING_LEN(str), enc);
3427 if (MBCLEN_NEEDMORE_P(r)) {
3428 goto getc_needmore;
3429 }
3430 else if (MBCLEN_CHARFOUND_P(r)) {
3431 cr = ENC_CODERANGE_VALID;
3432 }
3433 }
3434 }
3435 else {
3436 str = rb_str_new(fptr->rbuf.ptr+fptr->rbuf.off, 1);
3437 fptr->rbuf.off++;
3438 fptr->rbuf.len--;
3439 }
3440 }
3441 if (!cr) cr = ENC_CODERANGE_BROKEN;
3442 str = io_enc_str(str, fptr);
3443 ENC_CODERANGE_SET(str, cr);
3444 return str;
3445 }
3446
3447 /*
3448 * call-seq:
3449 * ios.each_char {|c| block } -> ios
3450 * ios.each_char -> an_enumerator
3451 *
3452 * Calls the given block once for each character in <em>ios</em>,
3453 * passing the character as an argument. The stream must be opened for
3454 * reading or an <code>IOError</code> will be raised.
3455 *
3456 * If no block is given, an enumerator is returned instead.
3457 *
3458 * f = File.new("testfile")
3459 * f.each_char {|c| print c, ' ' } #=> #<File:testfile>
3460 */
3461
3462 static VALUE
3463 rb_io_each_char(VALUE io)
3464 {
3465 rb_io_t *fptr;
3466 rb_encoding *enc;
3467 VALUE c;
3468
3469 RETURN_ENUMERATOR(io, 0, 0);
3470 GetOpenFile(io, fptr);
3471 rb_io_check_char_readable(fptr);
3472
3473 enc = io_input_encoding(fptr);
3474 READ_CHECK(fptr);
3475 while (!NIL_P(c = io_getc(fptr, enc))) {
3476 rb_yield(c);
3477 }
3478 return io;
3479 }
3480
3481 /*
3482 * This is a deprecated alias for <code>each_char</code>.
3483 */
3484
3485 static VALUE
3486 rb_io_chars(VALUE io)
3487 {
3488 rb_warn("IO#chars is deprecated; use #each_char instead");
3489 if (!rb_block_given_p())
3490 return rb_enumeratorize(io, ID2SYM(rb_intern("each_char")), 0, 0);
3491 return rb_io_each_char(io);
3492 }
3493
3494
3495 /*
3496 * call-seq:
3497 * ios.each_codepoint {|c| block } -> ios
3498 * ios.codepoints {|c| block } -> ios
3499 * ios.each_codepoint -> an_enumerator
3500 * ios.codepoints -> an_enumerator
3501 *
3502 * Passes the <code>Integer</code> ordinal of each character in <i>ios</i>,
3503 * passing the codepoint as an argument. The stream must be opened for
3504 * reading or an <code>IOError</code> will be raised.
3505 *
3506 * If no block is given, an enumerator is returned instead.
3507 *
3508 */
3509
3510 static VALUE
3511 rb_io_each_codepoint(VALUE io)
3512 {
3513 rb_io_t *fptr;
3514 rb_encoding *enc;
3515 unsigned int c;
3516 int r, n;
3517
3518 RETURN_ENUMERATOR(io, 0, 0);
3519 GetOpenFile(io, fptr);
3520 rb_io_check_char_readable(fptr);
3521
3522 READ_CHECK(fptr);
3523 if (NEED_READCONV(fptr)) {
3524 SET_BINARY_MODE(fptr);
3525 for (;;) {
3526 make_readconv(fptr, 0);
3527 for (;;) {
3528 if (fptr->cbuf.len) {
3529 if (fptr->encs.enc)
3530 r = rb_enc_precise_mbclen(fptr->cbuf.ptr+fptr->cbuf.off,
3531 fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
3532 fptr->encs.enc);
3533 else
3534 r = ONIGENC_CONSTRUCT_MBCLEN_CHARFOUND(1);
3535 if (!MBCLEN_NEEDMORE_P(r))
3536 break;
3537 if (fptr->cbuf.len == fptr->cbuf.capa) {
3538 rb_raise(rb_eIOError, "too long character");
3539 }
3540 }
3541 if (more_char(fptr) == MORE_CHAR_FINISHED) {
3542 clear_readconv(fptr);
3543 /* ignore an incomplete character before EOF */
3544 return io;
3545 }
3546 }
3547 if (MBCLEN_INVALID_P(r)) {
3548 rb_raise(rb_eArgError, "invalid byte sequence in %s",
3549 rb_enc_name(fptr->encs.enc));
3550 }
3551 n = MBCLEN_CHARFOUND_LEN(r);
3552 if (fptr->encs.enc) {
3553 c = rb_enc_codepoint(fptr->cbuf.ptr+fptr->cbuf.off,
3554 fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
3555 fptr->encs.enc);
3556 }
3557 else {
3558 c = (unsigned char)fptr->cbuf.ptr[fptr->cbuf.off];
3559 }
3560 fptr->cbuf.off += n;
3561 fptr->cbuf.len -= n;
3562 rb_yield(UINT2NUM(c));
3563 }
3564 }
3565 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
3566 enc = io_input_encoding(fptr);
3567 for (;;) {
3568 if (io_fillbuf(fptr) < 0) {
3569 return io;
3570 }
3571 r = rb_enc_precise_mbclen(fptr->rbuf.ptr+fptr->rbuf.off,
3572 fptr->rbuf.ptr+fptr->rbuf.off+fptr->rbuf.len, enc);
3573 if (MBCLEN_CHARFOUND_P(r) &&
3574 (n = MBCLEN_CHARFOUND_LEN(r)) <= fptr->rbuf.len) {
3575 c = rb_enc_codepoint(fptr->rbuf.ptr+fptr->rbuf.off,
3576 fptr->rbuf.ptr+fptr->rbuf.off+fptr->rbuf.len, enc);
3577 fptr->rbuf.off += n;
3578 fptr->rbuf.len -= n;
3579 rb_yield(UINT2NUM(c));
3580 }
3581 else if (MBCLEN_INVALID_P(r)) {
3582 rb_raise(rb_eArgError, "invalid byte sequence in %s", rb_enc_name(enc));
3583 }
3584 else {
3585 continue;
3586 }
3587 }
3588 return io;
3589 }
3590
3591 /*
3592 * This is a deprecated alias for <code>each_codepoint</code>.
3593 */
3594
3595 static VALUE
3596 rb_io_codepoints(VALUE io)
3597 {
3598 rb_warn("IO#codepoints is deprecated; use #each_codepoint instead");
3599 if (!rb_block_given_p())
3600 return rb_enumeratorize(io, ID2SYM(rb_intern("each_codepoint")), 0, 0);
3601 return rb_io_each_codepoint(io);
3602 }
3603
3604
3605 /*
3606 * call-seq:
3607 * ios.getc -> string or nil
3608 *
3609 * Reads a one-character string from <em>ios</em>. Returns
3610 * <code>nil</code> if called at end of file.
3611 *
3612 * f = File.new("testfile")
3613 * f.getc #=> "h"
3614 * f.getc #=> "e"
3615 */
3616
3617 static VALUE
3618 rb_io_getc(VALUE io)
3619 {
3620 rb_io_t *fptr;
3621 rb_encoding *enc;
3622
3623 GetOpenFile(io, fptr);
3624 rb_io_check_char_readable(fptr);
3625
3626 enc = io_input_encoding(fptr);
3627 READ_CHECK(fptr);
3628 return io_getc(fptr, enc);
3629 }
3630
3631 /*
3632 * call-seq:
3633 * ios.readchar -> string
3634 *
3635 * Reads a one-character string from <em>ios</em>. Raises an
3636 * <code>EOFError</code> on end of file.
3637 *
3638 * f = File.new("testfile")
3639 * f.readchar #=> "h"
3640 * f.readchar #=> "e"
3641 */
3642
3643 static VALUE
3644 rb_io_readchar(VALUE io)
3645 {
3646 VALUE c = rb_io_getc(io);
3647
3648 if (NIL_P(c)) {
3649 rb_eof_error();
3650 }
3651 return c;
3652 }
3653
3654 /*
3655 * call-seq:
3656 * ios.getbyte -> fixnum or nil
3657 *
3658 * Gets the next 8-bit byte (0..255) from <em>ios</em>. Returns
3659 * <code>nil</code> if called at end of file.
3660 *
3661 * f = File.new("testfile")
3662 * f.getbyte #=> 84
3663 * f.getbyte #=> 104
3664 */
3665
3666 VALUE
3667 rb_io_getbyte(VALUE io)
3668 {
3669 rb_io_t *fptr;
3670 int c;
3671
3672 GetOpenFile(io, fptr);
3673 rb_io_check_byte_readable(fptr);
3674 READ_CHECK(fptr);
3675 if (fptr->fd == 0 && (fptr->mode & FMODE_TTY) && RB_TYPE_P(rb_stdout, T_FILE)) {
3676 rb_io_t *ofp;
3677 GetOpenFile(rb_stdout, ofp);
3678 if (ofp->mode & FMODE_TTY) {
3679 rb_io_flush(rb_stdout);
3680 }
3681 }
3682 if (io_fillbuf(fptr) < 0) {
3683 return Qnil;
3684 }
3685 fptr->rbuf.off++;
3686 fptr->rbuf.len--;
3687 c = (unsigned char)fptr->rbuf.ptr[fptr->rbuf.off-1];
3688 return INT2FIX(c & 0xff);
3689 }
3690
3691 /*
3692 * call-seq:
3693 * ios.readbyte -> fixnum
3694 *
3695 * Reads a byte as with <code>IO#getbyte</code>, but raises an
3696 * <code>EOFError</code> on end of file.
3697 */
3698
3699 static VALUE
3700 rb_io_readbyte(VALUE io)
3701 {
3702 VALUE c = rb_io_getbyte(io);
3703
3704 if (NIL_P(c)) {
3705 rb_eof_error();
3706 }
3707 return c;
3708 }
3709
3710 /*
3711 * call-seq:
3712 * ios.ungetbyte(string) -> nil
3713 * ios.ungetbyte(integer) -> nil
3714 *
3715 * Pushes back bytes (passed as a parameter) onto <em>ios</em>,
3716 * such that a subsequent buffered read will return it. Only one byte
3717 * may be pushed back before a subsequent read operation (that is,
3718 * you will be able to read only the last of several bytes that have been pushed
3719 * back). Has no effect with unbuffered reads (such as <code>IO#sysread</code>).
3720 *
3721 * f = File.new("testfile") #=> #<File:testfile>
3722 * b = f.getbyte #=> 0x38
3723 * f.ungetbyte(b) #=> nil
3724 * f.getbyte #=> 0x38
3725 */
3726
3727 VALUE
3728 rb_io_ungetbyte(VALUE io, VALUE b)
3729 {
3730 rb_io_t *fptr;
3731
3732 GetOpenFile(io, fptr);
3733 rb_io_check_byte_readable(fptr);
3734 if (NIL_P(b)) return Qnil;
3735 if (FIXNUM_P(b)) {
3736 char cc = FIX2INT(b);
3737 b = rb_str_new(&cc, 1);
3738 }
3739 else {
3740 SafeStringValue(b);
3741 }
3742 io_ungetbyte(b, fptr);
3743 return Qnil;
3744 }
3745
3746 /*
3747 * call-seq:
3748 * ios.ungetc(string) -> nil
3749 *
3750 * Pushes back one character (passed as a parameter) onto <em>ios</em>,
3751 * such that a subsequent buffered character read will return it. Only one character
3752 * may be pushed back before a subsequent read operation (that is,
3753 * you will be able to read only the last of several characters that have been pushed
3754 * back). Has no effect with unbuffered reads (such as <code>IO#sysread</code>).
3755 *
3756 * f = File.new("testfile") #=> #<File:testfile>
3757 * c = f.getc #=> "8"
3758 * f.ungetc(c) #=> nil
3759 * f.getc #=> "8"
3760 */
3761
3762 VALUE
3763 rb_io_ungetc(VALUE io, VALUE c)
3764 {
3765 rb_io_t *fptr;
3766 long len;
3767
3768 GetOpenFile(io, fptr);
3769 rb_io_check_char_readable(fptr);
3770 if (NIL_P(c)) return Qnil;
3771 if (FIXNUM_P(c)) {
3772 c = rb_enc_uint_chr(FIX2UINT(c), io_read_encoding(fptr));
3773 }
3774 else if (RB_TYPE_P(c, T_BIGNUM)) {
3775 c = rb_enc_uint_chr(NUM2UINT(c), io_read_encoding(fptr));
3776 }
3777 else {
3778 SafeStringValue(c);
3779 }
3780 if (NEED_READCONV(fptr)) {
3781 SET_BINARY_MODE(fptr);
3782 len = RSTRING_LEN(c);
3783 #if SIZEOF_LONG > SIZEOF_INT
3784 if (len > INT_MAX)
3785 rb_raise(rb_eIOError, "ungetc failed");
3786 #endif
3787 make_readconv(fptr, (int)len);
3788 if (fptr->cbuf.capa - fptr->cbuf.len < len)
3789 rb_raise(rb_eIOError, "ungetc failed");
3790 if (fptr->cbuf.off < len) {
3791 MEMMOVE(fptr->cbuf.ptr+fptr->cbuf.capa-fptr->cbuf.len,
3792 fptr->cbuf.ptr+fptr->cbuf.off,
3793 char, fptr->cbuf.len);
3794 fptr->cbuf.off = fptr->cbuf.capa-fptr->cbuf.len;
3795 }
3796 fptr->cbuf.off -= (int)len;
3797 fptr->cbuf.len += (int)len;
3798 MEMMOVE(fptr->cbuf.ptr+fptr->cbuf.off, RSTRING_PTR(c), char, len);
3799 }
3800 else {
3801 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
3802 io_ungetbyte(c, fptr);
3803 }
3804 return Qnil;
3805 }
3806
3807 /*
3808 * call-seq:
3809 * ios.isatty -> true or false
3810 * ios.tty? -> true or false
3811 *
3812 * Returns <code>true</code> if <em>ios</em> is associated with a
3813 * terminal device (tty), <code>false</code> otherwise.
3814 *
3815 * File.new("testfile").isatty #=> false
3816 * File.new("/dev/tty").isatty #=> true
3817 */
3818
3819 static VALUE
3820 rb_io_isatty(VALUE io)
3821 {
3822 rb_io_t *fptr;
3823
3824 GetOpenFile(io, fptr);
3825 if (isatty(fptr->fd) == 0)
3826 return Qfalse;
3827 return Qtrue;
3828 }
3829
3830 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
3831 /*
3832 * call-seq:
3833 * ios.close_on_exec? -> true or false
3834 *
3835 * Returns <code>true</code> if <em>ios</em> will be closed on exec.
3836 *
3837 * f = open("/dev/null")
3838 * f.close_on_exec? #=> false
3839 * f.close_on_exec = true
3840 * f.close_on_exec? #=> true
3841 * f.close_on_exec = false
3842 * f.close_on_exec? #=> false
3843 */
3844
3845 static VALUE
3846 rb_io_close_on_exec_p(VALUE io)
3847 {
3848 rb_io_t *fptr;
3849 VALUE write_io;
3850 int fd, ret;
3851
3852 write_io = GetWriteIO(io);
3853 if (io != write_io) {
3854 GetOpenFile(write_io, fptr);
3855 if (fptr && 0 <= (fd = fptr->fd)) {
3856 if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
3857 if (!(ret & FD_CLOEXEC)) return Qfalse;
3858 }
3859 }
3860
3861 GetOpenFile(io, fptr);
3862 if (fptr && 0 <= (fd = fptr->fd)) {
3863 if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
3864 if (!(ret & FD_CLOEXEC)) return Qfalse;
3865 }
3866 return Qtrue;
3867 }
3868 #else
3869 #define rb_io_close_on_exec_p rb_f_notimplement
3870 #endif
3871
3872 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
3873 /*
3874 * call-seq:
3875 * ios.close_on_exec = bool -> true or false
3876 *
3877 * Sets a close-on-exec flag.
3878 *
3879 * f = open("/dev/null")
3880 * f.close_on_exec = true
3881 * system("cat", "/proc/self/fd/#{f.fileno}") # cat: /proc/self/fd/3: No such file or directory
3882 * f.closed? #=> false
3883 *
3884 * Ruby sets close-on-exec flags of all file descriptors by default
3885 * since Ruby 2.0.0.
3886 * So you don't need to set by yourself.
3887 * Also, unsetting a close-on-exec flag can cause file descriptor leak
3888 * if another thread use fork() and exec() (via system() method for example).
3889 * If you really needs file descriptor inheritance to child process,
3890 * use spawn()'s argument such as fd=>fd.
3891 */
3892
3893 static VALUE
3894 rb_io_set_close_on_exec(VALUE io, VALUE arg)
3895 {
3896 int flag = RTEST(arg) ? FD_CLOEXEC : 0;
3897 rb_io_t *fptr;
3898 VALUE write_io;
3899 int fd, ret;
3900
3901 write_io = GetWriteIO(io);
3902 if (io != write_io) {
3903 GetOpenFile(write_io, fptr);
3904 if (fptr && 0 <= (fd = fptr->fd)) {
3905 if ((ret = fcntl(fptr->fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
3906 if ((ret & FD_CLOEXEC) != flag) {
3907 ret = (ret & ~FD_CLOEXEC) | flag;
3908 ret = fcntl(fd, F_SETFD, ret);
3909 if (ret == -1) rb_sys_fail_path(fptr->pathv);
3910 }
3911 }
3912
3913 }
3914
3915 GetOpenFile(io, fptr);
3916 if (fptr && 0 <= (fd = fptr->fd)) {
3917 if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
3918 if ((ret & FD_CLOEXEC) != flag) {
3919 ret = (ret & ~FD_CLOEXEC) | flag;
3920 ret = fcntl(fd, F_SETFD, ret);
3921 if (ret == -1) rb_sys_fail_path(fptr->pathv);
3922 }
3923 }
3924 return Qnil;
3925 }
3926 #else
3927 #define rb_io_set_close_on_exec rb_f_notimplement
3928 #endif
3929
3930 #define FMODE_PREP (1<<16)
3931 #define IS_PREP_STDIO(f) ((f)->mode & FMODE_PREP)
3932 #define PREP_STDIO_NAME(f) (RSTRING_PTR((f)->pathv))
3933
3934 static VALUE
3935 finish_writeconv(rb_io_t *fptr, int noalloc)
3936 {
3937 unsigned char *ds, *dp, *de;
3938 rb_econv_result_t res;
3939
3940 if (!fptr->wbuf.ptr) {
3941 unsigned char buf[1024];
3942 long r;
3943
3944 res = econv_destination_buffer_full;
3945 while (res == econv_destination_buffer_full) {
3946 ds = dp = buf;
3947 de = buf + sizeof(buf);
3948 res = rb_econv_convert(fptr->writeconv, NULL, NULL, &dp, de, 0);
3949 while (dp-ds) {
3950 retry:
3951 if (fptr->write_lock && rb_mutex_owned_p(fptr->write_lock))
3952 r = rb_write_internal2(fptr->fd, ds, dp-ds);
3953 else
3954 r = rb_write_internal(fptr->fd, ds, dp-ds);
3955 if (r == dp-ds)
3956 break;
3957 if (0 <= r) {
3958 ds += r;
3959 }
3960 if (rb_io_wait_writable(fptr->fd)) {
3961 if (fptr->fd < 0)
3962 return noalloc ? Qtrue : rb_exc_new3(rb_eIOError, rb_str_new_cstr("closed stream"));
3963 goto retry;
3964 }
3965 return noalloc ? Qtrue : INT2NUM(errno);
3966 }
3967 if (res == econv_invalid_byte_sequence ||
3968 res == econv_incomplete_input ||
3969 res == econv_undefined_conversion) {
3970 return noalloc ? Qtrue : rb_econv_make_exception(fptr->writeconv);
3971 }
3972 }
3973
3974 return Qnil;
3975 }
3976
3977 res = econv_destination_buffer_full;
3978 while (res == econv_destination_buffer_full) {
3979 if (fptr->wbuf.len == fptr->wbuf.capa) {
3980 if (io_fflush(fptr) < 0)
3981 return noalloc ? Qtrue : INT2NUM(errno);
3982 }
3983
3984 ds = dp = (unsigned char *)fptr->wbuf.ptr + fptr->wbuf.off + fptr->wbuf.len;
3985 de = (unsigned char *)fptr->wbuf.ptr + fptr->wbuf.capa;
3986 res = rb_econv_convert(fptr->writeconv, NULL, NULL, &dp, de, 0);
3987 fptr->wbuf.len += (int)(dp - ds);
3988 if (res == econv_invalid_byte_sequence ||
3989 res == econv_incomplete_input ||
3990 res == econv_undefined_conversion) {
3991 return noalloc ? Qtrue : rb_econv_make_exception(fptr->writeconv);
3992 }
3993 }
3994 return Qnil;
3995 }
3996
3997 struct finish_writeconv_arg {
3998 rb_io_t *fptr;
3999 int noalloc;
4000 };
4001
4002 static VALUE
4003 finish_writeconv_sync(VALUE arg)
4004 {
4005 struct finish_writeconv_arg *p = (struct finish_writeconv_arg *)arg;
4006 return finish_writeconv(p->fptr, p->noalloc);
4007 }
4008
4009 static void*
4010 nogvl_close(void *ptr)
4011 {
4012 int *fd = ptr;
4013
4014 return (void*)(intptr_t)close(*fd);
4015 }
4016
4017 static int
4018 maygvl_close(int fd, int keepgvl)
4019 {
4020 if (keepgvl)
4021 return close(fd);
4022
4023 /*
4024 * close() may block for certain file types (NFS, SO_LINGER sockets,
4025 * inotify), so let other threads run.
4026 */
4027 return (int)(intptr_t)rb_thread_call_without_gvl(nogvl_close, &fd, RUBY_UBF_IO, 0);
4028 }
4029
4030 static void*
4031 nogvl_fclose(void *ptr)
4032 {
4033 FILE *file = ptr;
4034
4035 return (void*)(intptr_t)fclose(file);
4036 }
4037
4038 static int
4039 maygvl_fclose(FILE *file, int keepgvl)
4040 {
4041 if (keepgvl)
4042 return fclose(file);
4043
4044 return (int)(intptr_t)rb_thread_call_without_gvl(nogvl_fclose, file, RUBY_UBF_IO, 0);
4045 }
4046
4047 static void
4048 fptr_finalize(rb_io_t *fptr, int noraise)
4049 {
4050 VALUE err = Qnil;
4051 int fd = fptr->fd;
4052 FILE *stdio_file = fptr->stdio_file;
4053
4054 if (fptr->writeconv) {
4055 if (fptr->write_lock && !noraise) {
4056 struct finish_writeconv_arg arg;
4057 arg.fptr = fptr;
4058 arg.noalloc = noraise;
4059 err = rb_mutex_synchronize(fptr->write_lock, finish_writeconv_sync, (VALUE)&arg);
4060 }
4061 else {
4062 err = finish_writeconv(fptr, noraise);
4063 }
4064 }
4065 if (fptr->wbuf.len) {
4066 if (noraise) {
4067 if ((int)io_flush_buffer_sync(fptr) < 0 && NIL_P(err))
4068 err = Qtrue;
4069 }
4070 else {
4071 if (io_fflush(fptr) < 0 && NIL_P(err))
4072 err = INT2NUM(errno);
4073 }
4074 }
4075
4076 fptr->fd = -1;
4077 fptr->stdio_file = 0;
4078 fptr->mode &= ~(FMODE_READABLE|FMODE_WRITABLE);
4079
4080 if (IS_PREP_STDIO(fptr) || fd <= 2) {
4081 /* need to keep FILE objects of stdin, stdout and stderr */
4082 }
4083 else if (stdio_file) {
4084 /* stdio_file is deallocated anyway
4085 * even if fclose failed. */
4086 if ((maygvl_fclose(stdio_file, noraise) < 0) && NIL_P(err))
4087 err = noraise ? Qtrue : INT2NUM(errno);
4088 }
4089 else if (0 <= fd) {
4090 /* fptr->fd may be closed even if close fails.
4091 * POSIX doesn't specify it.
4092 * We assumes it is closed. */
4093 if ((maygvl_close(fd, noraise) < 0) && NIL_P(err))
4094 err = noraise ? Qtrue : INT2NUM(errno);
4095 }
4096
4097 if (!NIL_P(err) && !noraise) {
4098 switch (TYPE(err)) {
4099 case T_FIXNUM:
4100 case T_BIGNUM:
4101 errno = NUM2INT(err);
4102 rb_sys_fail_path(fptr->pathv);
4103
4104 default:
4105 rb_exc_raise(err);
4106 }
4107 }
4108 }
4109
4110 static void
4111 rb_io_fptr_cleanup(rb_io_t *fptr, int noraise)
4112 {
4113 if (fptr->finalize) {
4114 (*fptr->finalize)(fptr, noraise);
4115 }
4116 else {
4117 fptr_finalize(fptr, noraise);
4118 }
4119 }
4120
4121 static void
4122 clear_readconv(rb_io_t *fptr)
4123 {
4124 if (fptr->readconv) {
4125 rb_econv_close(fptr->readconv);
4126 fptr->readconv = NULL;
4127 }
4128 if (fptr->cbuf.ptr) {
4129 free(fptr->cbuf.ptr);
4130 fptr->cbuf.ptr = NULL;
4131 }
4132 }
4133
4134 static void
4135 clear_writeconv(rb_io_t *fptr)
4136 {
4137 if (fptr->writeconv) {
4138 rb_econv_close(fptr->writeconv);
4139 fptr->writeconv = NULL;
4140 }
4141 fptr->writeconv_initialized = 0;
4142 }
4143
4144 static void
4145 clear_codeconv(rb_io_t *fptr)
4146 {
4147 clear_readconv(fptr);
4148 clear_writeconv(fptr);
4149 }
4150
4151 int
4152 rb_io_fptr_finalize(rb_io_t *fptr)
4153 {
4154 if (!fptr) return 0;
4155 fptr->pathv = Qnil;
4156 if (0 <= fptr->fd)
4157 rb_io_fptr_cleanup(fptr, TRUE);
4158 fptr->write_lock = 0;
4159 if (fptr->rbuf.ptr) {
4160 free(fptr->rbuf.ptr);
4161 fptr->rbuf.ptr = 0;
4162 }
4163 if (fptr->wbuf.ptr) {
4164 free(fptr->wbuf.ptr);
4165 fptr->wbuf.ptr = 0;
4166 }
4167 clear_codeconv(fptr);
4168 free(fptr);
4169 return 1;
4170 }
4171
4172 size_t rb_econv_memsize(rb_econv_t *);
4173
4174 RUBY_FUNC_EXPORTED size_t
4175 rb_io_memsize(const rb_io_t *fptr)
4176 {
4177 size_t size = sizeof(rb_io_t);
4178 size += fptr->rbuf.capa;
4179 size += fptr->wbuf.capa;
4180 size += fptr->cbuf.capa;
4181 if (fptr->readconv) size += rb_econv_memsize(fptr->readconv);
4182 if (fptr->writeconv) size += rb_econv_memsize(fptr->writeconv);
4183 return size;
4184 }
4185
4186 VALUE
4187 rb_io_close(VALUE io)
4188 {
4189 rb_io_t *fptr;
4190 int fd;
4191 VALUE write_io;
4192 rb_io_t *write_fptr;
4193
4194 write_io = GetWriteIO(io);
4195 if (io != write_io) {
4196 write_fptr = RFILE(write_io)->fptr;
4197 if (write_fptr && 0 <= write_fptr->fd) {
4198 rb_io_fptr_cleanup(write_fptr, TRUE);
4199 }
4200 }
4201
4202 fptr = RFILE(io)->fptr;
4203 if (!fptr) return Qnil;
4204 if (fptr->fd < 0) return Qnil;
4205
4206 fd = fptr->fd;
4207 rb_thread_fd_close(fd);
4208 rb_io_fptr_cleanup(fptr, FALSE);
4209
4210 if (fptr->pid) {
4211 rb_last_status_clear();
4212 rb_syswait(fptr->pid);
4213 fptr->pid = 0;
4214 }
4215
4216 return Qnil;
4217 }
4218
4219 /*
4220 * call-seq:
4221 * ios.close -> nil
4222 *
4223 * Closes <em>ios</em> and flushes any pending writes to the operating
4224 * system. The stream is unavailable for any further data operations;
4225 * an <code>IOError</code> is raised if such an attempt is made. I/O
4226 * streams are automatically closed when they are claimed by the
4227 * garbage collector.
4228 *
4229 * If <em>ios</em> is opened by <code>IO.popen</code>,
4230 * <code>close</code> sets <code>$?</code>.
4231 */
4232
4233 static VALUE
4234 rb_io_close_m(VALUE io)
4235 {
4236 if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(io)) {
4237 rb_raise(rb_eSecurityError, "Insecure: can't close");
4238 }
4239 rb_io_check_closed(RFILE(io)->fptr);
4240 rb_io_close(io);
4241 return Qnil;
4242 }
4243
4244 static VALUE
4245 io_call_close(VALUE io)
4246 {
4247 return rb_funcall(io, rb_intern("close"), 0, 0);
4248 }
4249
4250 static VALUE
4251 io_close(VALUE io)
4252 {
4253 return rb_rescue(io_call_close, io, 0, 0);
4254 }
4255
4256 /*
4257 * call-seq:
4258 * ios.closed? -> true or false
4259 *
4260 * Returns <code>true</code> if <em>ios</em> is completely closed (for
4261 * duplex streams, both reader and writer), <code>false</code>
4262 * otherwise.
4263 *
4264 * f = File.new("testfile")
4265 * f.close #=> nil
4266 * f.closed? #=> true
4267 * f = IO.popen("/bin/sh","r+")
4268 * f.close_write #=> nil
4269 * f.closed? #=> false
4270 * f.close_read #=> nil
4271 * f.closed? #=> true
4272 */
4273
4274
4275 static VALUE
4276 rb_io_closed(VALUE io)
4277 {
4278 rb_io_t *fptr;
4279 VALUE write_io;
4280 rb_io_t *write_fptr;
4281
4282 write_io = GetWriteIO(io);
4283 if (io != write_io) {
4284 write_fptr = RFILE(write_io)->fptr;
4285 if (write_fptr && 0 <= write_fptr->fd) {
4286 return Qfalse;
4287 }
4288 }
4289
4290 fptr = RFILE(io)->fptr;
4291 rb_io_check_initialized(fptr);
4292 return 0 <= fptr->fd ? Qfalse : Qtrue;
4293 }
4294
4295 /*
4296 * call-seq:
4297 * ios.close_read -> nil
4298 *
4299 * Closes the read end of a duplex I/O stream (i.e., one that contains
4300 * both a read and a write stream, such as a pipe). Will raise an
4301 * <code>IOError</code> if the stream is not duplexed.
4302 *
4303 * f = IO.popen("/bin/sh","r+")
4304 * f.close_read
4305 * f.readlines
4306 *
4307 * <em>produces:</em>
4308 *
4309 * prog.rb:3:in `readlines': not opened for reading (IOError)
4310 * from prog.rb:3
4311 */
4312
4313 static VALUE
4314 rb_io_close_read(VALUE io)
4315 {
4316 rb_io_t *fptr;
4317 VALUE write_io;
4318
4319 if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(io)) {
4320 rb_raise(rb_eSecurityError, "Insecure: can't close");
4321 }
4322 GetOpenFile(io, fptr);
4323 if (is_socket(fptr->fd, fptr->pathv)) {
4324 #ifndef SHUT_RD
4325 # define SHUT_RD 0
4326 #endif
4327 if (shutdown(fptr->fd, SHUT_RD) < 0)
4328 rb_sys_fail_path(fptr->pathv);
4329 fptr->mode &= ~FMODE_READABLE;
4330 if (!(fptr->mode & FMODE_WRITABLE))
4331 return rb_io_close(io);
4332 return Qnil;
4333 }
4334
4335 write_io = GetWriteIO(io);
4336 if (io != write_io) {
4337 rb_io_t *wfptr;
4338 rb_io_fptr_cleanup(fptr, FALSE);
4339 GetOpenFile(write_io, wfptr);
4340 RFILE(io)->fptr = wfptr;
4341 RFILE(write_io)->fptr = NULL;
4342 rb_io_fptr_finalize(fptr);
4343 return Qnil;
4344 }
4345
4346 if (fptr->mode & FMODE_WRITABLE) {
4347 rb_raise(rb_eIOError, "closing non-duplex IO for reading");
4348 }
4349 return rb_io_close(io);
4350 }
4351
4352 /*
4353 * call-seq:
4354 * ios.close_write -> nil
4355 *
4356 * Closes the write end of a duplex I/O stream (i.e., one that contains
4357 * both a read and a write stream, such as a pipe). Will raise an
4358 * <code>IOError</code> if the stream is not duplexed.
4359 *
4360 * f = IO.popen("/bin/sh","r+")
4361 * f.close_write
4362 * f.print "nowhere"
4363 *
4364 * <em>produces:</em>
4365 *
4366 * prog.rb:3:in `write': not opened for writing (IOError)
4367 * from prog.rb:3:in `print'
4368 * from prog.rb:3
4369 */
4370
4371 static VALUE
4372 rb_io_close_write(VALUE io)
4373 {
4374 rb_io_t *fptr;
4375 VALUE write_io;
4376
4377 if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(io)) {
4378 rb_raise(rb_eSecurityError, "Insecure: can't close");
4379 }
4380 write_io = GetWriteIO(io);
4381 GetOpenFile(write_io, fptr);
4382 if (is_socket(fptr->fd, fptr->pathv)) {
4383 #ifndef SHUT_WR
4384 # define SHUT_WR 1
4385 #endif
4386 if (shutdown(fptr->fd, SHUT_WR) < 0)
4387 rb_sys_fail_path(fptr->pathv);
4388 fptr->mode &= ~FMODE_WRITABLE;
4389 if (!(fptr->mode & FMODE_READABLE))
4390 return rb_io_close(write_io);
4391 return Qnil;
4392 }
4393
4394 if (fptr->mode & FMODE_READABLE) {
4395 rb_raise(rb_eIOError, "closing non-duplex IO for writing");
4396 }
4397
4398 rb_io_close(write_io);
4399 if (io != write_io) {
4400 GetOpenFile(io, fptr);
4401 fptr->tied_io_for_writing = 0;
4402 fptr->mode &= ~FMODE_DUPLEX;
4403 }
4404 return Qnil;
4405 }
4406
4407 /*
4408 * call-seq:
4409 * ios.sysseek(offset, whence=IO::SEEK_SET) -> integer
4410 *
4411 * Seeks to a given <i>offset</i> in the stream according to the value
4412 * of <i>whence</i> (see <code>IO#seek</code> for values of
4413 * <i>whence</i>). Returns the new offset into the file.
4414 *
4415 * f = File.new("testfile")
4416 * f.sysseek(-13, IO::SEEK_END) #=> 53
4417 * f.sysread(10) #=> "And so on."
4418 */
4419
4420 static VALUE
4421 rb_io_sysseek(int argc, VALUE *argv, VALUE io)
4422 {
4423 VALUE offset, ptrname;
4424 int whence = SEEK_SET;
4425 rb_io_t *fptr;
4426 off_t pos;
4427
4428 if (rb_scan_args(argc, argv, "11", &offset, &ptrname) == 2) {
4429 whence = NUM2INT(ptrname);
4430 }
4431 pos = NUM2OFFT(offset);
4432 GetOpenFile(io, fptr);
4433 if ((fptr->mode & FMODE_READABLE) &&
4434 (READ_DATA_BUFFERED(fptr) || READ_CHAR_PENDING(fptr))) {
4435 rb_raise(rb_eIOError, "sysseek for buffered IO");
4436 }
4437 if ((fptr->mode & FMODE_WRITABLE) && fptr->wbuf.len) {
4438 rb_warn("sysseek for buffered IO");
4439 }
4440 errno = 0;
4441 pos = lseek(fptr->fd, pos, whence);
4442 if (pos == -1 && errno) rb_sys_fail_path(fptr->pathv);
4443
4444 return OFFT2NUM(pos);
4445 }
4446
4447 /*
4448 * call-seq:
4449 * ios.syswrite(string) -> integer
4450 *
4451 * Writes the given string to <em>ios</em> using a low-level write.
4452 * Returns the number of bytes written. Do not mix with other methods
4453 * that write to <em>ios</em> or you may get unpredictable results.
4454 * Raises <code>SystemCallError</code> on error.
4455 *
4456 * f = File.new("out", "w")
4457 * f.syswrite("ABCDEF") #=> 6
4458 */
4459
4460 static VALUE
4461 rb_io_syswrite(VALUE io, VALUE str)
4462 {
4463 rb_io_t *fptr;
4464 long n;
4465
4466 rb_secure(4);
4467 if (!RB_TYPE_P(str, T_STRING))
4468 str = rb_obj_as_string(str);
4469
4470 io = GetWriteIO(io);
4471 GetOpenFile(io, fptr);
4472 rb_io_check_writable(fptr);
4473
4474 str = rb_str_new_frozen(str);
4475
4476 if (fptr->wbuf.len) {
4477 rb_warn("syswrite for buffered IO");
4478 }
4479
4480 n = rb_write_internal(fptr->fd, RSTRING_PTR(str), RSTRING_LEN(str));
4481
4482 if (n == -1) rb_sys_fail_path(fptr->pathv);
4483
4484 return LONG2FIX(n);
4485 }
4486
4487 /*
4488 * call-seq:
4489 * ios.sysread(maxlen[, outbuf]) -> string
4490 *
4491 * Reads <i>maxlen</i> bytes from <em>ios</em> using a low-level
4492 * read and returns them as a string. Do not mix with other methods
4493 * that read from <em>ios</em> or you may get unpredictable results.
4494 * If the optional <i>outbuf</i> argument is present, it must reference
4495 * a String, which will receive the data.
4496 * The <i>outbuf</i> will contain only the received data after the method call
4497 * even if it is not empty at the beginning.
4498 * Raises <code>SystemCallError</code> on error and
4499 * <code>EOFError</code> at end of file.
4500 *
4501 * f = File.new("testfile")
4502 * f.sysread(16) #=> "This is line one"
4503 */
4504
4505 static VALUE
4506 rb_io_sysread(int argc, VALUE *argv, VALUE io)
4507 {
4508 VALUE len, str;
4509 rb_io_t *fptr;
4510 long n, ilen;
4511
4512 rb_scan_args(argc, argv, "11", &len, &str);
4513 ilen = NUM2LONG(len);
4514
4515 io_setstrbuf(&str,ilen);
4516 if (ilen == 0) return str;
4517
4518 GetOpenFile(io, fptr);
4519 rb_io_check_byte_readable(fptr);
4520
4521 if (READ_DATA_BUFFERED(fptr)) {
4522 rb_raise(rb_eIOError, "sysread for buffered IO");
4523 }
4524
4525 n = fptr->fd;
4526
4527 /*
4528 * FIXME: removing rb_thread_wait_fd() here changes sysread semantics
4529 * on non-blocking IOs. However, it's still currently possible
4530 * for sysread to raise Errno::EAGAIN if another thread read()s
4531 * the IO after we return from rb_thread_wait_fd() but before
4532 * we call read()
4533 */
4534 rb_thread_wait_fd(fptr->fd);
4535
4536 rb_io_check_closed(fptr);
4537
4538 io_setstrbuf(&str, ilen);
4539 rb_str_locktmp(str);
4540 n = rb_read_internal(fptr->fd, RSTRING_PTR(str), ilen);
4541 rb_str_unlocktmp(str);
4542
4543 if (n == -1) {
4544 rb_sys_fail_path(fptr->pathv);
4545 }
4546 io_set_read_length(str, n);
4547 if (n == 0 && ilen > 0) {
4548 rb_eof_error();
4549 }
4550 OBJ_TAINT(str);
4551
4552 return str;
4553 }
4554
4555 VALUE
4556 rb_io_binmode(VALUE io)
4557 {
4558 rb_io_t *fptr;
4559
4560 GetOpenFile(io, fptr);
4561 if (fptr->readconv)
4562 rb_econv_binmode(fptr->readconv);
4563 if (fptr->writeconv)
4564 rb_econv_binmode(fptr->writeconv);
4565 fptr->mode |= FMODE_BINMODE;
4566 fptr->mode &= ~FMODE_TEXTMODE;
4567 fptr->writeconv_pre_ecflags &= ~ECONV_NEWLINE_DECORATOR_MASK;
4568 #ifdef O_BINARY
4569 if (!fptr->readconv) {
4570 SET_BINARY_MODE_WITH_SEEK_CUR(fptr);
4571 }
4572 else {
4573 setmode(fptr->fd, O_BINARY);
4574 }
4575 #endif
4576 return io;
4577 }
4578
4579 VALUE
4580 rb_io_ascii8bit_binmode(VALUE io)
4581 {
4582 rb_io_t *fptr;
4583
4584 GetOpenFile(io, fptr);
4585 if (fptr->readconv) {
4586 rb_econv_close(fptr->readconv);
4587 fptr->readconv = NULL;
4588 }
4589 if (fptr->writeconv) {
4590 rb_econv_close(fptr->writeconv);
4591 fptr->writeconv = NULL;
4592 }
4593 fptr->mode |= FMODE_BINMODE;
4594 fptr->mode &= ~FMODE_TEXTMODE;
4595 SET_BINARY_MODE_WITH_SEEK_CUR(fptr);
4596
4597 fptr->encs.enc = rb_ascii8bit_encoding();
4598 fptr->encs.enc2 = NULL;
4599 fptr->encs.ecflags = 0;
4600 fptr->encs.ecopts = Qnil;
4601 clear_codeconv(fptr);
4602
4603 return io;
4604 }
4605
4606 /*
4607 * call-seq:
4608 * ios.binmode -> ios
4609 *
4610 * Puts <em>ios</em> into binary mode.
4611 * Once a stream is in binary mode, it cannot be reset to nonbinary mode.
4612 *
4613 * - newline conversion disabled
4614 * - encoding conversion disabled
4615 * - content is treated as ASCII-8BIT
4616 *
4617 */
4618
4619 static VALUE
4620 rb_io_binmode_m(VALUE io)
4621 {
4622 VALUE write_io;
4623
4624 rb_io_ascii8bit_binmode(io);
4625
4626 write_io = GetWriteIO(io);
4627 if (write_io != io)
4628 rb_io_ascii8bit_binmode(write_io);
4629 return io;
4630 }
4631
4632 /*
4633 * call-seq:
4634 * ios.binmode? -> true or false
4635 *
4636 * Returns <code>true</code> if <em>ios</em> is binmode.
4637 */
4638 static VALUE
4639 rb_io_binmode_p(VALUE io)
4640 {
4641 rb_io_t *fptr;
4642 GetOpenFile(io, fptr);
4643 return fptr->mode & FMODE_BINMODE ? Qtrue : Qfalse;
4644 }
4645
4646 static const char*
4647 rb_io_fmode_modestr(int fmode)
4648 {
4649 if (fmode & FMODE_APPEND) {
4650 if ((fmode & FMODE_READWRITE) == FMODE_READWRITE) {
4651 return MODE_BTMODE("a+", "ab+", "at+");
4652 }
4653 return MODE_BTMODE("a", "ab", "at");
4654 }
4655 switch (fmode & FMODE_READWRITE) {
4656 default:
4657 rb_raise(rb_eArgError, "invalid access fmode 0x%x", fmode);
4658 case FMODE_READABLE:
4659 return MODE_BTMODE("r", "rb", "rt");
4660 case FMODE_WRITABLE:
4661 return MODE_BTMODE("w", "wb", "wt");
4662 case FMODE_READWRITE:
4663 if (fmode & FMODE_CREATE) {
4664 return MODE_BTMODE("w+", "wb+", "wt+");
4665 }
4666 return MODE_BTMODE("r+", "rb+", "rt+");
4667 }
4668 }
4669
4670 static int
4671 io_encname_bom_p(const char *name, long len)
4672 {
4673 static const char bom_prefix[] = "bom|utf-";
4674 enum {bom_prefix_len = (int)sizeof(bom_prefix) - 1};
4675 if (!len) {
4676 const char *p = strchr(name, ':');
4677 len = p ? (long)(p - name) : (long)strlen(name);
4678 }
4679 return len > bom_prefix_len && STRNCASECMP(name, bom_prefix, bom_prefix_len) == 0;
4680 }
4681
4682 int
4683 rb_io_modestr_fmode(const char *modestr)
4684 {
4685 int fmode = 0;
4686 const char *m = modestr, *p = NULL;
4687
4688 switch (*m++) {
4689 case 'r':
4690 fmode |= FMODE_READABLE;
4691 break;
4692 case 'w':
4693 fmode |= FMODE_WRITABLE | FMODE_TRUNC | FMODE_CREATE;
4694 break;
4695 case 'a':
4696 fmode |= FMODE_WRITABLE | FMODE_APPEND | FMODE_CREATE;
4697 break;
4698 default:
4699 error:
4700 rb_raise(rb_eArgError, "invalid access mode %s", modestr);
4701 }
4702
4703 while (*m) {
4704 switch (*m++) {
4705 case 'b':
4706 fmode |= FMODE_BINMODE;
4707 break;
4708 case 't':
4709 fmode |= FMODE_TEXTMODE;
4710 break;
4711 case '+':
4712 fmode |= FMODE_READWRITE;
4713 break;
4714 default:
4715 goto error;
4716 case ':':
4717 p = m;
4718 goto finished;
4719 }
4720 }
4721
4722 finished:
4723 if ((fmode & FMODE_BINMODE) && (fmode & FMODE_TEXTMODE))
4724 goto error;
4725 if (p && io_encname_bom_p(p, 0))
4726 fmode |= FMODE_SETENC_BY_BOM;
4727
4728 return fmode;
4729 }
4730
4731 int
4732 rb_io_oflags_fmode(int oflags)
4733 {
4734 int fmode = 0;
4735
4736 switch (oflags & (O_RDONLY|O_WRONLY|O_RDWR)) {
4737 case O_RDONLY:
4738 fmode = FMODE_READABLE;
4739 break;
4740 case O_WRONLY:
4741 fmode = FMODE_WRITABLE;
4742 break;
4743 case O_RDWR:
4744 fmode = FMODE_READWRITE;
4745 break;
4746 }
4747
4748 if (oflags & O_APPEND) {
4749 fmode |= FMODE_APPEND;
4750 }
4751 if (oflags & O_TRUNC) {
4752 fmode |= FMODE_TRUNC;
4753 }
4754 if (oflags & O_CREAT) {
4755 fmode |= FMODE_CREATE;
4756 }
4757 #ifdef O_BINARY
4758 if (oflags & O_BINARY) {
4759 fmode |= FMODE_BINMODE;
4760 }
4761 #endif
4762
4763 return fmode;
4764 }
4765
4766 static int
4767 rb_io_fmode_oflags(int fmode)
4768 {
4769 int oflags = 0;
4770
4771 switch (fmode & FMODE_READWRITE) {
4772 case FMODE_READABLE:
4773 oflags |= O_RDONLY;
4774 break;
4775 case FMODE_WRITABLE:
4776 oflags |= O_WRONLY;
4777 break;
4778 case FMODE_READWRITE:
4779 oflags |= O_RDWR;
4780 break;
4781 }
4782
4783 if (fmode & FMODE_APPEND) {
4784 oflags |= O_APPEND;
4785 }
4786 if (fmode & FMODE_TRUNC) {
4787 oflags |= O_TRUNC;
4788 }
4789 if (fmode & FMODE_CREATE) {
4790 oflags |= O_CREAT;
4791 }
4792 #ifdef O_BINARY
4793 if (fmode & FMODE_BINMODE) {
4794 oflags |= O_BINARY;
4795 }
4796 #endif
4797
4798 return oflags;
4799 }
4800
4801 int
4802 rb_io_modestr_oflags(const char *modestr)
4803 {
4804 return rb_io_fmode_oflags(rb_io_modestr_fmode(modestr));
4805 }
4806
4807 static const char*
4808 rb_io_oflags_modestr(int oflags)
4809 {
4810 #ifdef O_BINARY
4811 # define MODE_BINARY(a,b) ((oflags & O_BINARY) ? (b) : (a))
4812 #else
4813 # define MODE_BINARY(a,b) (a)
4814 #endif
4815 int accmode = oflags & (O_RDONLY|O_WRONLY|O_RDWR);
4816 if (oflags & O_APPEND) {
4817 if (accmode == O_WRONLY) {
4818 return MODE_BINARY("a", "ab");
4819 }
4820 if (accmode == O_RDWR) {
4821 return MODE_BINARY("a+", "ab+");
4822 }
4823 }
4824 switch (oflags & (O_RDONLY|O_WRONLY|O_RDWR)) {
4825 default:
4826 rb_raise(rb_eArgError, "invalid access oflags 0x%x", oflags);
4827 case O_RDONLY:
4828 return MODE_BINARY("r", "rb");
4829 case O_WRONLY:
4830 return MODE_BINARY("w", "wb");
4831 case O_RDWR:
4832 return MODE_BINARY("r+", "rb+");
4833 }
4834 }
4835
4836 /*
4837 * Convert external/internal encodings to enc/enc2
4838 * NULL => use default encoding
4839 * Qnil => no encoding specified (internal only)
4840 */
4841 static void
4842 rb_io_ext_int_to_encs(rb_encoding *ext, rb_encoding *intern, rb_encoding **enc, rb_encoding **enc2, int fmode)
4843 {
4844 int default_ext = 0;
4845
4846 if (ext == NULL) {
4847 ext = rb_default_external_encoding();
4848 default_ext = 1;
4849 }
4850 if (intern == NULL && ext != rb_ascii8bit_encoding())
4851 /* If external is ASCII-8BIT, no default transcoding */
4852 intern = rb_default_internal_encoding();
4853 if (intern == NULL || intern == (rb_encoding *)Qnil ||
4854 (!(fmode & FMODE_SETENC_BY_BOM) && (intern == ext))) {
4855 /* No internal encoding => use external + no transcoding */
4856 *enc = (default_ext && intern != ext) ? NULL : ext;
4857 *enc2 = NULL;
4858 }
4859 else {
4860 *enc = intern;
4861 *enc2 = ext;
4862 }
4863 }
4864
4865 static void
4866 unsupported_encoding(const char *name)
4867 {
4868 rb_warn("Unsupported encoding %s ignored", name);
4869 }
4870
4871 static void
4872 parse_mode_enc(const char *estr, rb_encoding **enc_p, rb_encoding **enc2_p, int *fmode_p)
4873 {
4874 const char *p;
4875 char encname[ENCODING_MAXNAMELEN+1];
4876 int idx, idx2;
4877 int fmode = fmode_p ? *fmode_p : 0;
4878 rb_encoding *ext_enc, *int_enc;
4879
4880 /* parse estr as "enc" or "enc2:enc" or "enc:-" */
4881
4882 p = strrchr(estr, ':');
4883 if (p) {
4884 long len = (p++) - estr;
4885 if (len == 0 || len > ENCODING_MAXNAMELEN)
4886 idx = -1;
4887 else {
4888 if (io_encname_bom_p(estr, len)) {
4889 fmode |= FMODE_SETENC_BY_BOM;
4890 estr += 4;
4891 len -= 4;
4892 }
4893 memcpy(encname, estr, len);
4894 encname[len] = '\0';
4895 estr = encname;
4896 idx = rb_enc_find_index(encname);
4897 }
4898 }
4899 else {
4900 long len = strlen(estr);
4901 if (io_encname_bom_p(estr, len)) {
4902 fmode |= FMODE_SETENC_BY_BOM;
4903 estr += 4;
4904 len -= 4;
4905 memcpy(encname, estr, len);
4906 encname[len] = '\0';
4907 estr = encname;
4908 }
4909 idx = rb_enc_find_index(estr);
4910 }
4911 if (fmode_p) *fmode_p = fmode;
4912
4913 if (idx >= 0)
4914 ext_enc = rb_enc_from_index(idx);
4915 else {
4916 if (idx != -2)
4917 unsupported_encoding(estr);
4918 ext_enc = NULL;
4919 }
4920
4921 int_enc = NULL;
4922 if (p) {
4923 if (*p == '-' && *(p+1) == '\0') {
4924 /* Special case - "-" => no transcoding */
4925 int_enc = (rb_encoding *)Qnil;
4926 }
4927 else {
4928 idx2 = rb_enc_find_index(p);
4929 if (idx2 < 0)
4930 unsupported_encoding(p);
4931 else if (!(fmode & FMODE_SETENC_BY_BOM) && (idx2 == idx)) {
4932 int_enc = (rb_encoding *)Qnil;
4933 }
4934 else
4935 int_enc = rb_enc_from_index(idx2);
4936 }
4937 }
4938
4939 rb_io_ext_int_to_encs(ext_enc, int_enc, enc_p, enc2_p, fmode);
4940 }
4941
4942 int
4943 rb_io_extract_encoding_option(VALUE opt, rb_encoding **enc_p, rb_encoding **enc2_p, int *fmode_p)
4944 {
4945 VALUE encoding=Qnil, extenc=Qundef, intenc=Qundef, tmp;
4946 int extracted = 0;
4947 rb_encoding *extencoding = NULL;
4948 rb_encoding *intencoding = NULL;
4949
4950 if (!NIL_P(opt)) {
4951 VALUE v;
4952 v = rb_hash_lookup2(opt, sym_encoding, Qnil);
4953 if (v != Qnil) encoding = v;
4954 v = rb_hash_lookup2(opt, sym_extenc, Qundef);
4955 if (v != Qnil) extenc = v;
4956 v = rb_hash_lookup2(opt, sym_intenc, Qundef);
4957 if (v != Qundef) intenc = v;
4958 }
4959 if ((extenc != Qundef || intenc != Qundef) && !NIL_P(encoding)) {
4960 if (!NIL_P(ruby_verbose)) {
4961 int idx = rb_to_encoding_index(encoding);
4962 rb_warn("Ignoring encoding parameter '%s': %s_encoding is used",
4963 idx < 0 ? StringValueCStr(encoding) : rb_enc_name(rb_enc_from_index(idx)),
4964 extenc == Qundef ? "internal" : "external");
4965 }
4966 encoding = Qnil;
4967 }
4968 if (extenc != Qundef && !NIL_P(extenc)) {
4969 extencoding = rb_to_encoding(extenc);
4970 }
4971 if (intenc != Qundef) {
4972 if (NIL_P(intenc)) {
4973 /* internal_encoding: nil => no transcoding */
4974 intencoding = (rb_encoding *)Qnil;
4975 }
4976 else if (!NIL_P(tmp = rb_check_string_type(intenc))) {
4977 char *p = StringValueCStr(tmp);
4978
4979 if (*p == '-' && *(p+1) == '\0') {
4980 /* Special case - "-" => no transcoding */
4981 intencoding = (rb_encoding *)Qnil;
4982 }
4983 else {
4984 intencoding = rb_to_encoding(intenc);
4985 }
4986 }
4987 else {
4988 intencoding = rb_to_encoding(intenc);
4989 }
4990 if (extencoding == intencoding) {
4991 intencoding = (rb_encoding *)Qnil;
4992 }
4993 }
4994 if (!NIL_P(encoding)) {
4995 extracted = 1;
4996 if (!NIL_P(tmp = rb_check_string_type(encoding))) {
4997 parse_mode_enc(StringValueCStr(tmp), enc_p, enc2_p, fmode_p);
4998 }
4999 else {
5000 rb_io_ext_int_to_encs(rb_to_encoding(encoding), NULL, enc_p, enc2_p, 0);
5001 }
5002 }
5003 else if (extenc != Qundef || intenc != Qundef) {
5004 extracted = 1;
5005 rb_io_ext_int_to_encs(extencoding, intencoding, enc_p, enc2_p, 0);
5006 }
5007 return extracted;
5008 }
5009
5010 typedef struct rb_io_enc_t convconfig_t;
5011
5012 static void
5013 validate_enc_binmode(int *fmode_p, int ecflags, rb_encoding *enc, rb_encoding *enc2)
5014 {
5015 int fmode = *fmode_p;
5016
5017 if ((fmode & FMODE_READABLE) &&
5018 !enc2 &&
5019 !(fmode & FMODE_BINMODE) &&
5020 !rb_enc_asciicompat(enc ? enc : rb_default_external_encoding()))
5021 rb_raise(rb_eArgError, "ASCII incompatible encoding needs binmode");
5022
5023 if (!(fmode & FMODE_BINMODE) &&
5024 (DEFAULT_TEXTMODE || (ecflags & ECONV_NEWLINE_DECORATOR_MASK))) {
5025 fmode |= DEFAULT_TEXTMODE;
5026 *fmode_p = fmode;
5027 }
5028 #if !DEFAULT_TEXTMODE
5029 else if (!(ecflags & ECONV_NEWLINE_DECORATOR_MASK)) {
5030 fmode &= ~FMODE_TEXTMODE;
5031 *fmode_p = fmode;
5032 }
5033 #endif
5034 }
5035
5036 static void
5037 extract_binmode(VALUE opthash, int *fmode)
5038 {
5039 if (!NIL_P(opthash)) {
5040 VALUE v;
5041 v = rb_hash_aref(opthash, sym_textmode);
5042 if (!NIL_P(v)) {
5043 if (*fmode & FMODE_TEXTMODE)
5044 rb_raise(rb_eArgError, "textmode specified twice");
5045 if (RTEST(v))
5046 *fmode |= FMODE_TEXTMODE;
5047 }
5048 v = rb_hash_aref(opthash, sym_binmode);
5049 if (!NIL_P(v)) {
5050 if (*fmode & FMODE_BINMODE)
5051 rb_raise(rb_eArgError, "binmode specified twice");
5052 if (RTEST(v))
5053 *fmode |= FMODE_BINMODE;
5054 }
5055
5056 if ((*fmode & FMODE_BINMODE) && (*fmode & FMODE_TEXTMODE))
5057 rb_raise(rb_eArgError, "both textmode and binmode specified");
5058 }
5059 }
5060
5061 static void
5062 rb_io_extract_modeenc(VALUE *vmode_p, VALUE *vperm_p, VALUE opthash,
5063 int *oflags_p, int *fmode_p, convconfig_t *convconfig_p)
5064 {
5065 VALUE vmode;
5066 int oflags, fmode;
5067 rb_encoding *enc, *enc2;
5068 int ecflags;
5069 VALUE ecopts;
5070 int has_enc = 0, has_vmode = 0;
5071 VALUE intmode;
5072
5073 vmode = *vmode_p;
5074
5075 /* Set to defaults */
5076 rb_io_ext_int_to_encs(NULL, NULL, &enc, &enc2, 0);
5077
5078 vmode_handle:
5079 if (NIL_P(vmode)) {
5080 fmode = FMODE_READABLE;
5081 oflags = O_RDONLY;
5082 }
5083 else if (!NIL_P(intmode = rb_check_to_integer(vmode, "to_int"))) {
5084 vmode = intmode;
5085 oflags = NUM2INT(intmode);
5086 fmode = rb_io_oflags_fmode(oflags);
5087 }
5088 else {
5089 const char *p;
5090
5091 SafeStringValue(vmode);
5092 p = StringValueCStr(vmode);
5093 fmode = rb_io_modestr_fmode(p);
5094 oflags = rb_io_fmode_oflags(fmode);
5095 p = strchr(p, ':');
5096 if (p) {
5097 has_enc = 1;
5098 parse_mode_enc(p+1, &enc, &enc2, &fmode);
5099 }
5100 else {
5101 rb_encoding *e;
5102
5103 e = (fmode & FMODE_BINMODE) ? rb_ascii8bit_encoding() : NULL;
5104 rb_io_ext_int_to_encs(e, NULL, &enc, &enc2, fmode);
5105 }
5106 }
5107
5108 if (NIL_P(opthash)) {
5109 ecflags = (fmode & FMODE_READABLE) ?
5110 MODE_BTMODE(ECONV_DEFAULT_NEWLINE_DECORATOR,
5111 0, ECONV_UNIVERSAL_NEWLINE_DECORATOR) : 0;
5112 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
5113 ecflags |= (fmode & FMODE_WRITABLE) ?
5114 MODE_BTMODE(TEXTMODE_NEWLINE_DECORATOR_ON_WRITE,
5115 0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE) : 0;
5116 #endif
5117 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
5118 ecopts = Qnil;
5119 }
5120 else {
5121 VALUE v;
5122 extract_binmode(opthash, &fmode);
5123 if (fmode & FMODE_BINMODE) {
5124 #ifdef O_BINARY
5125 oflags |= O_BINARY;
5126 #endif
5127 if (!has_enc)
5128 rb_io_ext_int_to_encs(rb_ascii8bit_encoding(), NULL, &enc, &enc2, fmode);
5129 }
5130 #if DEFAULT_TEXTMODE
5131 else if (NIL_P(vmode)) {
5132 fmode |= DEFAULT_TEXTMODE;
5133 }
5134 #endif
5135 if (!has_vmode) {
5136 v = rb_hash_aref(opthash, sym_mode);
5137 if (!NIL_P(v)) {
5138 if (!NIL_P(vmode)) {
5139 rb_raise(rb_eArgError, "mode specified twice");
5140 }
5141 has_vmode = 1;
5142 vmode = v;
5143 goto vmode_handle;
5144 }
5145 }
5146 v = rb_hash_aref(opthash, sym_perm);
5147 if (!NIL_P(v)) {
5148 if (vperm_p) {
5149 if (!NIL_P(*vperm_p)) {
5150 rb_raise(rb_eArgError, "perm specified twice");
5151 }
5152 *vperm_p = v;
5153 }
5154 else {
5155 /* perm no use, just ignore */
5156 }
5157 }
5158 ecflags = (fmode & FMODE_READABLE) ?
5159 MODE_BTMODE(ECONV_DEFAULT_NEWLINE_DECORATOR,
5160 0, ECONV_UNIVERSAL_NEWLINE_DECORATOR) : 0;
5161 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
5162 ecflags |= (fmode & FMODE_WRITABLE) ?
5163 MODE_BTMODE(TEXTMODE_NEWLINE_DECORATOR_ON_WRITE,
5164 0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE) : 0;
5165 #endif
5166
5167 if (rb_io_extract_encoding_option(opthash, &enc, &enc2, &fmode)) {
5168 if (has_enc) {
5169 rb_raise(rb_eArgError, "encoding specified twice");
5170 }
5171 }
5172 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
5173 ecflags = rb_econv_prepare_options(opthash, &ecopts, ecflags);
5174 }
5175
5176 validate_enc_binmode(&fmode, ecflags, enc, enc2);
5177
5178 *vmode_p = vmode;
5179
5180 *oflags_p = oflags;
5181 *fmode_p = fmode;
5182 convconfig_p->enc = enc;
5183 convconfig_p->enc2 = enc2;
5184 convconfig_p->ecflags = ecflags;
5185 convconfig_p->ecopts = ecopts;
5186 }
5187
5188 struct sysopen_struct {
5189 VALUE fname;
5190 int oflags;
5191 mode_t perm;
5192 };
5193
5194 static void *
5195 sysopen_func(void *ptr)
5196 {
5197 const struct sysopen_struct *data = ptr;
5198 const char *fname = RSTRING_PTR(data->fname);
5199 return (void *)(VALUE)rb_cloexec_open(fname, data->oflags, data->perm);
5200 }
5201
5202 static inline int
5203 rb_sysopen_internal(struct sysopen_struct *data)
5204 {
5205 int fd;
5206 fd = (int)(VALUE)rb_thread_call_without_gvl(sysopen_func, data, RUBY_UBF_IO, 0);
5207 if (0 <= fd)
5208 rb_update_max_fd(fd);
5209 return fd;
5210 }
5211
5212 static int
5213 rb_sysopen(VALUE fname, int oflags, mode_t perm)
5214 {
5215 int fd;
5216 struct sysopen_struct data;
5217
5218 data.fname = rb_str_encode_ospath(fname);
5219 data.oflags = oflags;
5220 data.perm = perm;
5221
5222 fd = rb_sysopen_internal(&data);
5223 if (fd < 0) {
5224 if (errno == EMFILE || errno == ENFILE) {
5225 rb_gc();
5226 fd = rb_sysopen_internal(&data);
5227 }
5228 if (fd < 0) {
5229 rb_sys_fail_path(fname);
5230 }
5231 }
5232 return fd;
5233 }
5234
5235 FILE *
5236 rb_fdopen(int fd, const char *modestr)
5237 {
5238 FILE *file;
5239
5240 #if defined(__sun)
5241 errno = 0;
5242 #endif
5243 file = fdopen(fd, modestr);
5244 if (!file) {
5245 if (
5246 #if defined(__sun)
5247 errno == 0 ||
5248 #endif
5249 errno == EMFILE || errno == ENFILE) {
5250 rb_gc();
5251 #if defined(__sun)
5252 errno = 0;
5253 #endif
5254 file = fdopen(fd, modestr);
5255 }
5256 if (!file) {
5257 #ifdef _WIN32
5258 if (errno == 0) errno = EINVAL;
5259 #elif defined(__sun)
5260 if (errno == 0) errno = EMFILE;
5261 #endif
5262 rb_sys_fail(0);
5263 }
5264 }
5265
5266 /* xxx: should be _IONBF? A buffer in FILE may have trouble. */
5267 #ifdef USE_SETVBUF
5268 if (setvbuf(file, NULL, _IOFBF, 0) != 0)
5269 rb_warn("setvbuf() can't be honoured (fd=%d)", fd);
5270 #endif
5271 return file;
5272 }
5273
5274 static void
5275 io_check_tty(rb_io_t *fptr)
5276 {
5277 if (isatty(fptr->fd))
5278 fptr->mode |= FMODE_TTY|FMODE_DUPLEX;
5279 }
5280
5281 static VALUE rb_io_internal_encoding(VALUE);
5282 static void io_encoding_set(rb_io_t *, VALUE, VALUE, VALUE);
5283
5284 static int
5285 io_strip_bom(VALUE io)
5286 {
5287 VALUE b1, b2, b3, b4;
5288
5289 if (NIL_P(b1 = rb_io_getbyte(io))) return 0;
5290 switch (b1) {
5291 case INT2FIX(0xEF):
5292 if (NIL_P(b2 = rb_io_getbyte(io))) break;
5293 if (b2 == INT2FIX(0xBB) && !NIL_P(b3 = rb_io_getbyte(io))) {
5294 if (b3 == INT2FIX(0xBF)) {
5295 return rb_utf8_encindex();
5296 }
5297 rb_io_ungetbyte(io, b3);
5298 }
5299 rb_io_ungetbyte(io, b2);
5300 break;
5301
5302 case INT2FIX(0xFE):
5303 if (NIL_P(b2 = rb_io_getbyte(io))) break;
5304 if (b2 == INT2FIX(0xFF)) {
5305 return rb_enc_find_index("UTF-16BE");
5306 }
5307 rb_io_ungetbyte(io, b2);
5308 break;
5309
5310 case INT2FIX(0xFF):
5311 if (NIL_P(b2 = rb_io_getbyte(io))) break;
5312 if (b2 == INT2FIX(0xFE)) {
5313 b3 = rb_io_getbyte(io);
5314 if (b3 == INT2FIX(0) && !NIL_P(b4 = rb_io_getbyte(io))) {
5315 if (b4 == INT2FIX(0)) {
5316 return rb_enc_find_index("UTF-32LE");
5317 }
5318 rb_io_ungetbyte(io, b4);
5319 rb_io_ungetbyte(io, b3);
5320 }
5321 else {
5322 rb_io_ungetbyte(io, b3);
5323 return rb_enc_find_index("UTF-16LE");
5324 }
5325 }
5326 rb_io_ungetbyte(io, b2);
5327 break;
5328
5329 case INT2FIX(0):
5330 if (NIL_P(b2 = rb_io_getbyte(io))) break;
5331 if (b2 == INT2FIX(0) && !NIL_P(b3 = rb_io_getbyte(io))) {
5332 if (b3 == INT2FIX(0xFE) && !NIL_P(b4 = rb_io_getbyte(io))) {
5333 if (b4 == INT2FIX(0xFF)) {
5334 return rb_enc_find_index("UTF-32BE");
5335 }
5336 rb_io_ungetbyte(io, b4);
5337 }
5338 rb_io_ungetbyte(io, b3);
5339 }
5340 rb_io_ungetbyte(io, b2);
5341 break;
5342 }
5343 rb_io_ungetbyte(io, b1);
5344 return 0;
5345 }
5346
5347 static void
5348 io_set_encoding_by_bom(VALUE io)
5349 {
5350 int idx = io_strip_bom(io);
5351 rb_io_t *fptr;
5352
5353 GetOpenFile(io, fptr);
5354 if (idx) {
5355 io_encoding_set(fptr, rb_enc_from_encoding(rb_enc_from_index(idx)),
5356 rb_io_internal_encoding(io), Qnil);
5357 }
5358 else {
5359 fptr->encs.enc2 = NULL;
5360 }
5361 }
5362
5363 static VALUE
5364 rb_file_open_generic(VALUE io, VALUE filename, int oflags, int fmode, convconfig_t *convconfig, mode_t perm)
5365 {
5366 rb_io_t *fptr;
5367 convconfig_t cc;
5368 if (!convconfig) {
5369 /* Set to default encodings */
5370 rb_io_ext_int_to_encs(NULL, NULL, &cc.enc, &cc.enc2, fmode);
5371 cc.ecflags = 0;
5372 cc.ecopts = Qnil;
5373 convconfig = &cc;
5374 }
5375 validate_enc_binmode(&fmode, convconfig->ecflags,
5376 convconfig->enc, convconfig->enc2);
5377
5378 MakeOpenFile(io, fptr);
5379 fptr->mode = fmode;
5380 fptr->encs = *convconfig;
5381 fptr->pathv = rb_str_new_frozen(filename);
5382 fptr->fd = rb_sysopen(fptr->pathv, oflags, perm);
5383 io_check_tty(fptr);
5384 if (fmode & FMODE_SETENC_BY_BOM) io_set_encoding_by_bom(io);
5385
5386 return io;
5387 }
5388
5389 static VALUE
5390 rb_file_open_internal(VALUE io, VALUE filename, const char *modestr)
5391 {
5392 int fmode = rb_io_modestr_fmode(modestr);
5393 const char *p = strchr(modestr, ':');
5394 convconfig_t convconfig;
5395
5396 if (p) {
5397 parse_mode_enc(p+1, &convconfig.enc, &convconfig.enc2, &fmode);
5398 }
5399 else {
5400 rb_encoding *e;
5401 /* Set to default encodings */
5402
5403 e = (fmode & FMODE_BINMODE) ? rb_ascii8bit_encoding() : NULL;
5404 rb_io_ext_int_to_encs(e, NULL, &convconfig.enc, &convconfig.enc2, fmode);
5405 convconfig.ecflags = 0;
5406 convconfig.ecopts = Qnil;
5407 }
5408
5409 return rb_file_open_generic(io, filename,
5410 rb_io_fmode_oflags(fmode),
5411 fmode,
5412 &convconfig,
5413 0666);
5414 }
5415
5416 VALUE
5417 rb_file_open_str(VALUE fname, const char *modestr)
5418 {
5419 FilePathValue(fname);
5420 return rb_file_open_internal(io_alloc(rb_cFile), fname, modestr);
5421 }
5422
5423 VALUE
5424 rb_file_open(const char *fname, const char *modestr)
5425 {
5426 return rb_file_open_internal(io_alloc(rb_cFile), rb_str_new_cstr(fname), modestr);
5427 }
5428
5429 #if defined(__CYGWIN__) || !defined(HAVE_FORK)
5430 static struct pipe_list {
5431 rb_io_t *fptr;
5432 struct pipe_list *next;
5433 } *pipe_list;
5434
5435 static void
5436 pipe_add_fptr(rb_io_t *fptr)
5437 {
5438 struct pipe_list *list;
5439
5440 list = ALLOC(struct pipe_list);
5441 list->fptr = fptr;
5442 list->next = pipe_list;
5443 pipe_list = list;
5444 }
5445
5446 static void
5447 pipe_del_fptr(rb_io_t *fptr)
5448 {
5449 struct pipe_list *list = pipe_list;
5450 struct pipe_list *tmp;
5451
5452 if (list->fptr == fptr) {
5453 pipe_list = list->next;
5454 free(list);
5455 return;
5456 }
5457
5458 while (list->next) {
5459 if (list->next->fptr == fptr) {
5460 tmp = list->next;
5461 list->next = list->next->next;
5462 free(tmp);
5463 return;
5464 }
5465 list = list->next;
5466 }
5467 }
5468
5469 static void
5470 pipe_atexit(void)
5471 {
5472 struct pipe_list *list = pipe_list;
5473 struct pipe_list *tmp;
5474
5475 while (list) {
5476 tmp = list->next;
5477 rb_io_fptr_finalize(list->fptr);
5478 list = tmp;
5479 }
5480 }
5481
5482 static void
5483 pipe_finalize(rb_io_t *fptr, int noraise)
5484 {
5485 #if !defined(HAVE_FORK) && !defined(_WIN32)
5486 int status = 0;
5487 if (fptr->stdio_file) {
5488 status = pclose(fptr->stdio_file);
5489 }
5490 fptr->fd = -1;
5491 fptr->stdio_file = 0;
5492 rb_last_status_set(status, fptr->pid);
5493 #else
5494 fptr_finalize(fptr, noraise);
5495 #endif
5496 pipe_del_fptr(fptr);
5497 }
5498 #endif
5499
5500 void
5501 rb_io_synchronized(rb_io_t *fptr)
5502 {
5503 rb_io_check_initialized(fptr);
5504 fptr->mode |= FMODE_SYNC;
5505 }
5506
5507 void
5508 rb_io_unbuffered(rb_io_t *fptr)
5509 {
5510 rb_io_synchronized(fptr);
5511 }
5512
5513 int
5514 rb_pipe(int *pipes)
5515 {
5516 int ret;
5517 ret = rb_cloexec_pipe(pipes);
5518 if (ret == -1) {
5519 if (errno == EMFILE || errno == ENFILE) {
5520 rb_gc();
5521 ret = rb_cloexec_pipe(pipes);
5522 }
5523 }
5524 if (ret == 0) {
5525 rb_update_max_fd(pipes[0]);
5526 rb_update_max_fd(pipes[1]);
5527 }
5528 return ret;
5529 }
5530
5531 #ifdef _WIN32
5532 #define HAVE_SPAWNV 1
5533 #define spawnv(mode, cmd, args) rb_w32_aspawn((mode), (cmd), (args))
5534 #define spawn(mode, cmd) rb_w32_spawn((mode), (cmd), 0)
5535 #endif
5536
5537 #if defined(HAVE_FORK) || defined(HAVE_SPAWNV)
5538 struct popen_arg {
5539 VALUE execarg_obj;
5540 struct rb_execarg *eargp;
5541 int modef;
5542 int pair[2];
5543 int write_pair[2];
5544 };
5545 #endif
5546
5547 #ifdef HAVE_FORK
5548 static void
5549 popen_redirect(struct popen_arg *p)
5550 {
5551 if ((p->modef & FMODE_READABLE) && (p->modef & FMODE_WRITABLE)) {
5552 close(p->write_pair[1]);
5553 if (p->write_pair[0] != 0) {
5554 dup2(p->write_pair[0], 0);
5555 close(p->write_pair[0]);
5556 }
5557 close(p->pair[0]);
5558 if (p->pair[1] != 1) {
5559 dup2(p->pair[1], 1);
5560 close(p->pair[1]);
5561 }
5562 }
5563 else if (p->modef & FMODE_READABLE) {
5564 close(p->pair[0]);
5565 if (p->pair[1] != 1) {
5566 dup2(p->pair[1], 1);
5567 close(p->pair[1]);
5568 }
5569 }
5570 else {
5571 close(p->pair[1]);
5572 if (p->pair[0] != 0) {
5573 dup2(p->pair[0], 0);
5574 close(p->pair[0]);
5575 }
5576 }
5577 }
5578
5579 #if defined(__linux__)
5580 /* Linux /proc/self/status contains a line: "FDSize:\t<nnn>\n"
5581 * Since /proc may not be available, linux_get_maxfd is just a hint.
5582 * This function, linux_get_maxfd, must be async-signal-safe.
5583 * I.e. opendir() is not usable.
5584 *
5585 * Note that memchr() and memcmp is *not* async-signal-safe in POSIX.
5586 * However they are easy to re-implement in async-signal-safe manner.
5587 * (Also note that there is missing/memcmp.c.)
5588 */
5589 static int
5590 linux_get_maxfd(void)
5591 {
5592 int fd;
5593 char buf[4096], *p, *np, *e;
5594 ssize_t ss;
5595 fd = rb_cloexec_open("/proc/self/status", O_RDONLY|O_NOCTTY, 0);
5596 if (fd == -1) return -1;
5597 ss = read(fd, buf, sizeof(buf));
5598 if (ss == -1) goto err;
5599 p = buf;
5600 e = buf + ss;
5601 while ((int)sizeof("FDSize:\t0\n")-1 <= e-p &&
5602 (np = memchr(p, '\n', e-p)) != NULL) {
5603 if (memcmp(p, "FDSize:", sizeof("FDSize:")-1) == 0) {
5604 int fdsize;
5605 p += sizeof("FDSize:")-1;
5606 *np = '\0';
5607 fdsize = (int)ruby_strtoul(p, (char **)NULL, 10);
5608 close(fd);
5609 return fdsize;
5610 }
5611 p = np+1;
5612 }
5613 /* fall through */
5614
5615 err:
5616 close(fd);
5617 return -1;
5618 }
5619 #endif
5620
5621 /* This function should be async-signal-safe. */
5622 void
5623 rb_close_before_exec(int lowfd, int maxhint, VALUE noclose_fds)
5624 {
5625 int fd, ret;
5626 int max = (int)max_file_descriptor;
5627 #ifdef F_MAXFD
5628 /* F_MAXFD is available since NetBSD 2.0. */
5629 ret = fcntl(0, F_MAXFD); /* async-signal-safe */
5630 if (ret != -1)
5631 maxhint = max = ret;
5632 #elif defined(__linux__)
5633 ret = linux_get_maxfd();
5634 if (maxhint < ret)
5635 maxhint = ret;
5636 /* maxhint = max = ret; if (ret == -1) abort(); // test */
5637 #endif
5638 if (max < maxhint)
5639 max = maxhint;
5640 for (fd = lowfd; fd <= max; fd++) {
5641 if (!NIL_P(noclose_fds) &&
5642 RTEST(rb_hash_lookup(noclose_fds, INT2FIX(fd)))) /* async-signal-safe */
5643 continue;
5644 ret = fcntl(fd, F_GETFD); /* async-signal-safe */
5645 if (ret != -1 && !(ret & FD_CLOEXEC)) {
5646 fcntl(fd, F_SETFD, ret|FD_CLOEXEC); /* async-signal-safe */
5647 }
5648 #define CONTIGUOUS_CLOSED_FDS 20
5649 if (ret != -1) {
5650 if (max < fd + CONTIGUOUS_CLOSED_FDS)
5651 max = fd + CONTIGUOUS_CLOSED_FDS;
5652 }
5653 }
5654 }
5655
5656 static int
5657 popen_exec(void *pp, char *errmsg, size_t errmsg_len)
5658 {
5659 struct popen_arg *p = (struct popen_arg*)pp;
5660
5661 return rb_exec_async_signal_safe(p->eargp, errmsg, errmsg_len);
5662 }
5663 #endif
5664
5665 static VALUE
5666 pipe_open(VALUE execarg_obj, const char *modestr, int fmode, convconfig_t *convconfig)
5667 {
5668 struct rb_execarg *eargp = NIL_P(execarg_obj) ? NULL : rb_execarg_get(execarg_obj);
5669 VALUE prog = eargp ? (eargp->use_shell ? eargp->invoke.sh.shell_script : eargp->invoke.cmd.command_name) : Qfalse ;
5670 rb_pid_t pid = 0;
5671 rb_io_t *fptr;
5672 VALUE port;
5673 rb_io_t *write_fptr;
5674 VALUE write_port;
5675 #if defined(HAVE_FORK)
5676 int status;
5677 char errmsg[80] = { '\0' };
5678 #endif
5679 #if defined(HAVE_FORK) || defined(HAVE_SPAWNV)
5680 struct popen_arg arg;
5681 int e = 0;
5682 #endif
5683 #if defined(HAVE_SPAWNV)
5684 # if defined(HAVE_SPAWNVE)
5685 # define DO_SPAWN(cmd, args, envp) ((args) ? \
5686 spawnve(P_NOWAIT, (cmd), (args), (envp)) : \
5687 spawne(P_NOWAIT, (cmd), (envp)))
5688 # else
5689 # define DO_SPAWN(cmd, args, envp) ((args) ? \
5690 spawnv(P_NOWAIT, (cmd), (args)) : \
5691 spawn(P_NOWAIT, (cmd)))
5692 # endif
5693 # if !defined(HAVE_FORK)
5694 char **args = NULL;
5695 # if defined(HAVE_SPAWNVE)
5696 char **envp = NULL;
5697 # endif
5698 # endif
5699 #endif
5700 #if !defined(HAVE_FORK)
5701 struct rb_execarg sarg, *sargp = &sarg;
5702 #endif
5703 FILE *fp = 0;
5704 int fd = -1;
5705 int write_fd = -1;
5706 #if !defined(HAVE_FORK)
5707 const char *cmd = 0;
5708 #if !defined(HAVE_SPAWNV)
5709 int argc;
5710 VALUE *argv;
5711 #endif
5712
5713 if (prog)
5714 cmd = StringValueCStr(prog);
5715 #endif
5716
5717 #if defined(HAVE_FORK) || defined(HAVE_SPAWNV)
5718 arg.execarg_obj = execarg_obj;
5719 arg.eargp = eargp;
5720 arg.modef = fmode;
5721 arg.pair[0] = arg.pair[1] = -1;
5722 arg.write_pair[0] = arg.write_pair[1] = -1;
5723 # if !defined(HAVE_FORK)
5724 if (eargp && !eargp->use_shell) {
5725 args = ARGVSTR2ARGV(eargp->invoke.cmd.argv_str);
5726 }
5727 # endif
5728 switch (fmode & (FMODE_READABLE|FMODE_WRITABLE)) {
5729 case FMODE_READABLE|FMODE_WRITABLE:
5730 if (rb_pipe(arg.write_pair) < 0)
5731 rb_sys_fail_str(prog);
5732 if (rb_pipe(arg.pair) < 0) {
5733 int e = errno;
5734 close(arg.write_pair[0]);
5735 close(arg.write_pair[1]);
5736 errno = e;
5737 rb_sys_fail_str(prog);
5738 }
5739 if (eargp) {
5740 rb_execarg_addopt(execarg_obj, INT2FIX(0), INT2FIX(arg.write_pair[0]));
5741 rb_execarg_addopt(execarg_obj, INT2FIX(1), INT2FIX(arg.pair[1]));
5742 }
5743 break;
5744 case FMODE_READABLE:
5745 if (rb_pipe(arg.pair) < 0)
5746 rb_sys_fail_str(prog);
5747 if (eargp)
5748 rb_execarg_addopt(execarg_obj, INT2FIX(1), INT2FIX(arg.pair[1]));
5749 break;
5750 case FMODE_WRITABLE:
5751 if (rb_pipe(arg.pair) < 0)
5752 rb_sys_fail_str(prog);
5753 if (eargp)
5754 rb_execarg_addopt(execarg_obj, INT2FIX(0), INT2FIX(arg.pair[0]));
5755 break;
5756 default:
5757 rb_sys_fail_str(prog);
5758 }
5759 if (!NIL_P(execarg_obj)) {
5760 rb_execarg_fixup(execarg_obj);
5761 # if defined(HAVE_FORK)
5762 pid = rb_fork_async_signal_safe(&status, popen_exec, &arg, arg.eargp->redirect_fds, errmsg, sizeof(errmsg));
5763 # else
5764 rb_execarg_run_options(eargp, sargp, NULL, 0);
5765 # if defined(HAVE_SPAWNVE)
5766 if (eargp->envp_str) envp = (char **)RSTRING_PTR(eargp->envp_str);
5767 # endif
5768 while ((pid = DO_SPAWN(cmd, args, envp)) == -1) {
5769 /* exec failed */
5770 switch (e = errno) {
5771 case EAGAIN:
5772 # if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
5773 case EWOULDBLOCK:
5774 # endif
5775 rb_thread_sleep(1);
5776 continue;
5777 }
5778 break;
5779 }
5780 if (eargp)
5781 rb_execarg_run_options(sargp, NULL, NULL, 0);
5782 # endif
5783 }
5784 else {
5785 # if defined(HAVE_FORK)
5786 pid = rb_fork_ruby(&status);
5787 if (pid == 0) { /* child */
5788 rb_thread_atfork();
5789 popen_redirect(&arg);
5790 rb_io_synchronized(RFILE(orig_stdout)->fptr);
5791 rb_io_synchronized(RFILE(orig_stderr)->fptr);
5792 return Qnil;
5793 }
5794 # else
5795 rb_notimplement();
5796 # endif
5797 }
5798
5799 /* parent */
5800 if (pid == -1) {
5801 # if defined(HAVE_FORK)
5802 e = errno;
5803 # endif
5804 close(arg.pair[0]);
5805 close(arg.pair[1]);
5806 if ((fmode & (FMODE_READABLE|FMODE_WRITABLE)) == (FMODE_READABLE|FMODE_WRITABLE)) {
5807 close(arg.write_pair[0]);
5808 close(arg.write_pair[1]);
5809 }
5810 errno = e;
5811 # if defined(HAVE_FORK)
5812 if (errmsg[0])
5813 rb_sys_fail(errmsg);
5814 # endif
5815 rb_sys_fail_str(prog);
5816 }
5817 if ((fmode & FMODE_READABLE) && (fmode & FMODE_WRITABLE)) {
5818 close(arg.pair[1]);
5819 fd = arg.pair[0];
5820 close(arg.write_pair[0]);
5821 write_fd = arg.write_pair[1];
5822 }
5823 else if (fmode & FMODE_READABLE) {
5824 close(arg.pair[1]);
5825 fd = arg.pair[0];
5826 }
5827 else {
5828 close(arg.pair[0]);
5829 fd = arg.pair[1];
5830 }
5831 #else
5832 if (argc) {
5833 prog = rb_ary_join(rb_ary_new4(argc, argv), rb_str_new2(" "));
5834 cmd = StringValueCStr(prog);
5835 }
5836 if (!NIL_P(execarg_obj)) {
5837 rb_execarg_fixup(execarg_obj);
5838 rb_execarg_run_options(eargp, sargp, NULL, 0);
5839 }
5840 fp = popen(cmd, modestr);
5841 if (eargp)
5842 rb_execarg_run_options(sargp, NULL, NULL, 0);
5843 if (!fp) rb_sys_fail_path(prog);
5844 fd = fileno(fp);
5845 #endif
5846
5847 port = io_alloc(rb_cIO);
5848 MakeOpenFile(port, fptr);
5849 fptr->fd = fd;
5850 fptr->stdio_file = fp;
5851 fptr->mode = fmode | FMODE_SYNC|FMODE_DUPLEX;
5852 if (convconfig) {
5853 fptr->encs = *convconfig;
5854 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
5855 if (fptr->encs.ecflags & ECONV_DEFAULT_NEWLINE_DECORATOR) {
5856 fptr->encs.ecflags |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;
5857 }
5858 #endif
5859 }
5860 else {
5861 if (NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {
5862 fptr->encs.ecflags |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;
5863 }
5864 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
5865 if (NEED_NEWLINE_DECORATOR_ON_WRITE(fptr)) {
5866 fptr->encs.ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
5867 }
5868 #endif
5869 }
5870 fptr->pid = pid;
5871
5872 if (0 <= write_fd) {
5873 write_port = io_alloc(rb_cIO);
5874 MakeOpenFile(write_port, write_fptr);
5875 write_fptr->fd = write_fd;
5876 write_fptr->mode = (fmode & ~FMODE_READABLE)| FMODE_SYNC|FMODE_DUPLEX;
5877 fptr->mode &= ~FMODE_WRITABLE;
5878 fptr->tied_io_for_writing = write_port;
5879 rb_ivar_set(port, rb_intern("@tied_io_for_writing"), write_port);
5880 }
5881
5882 #if defined (__CYGWIN__) || !defined(HAVE_FORK)
5883 fptr->finalize = pipe_finalize;
5884 pipe_add_fptr(fptr);
5885 #endif
5886 return port;
5887 }
5888
5889 static int
5890 is_popen_fork(VALUE prog)
5891 {
5892 if (RSTRING_LEN(prog) == 1 && RSTRING_PTR(prog)[0] == '-') {
5893 #if !defined(HAVE_FORK)
5894 rb_raise(rb_eNotImpError,
5895 "fork() function is unimplemented on this machine");
5896 #else
5897 return TRUE;
5898 #endif
5899 }
5900 return FALSE;
5901 }
5902
5903 static VALUE
5904 pipe_open_s(VALUE prog, const char *modestr, int fmode, convconfig_t *convconfig)
5905 {
5906 int argc = 1;
5907 VALUE *argv = &prog;
5908 VALUE execarg_obj = Qnil;
5909
5910 if (!is_popen_fork(prog))
5911 execarg_obj = rb_execarg_new(argc, argv, TRUE);
5912 return pipe_open(execarg_obj, modestr, fmode, convconfig);
5913 }
5914
5915 /*
5916 * call-seq:
5917 * IO.popen([env,] cmd, mode="r" [, opt]) -> io
5918 * IO.popen([env,] cmd, mode="r" [, opt]) {|io| block } -> obj
5919 *
5920 * Runs the specified command as a subprocess; the subprocess's
5921 * standard input and output will be connected to the returned
5922 * <code>IO</code> object.
5923 *
5924 * The PID of the started process can be obtained by IO#pid method.
5925 *
5926 * _cmd_ is a string or an array as follows.
5927 *
5928 * cmd:
5929 * "-" : fork
5930 * commandline : command line string which is passed to a shell
5931 * [env, cmdname, arg1, ..., opts] : command name and zero or more arguments (no shell)
5932 * [env, [cmdname, argv0], arg1, ..., opts] : command name, argv[0] and zero or more arguments (no shell)
5933 * (env and opts are optional.)
5934 *
5935 * If _cmd_ is a +String+ ``<code>-</code>'',
5936 * then a new instance of Ruby is started as the subprocess.
5937 *
5938 * If <i>cmd</i> is an +Array+ of +String+,
5939 * then it will be used as the subprocess's +argv+ bypassing a shell.
5940 * The array can contains a hash at first for environments and
5941 * a hash at last for options similar to <code>spawn</code>.
5942 *
5943 * The default mode for the new file object is ``r'',
5944 * but <i>mode</i> may be set to any of the modes listed in the description for class IO.
5945 * The last argument <i>opt</i> qualifies <i>mode</i>.
5946 *
5947 * # set IO encoding
5948 * IO.popen("nkf -e filename", :external_encoding=>"EUC-JP") {|nkf_io|
5949 * euc_jp_string = nkf_io.read
5950 * }
5951 *
5952 * # merge standard output and standard error using
5953 * # spawn option. See the document of Kernel.spawn.
5954 * IO.popen(["ls", "/", :err=>[:child, :out]]) {|ls_io|
5955 * ls_result_with_error = ls_io.read
5956 * }
5957 *
5958 * # spawn options can be mixed with IO options
5959 * IO.popen(["ls", "/"], :err=>[:child, :out]) {|ls_io|
5960 * ls_result_with_error = ls_io.read
5961 * }
5962 *
5963 * Raises exceptions which <code>IO.pipe</code> and
5964 * <code>Kernel.spawn</code> raise.
5965 *
5966 * If a block is given, Ruby will run the command as a child connected
5967 * to Ruby with a pipe. Ruby's end of the pipe will be passed as a
5968 * parameter to the block.
5969 * At the end of block, Ruby close the pipe and sets <code>$?</code>.
5970 * In this case <code>IO.popen</code> returns
5971 * the value of the block.
5972 *
5973 * If a block is given with a _cmd_ of ``<code>-</code>'',
5974 * the block will be run in two separate processes: once in the parent,
5975 * and once in a child. The parent process will be passed the pipe
5976 * object as a parameter to the block, the child version of the block
5977 * will be passed <code>nil</code>, and the child's standard in and
5978 * standard out will be connected to the parent through the pipe. Not
5979 * available on all platforms.
5980 *
5981 * f = IO.popen("uname")
5982 * p f.readlines
5983 * f.close
5984 * puts "Parent is #{Process.pid}"
5985 * IO.popen("date") { |f| puts f.gets }
5986 * IO.popen("-") {|f| $stderr.puts "#{Process.pid} is here, f is #{f.inspect}"}
5987 * p $?
5988 * IO.popen(%w"sed -e s|^|<foo>| -e s&$&;zot;&", "r+") {|f|
5989 * f.puts "bar"; f.close_write; puts f.gets
5990 * }
5991 *
5992 * <em>produces:</em>
5993 *
5994 * ["Linux\n"]
5995 * Parent is 21346
5996 * Thu Jan 15 22:41:19 JST 2009
5997 * 21346 is here, f is #<IO:fd 3>
5998 * 21352 is here, f is nil
5999 * #<Process::Status: pid 21352 exit 0>
6000 * <foo>bar;zot;
6001 */
6002
6003 static VALUE
6004 rb_io_s_popen(int argc, VALUE *argv, VALUE klass)
6005 {
6006 const char *modestr;
6007 VALUE pname, pmode = Qnil, port, tmp, opt = Qnil, env = Qnil, execarg_obj = Qnil;
6008 int oflags, fmode;
6009 convconfig_t convconfig;
6010
6011 if (argc > 1 && !NIL_P(opt = rb_check_hash_type(argv[argc-1]))) --argc;
6012 if (argc > 1 && !NIL_P(env = rb_check_hash_type(argv[0]))) --argc, ++argv;
6013 switch (argc) {
6014 case 2:
6015 pmode = argv[1];
6016 case 1:
6017 pname = argv[0];
6018 break;
6019 default:
6020 {
6021 int ex = !NIL_P(opt);
6022 rb_error_arity(argc + ex, 1 + ex, 2 + ex);
6023 }
6024 }
6025
6026 tmp = rb_check_array_type(pname);
6027 if (!NIL_P(tmp)) {
6028 long len = RARRAY_LEN(tmp);
6029 #if SIZEOF_LONG > SIZEOF_INT
6030 if (len > INT_MAX) {
6031 rb_raise(rb_eArgError, "too many arguments");
6032 }
6033 #endif
6034 tmp = rb_ary_dup(tmp);
6035 RBASIC(tmp)->klass = 0;
6036 execarg_obj = rb_execarg_new((int)len, RARRAY_PTR(tmp), FALSE);
6037 rb_ary_clear(tmp);
6038 }
6039 else {
6040 SafeStringValue(pname);
6041 execarg_obj = Qnil;
6042 if (!is_popen_fork(pname))
6043 execarg_obj = rb_execarg_new(1, &pname, TRUE);
6044 }
6045 if (!NIL_P(execarg_obj)) {
6046 if (!NIL_P(opt))
6047 opt = rb_execarg_extract_options(execarg_obj, opt);
6048 if (!NIL_P(env))
6049 rb_execarg_setenv(execarg_obj, env);
6050 }
6051 rb_io_extract_modeenc(&pmode, 0, opt, &oflags, &fmode, &convconfig);
6052 modestr = rb_io_oflags_modestr(oflags);
6053
6054 port = pipe_open(execarg_obj, modestr, fmode, &convconfig);
6055 if (NIL_P(port)) {
6056 /* child */
6057 if (rb_block_given_p()) {
6058 rb_yield(Qnil);
6059 rb_io_flush(rb_stdout);
6060 rb_io_flush(rb_stderr);
6061 _exit(0);
6062 }
6063 return Qnil;
6064 }
6065 RBASIC(port)->klass = klass;
6066 if (rb_block_given_p()) {
6067 return rb_ensure(rb_yield, port, io_close, port);
6068 }
6069 return port;
6070 }
6071
6072 static void
6073 rb_scan_open_args(int argc, VALUE *argv,
6074 VALUE *fname_p, int *oflags_p, int *fmode_p,
6075 convconfig_t *convconfig_p, mode_t *perm_p)
6076 {
6077 VALUE opt, fname, vmode, vperm;
6078 int oflags, fmode;
6079 mode_t perm;
6080
6081 argc = rb_scan_args(argc, argv, "12:", &fname, &vmode, &vperm, &opt);
6082 FilePathValue(fname);
6083
6084 rb_io_extract_modeenc(&vmode, &vperm, opt, &oflags, &fmode, convconfig_p);
6085
6086 perm = NIL_P(vperm) ? 0666 : NUM2MODET(vperm);
6087
6088 *fname_p = fname;
6089 *oflags_p = oflags;
6090 *fmode_p = fmode;
6091 *perm_p = perm;
6092 }
6093
6094 static VALUE
6095 rb_open_file(int argc, VALUE *argv, VALUE io)
6096 {
6097 VALUE fname;
6098 int oflags, fmode;
6099 convconfig_t convconfig;
6100 mode_t perm;
6101
6102 rb_scan_open_args(argc, argv, &fname, &oflags, &fmode, &convconfig, &perm);
6103 rb_file_open_generic(io, fname, oflags, fmode, &convconfig, perm);
6104
6105 return io;
6106 }
6107
6108
6109 /*
6110 * Document-method: File::open
6111 *
6112 * call-seq:
6113 * File.open(filename, mode="r" [, opt]) -> file
6114 * File.open(filename [, mode [, perm]] [, opt]) -> file
6115 * File.open(filename, mode="r" [, opt]) {|file| block } -> obj
6116 * File.open(filename [, mode [, perm]] [, opt]) {|file| block } -> obj
6117 *
6118 * With no associated block, <code>File.open</code> is a synonym for
6119 * File.new. If the optional code block is given, it will
6120 * be passed the opened +file+ as an argument and the File object will
6121 * automatically be closed when the block terminates. The value of the block
6122 * will be returned from <code>File.open</code>.
6123 *
6124 * If a file is being created, its initial permissions may be set using the
6125 * +perm+ parameter. See File.new for further discussion.
6126 *
6127 * See IO.new for a description of the +mode+ and +opt+ parameters.
6128 */
6129
6130 /*
6131 * Document-method: IO::open
6132 *
6133 * call-seq:
6134 * IO.open(fd, mode="r" [, opt]) -> io
6135 * IO.open(fd, mode="r" [, opt]) { |io| block } -> obj
6136 *
6137 * With no associated block, <code>IO.open</code> is a synonym for IO.new. If
6138 * the optional code block is given, it will be passed +io+ as an argument,
6139 * and the IO object will automatically be closed when the block terminates.
6140 * In this instance, IO.open returns the value of the block.
6141 *
6142 * See IO.new for a description of the +fd+, +mode+ and +opt+ parameters.
6143 */
6144
6145 static VALUE
6146 rb_io_s_open(int argc, VALUE *argv, VALUE klass)
6147 {
6148 VALUE io = rb_class_new_instance(argc, argv, klass);
6149
6150 if (rb_block_given_p()) {
6151 return rb_ensure(rb_yield, io, io_close, io);
6152 }
6153
6154 return io;
6155 }
6156
6157 /*
6158 * call-seq:
6159 * IO.sysopen(path, [mode, [perm]]) -> fixnum
6160 *
6161 * Opens the given path, returning the underlying file descriptor as a
6162 * <code>Fixnum</code>.
6163 *
6164 * IO.sysopen("testfile") #=> 3
6165 */
6166
6167 static VALUE
6168 rb_io_s_sysopen(int argc, VALUE *argv)
6169 {
6170 VALUE fname, vmode, vperm;
6171 VALUE intmode;
6172 int oflags, fd;
6173 mode_t perm;
6174
6175 rb_scan_args(argc, argv, "12", &fname, &vmode, &vperm);
6176 FilePathValue(fname);
6177
6178 if (NIL_P(vmode))
6179 oflags = O_RDONLY;
6180 else if (!NIL_P(intmode = rb_check_to_integer(vmode, "to_int")))
6181 oflags = NUM2INT(intmode);
6182 else {
6183 SafeStringValue(vmode);
6184 oflags = rb_io_modestr_oflags(StringValueCStr(vmode));
6185 }
6186 if (NIL_P(vperm)) perm = 0666;
6187 else perm = NUM2MODET(vperm);
6188
6189 RB_GC_GUARD(fname) = rb_str_new4(fname);
6190 fd = rb_sysopen(fname, oflags, perm);
6191 return INT2NUM(fd);
6192 }
6193
6194 static VALUE
6195 check_pipe_command(VALUE filename_or_command)
6196 {
6197 char *s = RSTRING_PTR(filename_or_command);
6198 long l = RSTRING_LEN(filename_or_command);
6199 char *e = s + l;
6200 int chlen;
6201
6202 if (rb_enc_ascget(s, e, &chlen, rb_enc_get(filename_or_command)) == '|') {
6203 VALUE cmd = rb_str_new(s+chlen, l-chlen);
6204 OBJ_INFECT(cmd, filename_or_command);
6205 return cmd;
6206 }
6207 return Qnil;
6208 }
6209
6210 /*
6211 * call-seq:
6212 * open(path [, mode [, perm]] [, opt]) -> io or nil
6213 * open(path [, mode [, perm]] [, opt]) {|io| block } -> obj
6214 *
6215 * Creates an IO object connected to the given stream, file, or subprocess.
6216 *
6217 * If +path+ does not start with a pipe character (<code>|</code>), treat it
6218 * as the name of a file to open using the specified mode (defaulting to
6219 * "r").
6220 *
6221 * The +mode+ is either a string or an integer. If it is an integer, it
6222 * must be bitwise-or of open(2) flags, such as File::RDWR or File::EXCL. If
6223 * it is a string, it is either "fmode", "fmode:ext_enc", or
6224 * "fmode:ext_enc:int_enc".
6225 *
6226 * See the documentation of IO.new for full documentation of the +mode+ string
6227 * directives.
6228 *
6229 * If a file is being created, its initial permissions may be set using the
6230 * +perm+ parameter. See File.new and the open(2) and chmod(2) man pages for
6231 * a description of permissions.
6232 *
6233 * If a block is specified, it will be invoked with the IO object as a
6234 * parameter, and the IO will be automatically closed when the block
6235 * terminates. The call returns the value of the block.
6236 *
6237 * If +path+ starts with a pipe character (<code>"|"</code>), a subprocess is
6238 * created, connected to the caller by a pair of pipes. The returned IO
6239 * object may be used to write to the standard input and read from the
6240 * standard output of this subprocess.
6241 *
6242 * If the command following the pipe is a single minus sign
6243 * (<code>"|-"</code>), Ruby forks, and this subprocess is connected to the
6244 * parent. If the command is not <code>"-"</code>, the subprocess runs the
6245 * command.
6246 *
6247 * When the subprocess is ruby (opened via <code>"|-"</code>), the +open+
6248 * call returns +nil+. If a block is associated with the open call, that
6249 * block will run twice --- once in the parent and once in the child.
6250 *
6251 * The block parameter will be an IO object in the parent and +nil+ in the
6252 * child. The parent's +IO+ object will be connected to the child's $stdin
6253 * and $stdout. The subprocess will be terminated at the end of the block.
6254 *
6255 * === Examples
6256 *
6257 * Reading from "testfile":
6258 *
6259 * open("testfile") do |f|
6260 * print f.gets
6261 * end
6262 *
6263 * Produces:
6264 *
6265 * This is line one
6266 *
6267 * Open a subprocess and read its output:
6268 *
6269 * cmd = open("|date")
6270 * print cmd.gets
6271 * cmd.close
6272 *
6273 * Produces:
6274 *
6275 * Wed Apr 9 08:56:31 CDT 2003
6276 *
6277 * Open a subprocess running the same Ruby program:
6278 *
6279 * f = open("|-", "w+")
6280 * if f == nil
6281 * puts "in Child"
6282 * exit
6283 * else
6284 * puts "Got: #{f.gets}"
6285 * end
6286 *
6287 * Produces:
6288 *
6289 * Got: in Child
6290 *
6291 * Open a subprocess using a block to receive the IO object:
6292 *
6293 * open "|-" do |f|
6294 * if f then
6295 * # parent process
6296 * puts "Got: #{f.gets}"
6297 * else
6298 * # child process
6299 * puts "in Child"
6300 * end
6301 * end
6302 *
6303 * Produces:
6304 *
6305 * Got: in Child
6306 */
6307
6308 static VALUE
6309 rb_f_open(int argc, VALUE *argv)
6310 {
6311 ID to_open = 0;
6312 int redirect = FALSE;
6313
6314 if (argc >= 1) {
6315 CONST_ID(to_open, "to_open");
6316 if (rb_respond_to(argv[0], to_open)) {
6317 redirect = TRUE;
6318 }
6319 else {
6320 VALUE tmp = argv[0];
6321 FilePathValue(tmp);
6322 if (NIL_P(tmp)) {
6323 redirect = TRUE;
6324 }
6325 else {
6326 VALUE cmd = check_pipe_command(tmp);
6327 if (!NIL_P(cmd)) {
6328 argv[0] = cmd;
6329 return rb_io_s_popen(argc, argv, rb_cIO);
6330 }
6331 }
6332 }
6333 }
6334 if (redirect) {
6335 VALUE io = rb_funcall2(argv[0], to_open, argc-1, argv+1);
6336
6337 if (rb_block_given_p()) {
6338 return rb_ensure(rb_yield, io, io_close, io);
6339 }
6340 return io;
6341 }
6342 return rb_io_s_open(argc, argv, rb_cFile);
6343 }
6344
6345 static VALUE
6346 rb_io_open(VALUE filename, VALUE vmode, VALUE vperm, VALUE opt)
6347 {
6348 VALUE cmd;
6349 int oflags, fmode;
6350 convconfig_t convconfig;
6351 mode_t perm;
6352
6353 rb_io_extract_modeenc(&vmode, &vperm, opt, &oflags, &fmode, &convconfig);
6354 perm = NIL_P(vperm) ? 0666 : NUM2MODET(vperm);
6355
6356 if (!NIL_P(cmd = check_pipe_command(filename))) {
6357 return pipe_open_s(cmd, rb_io_oflags_modestr(oflags), fmode, &convconfig);
6358 }
6359 else {
6360 return rb_file_open_generic(io_alloc(rb_cFile), filename,
6361 oflags, fmode, &convconfig, perm);
6362 }
6363 }
6364
6365 static VALUE
6366 rb_io_open_with_args(int argc, VALUE *argv)
6367 {
6368 VALUE io;
6369
6370 io = io_alloc(rb_cFile);
6371 rb_open_file(argc, argv, io);
6372 return io;
6373 }
6374
6375 static VALUE
6376 io_reopen(VALUE io, VALUE nfile)
6377 {
6378 rb_io_t *fptr, *orig;
6379 int fd, fd2;
6380 off_t pos = 0;
6381
6382 nfile = rb_io_get_io(nfile);
6383 if (rb_safe_level() >= 4 &&
6384 (!OBJ_UNTRUSTED(io) || !OBJ_UNTRUSTED(nfile))) {
6385 rb_raise(rb_eSecurityError, "Insecure: can't reopen");
6386 }
6387 GetOpenFile(io, fptr);
6388 GetOpenFile(nfile, orig);
6389
6390 if (fptr == orig) return io;
6391 if (IS_PREP_STDIO(fptr)) {
6392 if ((fptr->stdio_file == stdin && !(orig->mode & FMODE_READABLE)) ||
6393 (fptr->stdio_file == stdout && !(orig->mode & FMODE_WRITABLE)) ||
6394 (fptr->stdio_file == stderr && !(orig->mode & FMODE_WRITABLE))) {
6395 rb_raise(rb_eArgError,
6396 "%s can't change access mode from \"%s\" to \"%s\"",
6397 PREP_STDIO_NAME(fptr), rb_io_fmode_modestr(fptr->mode),
6398 rb_io_fmode_modestr(orig->mode));
6399 }
6400 }
6401 if (fptr->mode & FMODE_WRITABLE) {
6402 if (io_fflush(fptr) < 0)
6403 rb_sys_fail(0);
6404 }
6405 else {
6406 io_tell(fptr);
6407 }
6408 if (orig->mode & FMODE_READABLE) {
6409 pos = io_tell(orig);
6410 }
6411 if (orig->mode & FMODE_WRITABLE) {
6412 if (io_fflush(orig) < 0)
6413 rb_sys_fail(0);
6414 }
6415
6416 /* copy rb_io_t structure */
6417 fptr->mode = orig->mode | (fptr->mode & FMODE_PREP);
6418 fptr->pid = orig->pid;
6419 fptr->lineno = orig->lineno;
6420 if (RTEST(orig->pathv)) fptr->pathv = orig->pathv;
6421 else if (!IS_PREP_STDIO(fptr)) fptr->pathv = Qnil;
6422 fptr->finalize = orig->finalize;
6423 #if defined (__CYGWIN__) || !defined(HAVE_FORK)
6424 if (fptr->finalize == pipe_finalize)
6425 pipe_add_fptr(fptr);
6426 #endif
6427
6428 fd = fptr->fd;
6429 fd2 = orig->fd;
6430 if (fd != fd2) {
6431 if (IS_PREP_STDIO(fptr) || fd <= 2 || !fptr->stdio_file) {
6432 /* need to keep FILE objects of stdin, stdout and stderr */
6433 if (rb_cloexec_dup2(fd2, fd) < 0)
6434 rb_sys_fail_path(orig->pathv);
6435 rb_update_max_fd(fd);
6436 }
6437 else {
6438 fclose(fptr->stdio_file);
6439 fptr->stdio_file = 0;
6440 fptr->fd = -1;
6441 if (rb_cloexec_dup2(fd2, fd) < 0)
6442 rb_sys_fail_path(orig->pathv);
6443 rb_update_max_fd(fd);
6444 fptr->fd = fd;
6445 }
6446 rb_thread_fd_close(fd);
6447 if ((orig->mode & FMODE_READABLE) && pos >= 0) {
6448 if (io_seek(fptr, pos, SEEK_SET) < 0 && errno) {
6449 rb_sys_fail_path(fptr->pathv);
6450 }
6451 if (io_seek(orig, pos, SEEK_SET) < 0 && errno) {
6452 rb_sys_fail_path(orig->pathv);
6453 }
6454 }
6455 }
6456
6457 if (fptr->mode & FMODE_BINMODE) {
6458 rb_io_binmode(io);
6459 }
6460
6461 RBASIC(io)->klass = rb_obj_class(nfile);
6462 return io;
6463 }
6464
6465 /*
6466 * call-seq:
6467 * ios.reopen(other_IO) -> ios
6468 * ios.reopen(path, mode_str) -> ios
6469 *
6470 * Reassociates <em>ios</em> with the I/O stream given in
6471 * <i>other_IO</i> or to a new stream opened on <i>path</i>. This may
6472 * dynamically change the actual class of this stream.
6473 *
6474 * f1 = File.new("testfile")
6475 * f2 = File.new("testfile")
6476 * f2.readlines[0] #=> "This is line one\n"
6477 * f2.reopen(f1) #=> #<File:testfile>
6478 * f2.readlines[0] #=> "This is line one\n"
6479 */
6480
6481 static VALUE
6482 rb_io_reopen(int argc, VALUE *argv, VALUE file)
6483 {
6484 VALUE fname, nmode, opt;
6485 int oflags;
6486 rb_io_t *fptr;
6487
6488 rb_secure(4);
6489 if (rb_scan_args(argc, argv, "11:", &fname, &nmode, &opt) == 1) {
6490 VALUE tmp = rb_io_check_io(fname);
6491 if (!NIL_P(tmp)) {
6492 return io_reopen(file, tmp);
6493 }
6494 }
6495
6496 FilePathValue(fname);
6497 rb_io_taint_check(file);
6498 fptr = RFILE(file)->fptr;
6499 if (!fptr) {
6500 fptr = RFILE(file)->fptr = ALLOC(rb_io_t);
6501 MEMZERO(fptr, rb_io_t, 1);
6502 }
6503
6504 if (!NIL_P(nmode) || !NIL_P(opt)) {
6505 int fmode;
6506 convconfig_t convconfig;
6507
6508 rb_io_extract_modeenc(&nmode, 0, opt, &oflags, &fmode, &convconfig);
6509 if (IS_PREP_STDIO(fptr) &&
6510 ((fptr->mode & FMODE_READWRITE) & (fmode & FMODE_READWRITE)) !=
6511 (fptr->mode & FMODE_READWRITE)) {
6512 rb_raise(rb_eArgError,
6513 "%s can't change access mode from \"%s\" to \"%s\"",
6514 PREP_STDIO_NAME(fptr), rb_io_fmode_modestr(fptr->mode),
6515 rb_io_fmode_modestr(fmode));
6516 }
6517 fptr->mode = fmode;
6518 fptr->encs = convconfig;
6519 }
6520 else {
6521 oflags = rb_io_fmode_oflags(fptr->mode);
6522 }
6523
6524 fptr->pathv = rb_str_new_frozen(fname);
6525 if (fptr->fd < 0) {
6526 fptr->fd = rb_sysopen(fptr->pathv, oflags, 0666);
6527 fptr->stdio_file = 0;
6528 return file;
6529 }
6530
6531 if (fptr->mode & FMODE_WRITABLE) {
6532 if (io_fflush(fptr) < 0)
6533 rb_sys_fail(0);
6534 }
6535 fptr->rbuf.off = fptr->rbuf.len = 0;
6536
6537 if (fptr->stdio_file) {
6538 if (freopen(RSTRING_PTR(fptr->pathv), rb_io_oflags_modestr(oflags), fptr->stdio_file) == 0) {
6539 rb_sys_fail_path(fptr->pathv);
6540 }
6541 fptr->fd = fileno(fptr->stdio_file);
6542 rb_fd_fix_cloexec(fptr->fd);
6543 #ifdef USE_SETVBUF
6544 if (setvbuf(fptr->stdio_file, NULL, _IOFBF, 0) != 0)
6545 rb_warn("setvbuf() can't be honoured for %s", RSTRING_PTR(fptr->pathv));
6546 #endif
6547 if (fptr->stdio_file == stderr) {
6548 if (setvbuf(fptr->stdio_file, NULL, _IONBF, BUFSIZ) != 0)
6549 rb_warn("setvbuf() can't be honoured for %s", RSTRING_PTR(fptr->pathv));
6550 }
6551 else if (fptr->stdio_file == stdout && isatty(fptr->fd)) {
6552 if (setvbuf(fptr->stdio_file, NULL, _IOLBF, BUFSIZ) != 0)
6553 rb_warn("setvbuf() can't be honoured for %s", RSTRING_PTR(fptr->pathv));
6554 }
6555 }
6556 else {
6557 if (close(fptr->fd) < 0)
6558 rb_sys_fail_path(fptr->pathv);
6559 fptr->fd = -1;
6560 fptr->fd = rb_sysopen(fptr->pathv, oflags, 0666);
6561 }
6562
6563 return file;
6564 }
6565
6566 /* :nodoc: */
6567 static VALUE
6568 rb_io_init_copy(VALUE dest, VALUE io)
6569 {
6570 rb_io_t *fptr, *orig;
6571 int fd;
6572 VALUE write_io;
6573 off_t pos;
6574
6575 io = rb_io_get_io(io);
6576 if (!OBJ_INIT_COPY(dest, io)) return dest;
6577 GetOpenFile(io, orig);
6578 MakeOpenFile(dest, fptr);
6579
6580 rb_io_flush(io);
6581
6582 /* copy rb_io_t structure */
6583 fptr->mode = orig->mode & ~FMODE_PREP;
6584 fptr->encs = orig->encs;
6585 fptr->pid = orig->pid;
6586 fptr->lineno = orig->lineno;
6587 if (!NIL_P(orig->pathv)) fptr->pathv = orig->pathv;
6588 fptr->finalize = orig->finalize;
6589 #if defined (__CYGWIN__) || !defined(HAVE_FORK)
6590 if (fptr->finalize == pipe_finalize)
6591 pipe_add_fptr(fptr);
6592 #endif
6593
6594 fd = ruby_dup(orig->fd);
6595 fptr->fd = fd;
6596 pos = io_tell(orig);
6597 if (0 <= pos)
6598 io_seek(fptr, pos, SEEK_SET);
6599 if (fptr->mode & FMODE_BINMODE) {
6600 rb_io_binmode(dest);
6601 }
6602
6603 write_io = GetWriteIO(io);
6604 if (io != write_io) {
6605 write_io = rb_obj_dup(write_io);
6606 fptr->tied_io_for_writing = write_io;
6607 rb_ivar_set(dest, rb_intern("@tied_io_for_writing"), write_io);
6608 }
6609
6610 return dest;
6611 }
6612
6613 /*
6614 * call-seq:
6615 * ios.printf(format_string [, obj, ...]) -> nil
6616 *
6617 * Formats and writes to <em>ios</em>, converting parameters under
6618 * control of the format string. See <code>Kernel#sprintf</code>
6619 * for details.
6620 */
6621
6622 VALUE
6623 rb_io_printf(int argc, VALUE *argv, VALUE out)
6624 {
6625 rb_io_write(out, rb_f_sprintf(argc, argv));
6626 return Qnil;
6627 }
6628
6629 /*
6630 * call-seq:
6631 * printf(io, string [, obj ... ]) -> nil
6632 * printf(string [, obj ... ]) -> nil
6633 *
6634 * Equivalent to:
6635 * io.write(sprintf(string, obj, ...)
6636 * or
6637 * $stdout.write(sprintf(string, obj, ...)
6638 */
6639
6640 static VALUE
6641 rb_f_printf(int argc, VALUE *argv)
6642 {
6643 VALUE out;
6644
6645 if (argc == 0) return Qnil;
6646 if (RB_TYPE_P(argv[0], T_STRING)) {
6647 out = rb_stdout;
6648 }
6649 else {
6650 out = argv[0];
6651 argv++;
6652 argc--;
6653 }
6654 rb_io_write(out, rb_f_sprintf(argc, argv));
6655
6656 return Qnil;
6657 }
6658
6659 /*
6660 * call-seq:
6661 * ios.print() -> nil
6662 * ios.print(obj, ...) -> nil
6663 *
6664 * Writes the given object(s) to <em>ios</em>. The stream must be
6665 * opened for writing. If the output field separator (<code>$,</code>)
6666 * is not <code>nil</code>, it will be inserted between each object.
6667 * If the output record separator (<code>$\</code>)
6668 * is not <code>nil</code>, it will be appended to the output. If no
6669 * arguments are given, prints <code>$_</code>. Objects that aren't
6670 * strings will be converted by calling their <code>to_s</code> method.
6671 * With no argument, prints the contents of the variable <code>$_</code>.
6672 * Returns <code>nil</code>.
6673 *
6674 * $stdout.print("This is ", 100, " percent.\n")
6675 *
6676 * <em>produces:</em>
6677 *
6678 * This is 100 percent.
6679 */
6680
6681 VALUE
6682 rb_io_print(int argc, VALUE *argv, VALUE out)
6683 {
6684 int i;
6685 VALUE line;
6686
6687 /* if no argument given, print `$_' */
6688 if (argc == 0) {
6689 argc = 1;
6690 line = rb_lastline_get();
6691 argv = &line;
6692 }
6693 for (i=0; i<argc; i++) {
6694 if (!NIL_P(rb_output_fs) && i>0) {
6695 rb_io_write(out, rb_output_fs);
6696 }
6697 rb_io_write(out, argv[i]);
6698 }
6699 if (argc > 0 && !NIL_P(rb_output_rs)) {
6700 rb_io_write(out, rb_output_rs);
6701 }
6702
6703 return Qnil;
6704 }
6705
6706 /*
6707 * call-seq:
6708 * print(obj, ...) -> nil
6709 *
6710 * Prints each object in turn to <code>$stdout</code>. If the output
6711 * field separator (<code>$,</code>) is not +nil+, its
6712 * contents will appear between each field. If the output record
6713 * separator (<code>$\</code>) is not +nil+, it will be
6714 * appended to the output. If no arguments are given, prints
6715 * <code>$_</code>. Objects that aren't strings will be converted by
6716 * calling their <code>to_s</code> method.
6717 *
6718 * print "cat", [1,2,3], 99, "\n"
6719 * $, = ", "
6720 * $\ = "\n"
6721 * print "cat", [1,2,3], 99
6722 *
6723 * <em>produces:</em>
6724 *
6725 * cat12399
6726 * cat, 1, 2, 3, 99
6727 */
6728
6729 static VALUE
6730 rb_f_print(int argc, VALUE *argv)
6731 {
6732 rb_io_print(argc, argv, rb_stdout);
6733 return Qnil;
6734 }
6735
6736 /*
6737 * call-seq:
6738 * ios.putc(obj) -> obj
6739 *
6740 * If <i>obj</i> is <code>Numeric</code>, write the character whose code is
6741 * the least-significant byte of <i>obj</i>, otherwise write the first byte
6742 * of the string representation of <i>obj</i> to <em>ios</em>. Note: This
6743 * method is not safe for use with multi-byte characters as it will truncate
6744 * them.
6745 *
6746 * $stdout.putc "A"
6747 * $stdout.putc 65
6748 *
6749 * <em>produces:</em>
6750 *
6751 * AA
6752 */
6753
6754 static VALUE
6755 rb_io_putc(VALUE io, VALUE ch)
6756 {
6757 VALUE str;
6758 if (RB_TYPE_P(ch, T_STRING)) {
6759 str = rb_str_substr(ch, 0, 1);
6760 }
6761 else {
6762 char c = NUM2CHR(ch);
6763 str = rb_str_new(&c, 1);
6764 }
6765 rb_io_write(io, str);
6766 return ch;
6767 }
6768
6769 /*
6770 * call-seq:
6771 * putc(int) -> int
6772 *
6773 * Equivalent to:
6774 *
6775 * $stdout.putc(int)
6776 *
6777 * Refer to the documentation for IO#putc for important information regarding
6778 * multi-byte characters.
6779 */
6780
6781 static VALUE
6782 rb_f_putc(VALUE recv, VALUE ch)
6783 {
6784 if (recv == rb_stdout) {
6785 return rb_io_putc(recv, ch);
6786 }
6787 return rb_funcall2(rb_stdout, rb_intern("putc"), 1, &ch);
6788 }
6789
6790
6791 static int
6792 str_end_with_asciichar(VALUE str, int c)
6793 {
6794 long len = RSTRING_LEN(str);
6795 const char *ptr = RSTRING_PTR(str);
6796 rb_encoding *enc = rb_enc_from_index(ENCODING_GET(str));
6797 int n;
6798
6799 if (len == 0) return 0;
6800 if ((n = rb_enc_mbminlen(enc)) == 1) {
6801 return ptr[len - 1] == c;
6802 }
6803 return rb_enc_ascget(ptr + ((len - 1) / n) * n, ptr + len, &n, enc) == c;
6804 }
6805
6806 static VALUE
6807 io_puts_ary(VALUE ary, VALUE out, int recur)
6808 {
6809 VALUE tmp;
6810 long i;
6811
6812 if (recur) {
6813 tmp = rb_str_new2("[...]");
6814 rb_io_puts(1, &tmp, out);
6815 return Qtrue;
6816 }
6817 ary = rb_check_array_type(ary);
6818 if (NIL_P(ary)) return Qfalse;
6819 for (i=0; i<RARRAY_LEN(ary); i++) {
6820 tmp = RARRAY_PTR(ary)[i];
6821 rb_io_puts(1, &tmp, out);
6822 }
6823 return Qtrue;
6824 }
6825
6826 /*
6827 * call-seq:
6828 * ios.puts(obj, ...) -> nil
6829 *
6830 * Writes the given objects to <em>ios</em> as with
6831 * <code>IO#print</code>. Writes a record separator (typically a
6832 * newline) after any that do not already end with a newline sequence.
6833 * If called with an array argument, writes each element on a new line.
6834 * If called without arguments, outputs a single record separator.
6835 *
6836 * $stdout.puts("this", "is", "a", "test")
6837 *
6838 * <em>produces:</em>
6839 *
6840 * this
6841 * is
6842 * a
6843 * test
6844 */
6845
6846 VALUE
6847 rb_io_puts(int argc, VALUE *argv, VALUE out)
6848 {
6849 int i;
6850 VALUE line;
6851
6852 /* if no argument given, print newline. */
6853 if (argc == 0) {
6854 rb_io_write(out, rb_default_rs);
6855 return Qnil;
6856 }
6857 for (i=0; i<argc; i++) {
6858 if (RB_TYPE_P(argv[i], T_STRING)) {
6859 line = argv[i];
6860 goto string;
6861 }
6862 if (rb_exec_recursive(io_puts_ary, argv[i], out)) {
6863 continue;
6864 }
6865 line = rb_obj_as_string(argv[i]);
6866 string:
6867 rb_io_write(out, line);
6868 if (RSTRING_LEN(line) == 0 ||
6869 !str_end_with_asciichar(line, '\n')) {
6870 rb_io_write(out, rb_default_rs);
6871 }
6872 }
6873
6874 return Qnil;
6875 }
6876
6877 /*
6878 * call-seq:
6879 * puts(obj, ...) -> nil
6880 *
6881 * Equivalent to
6882 *
6883 * $stdout.puts(obj, ...)
6884 */
6885
6886 static VALUE
6887 rb_f_puts(int argc, VALUE *argv, VALUE recv)
6888 {
6889 if (recv == rb_stdout) {
6890 return rb_io_puts(argc, argv, recv);
6891 }
6892 return rb_funcall2(rb_stdout, rb_intern("puts"), argc, argv);
6893 }
6894
6895 void
6896 rb_p(VALUE obj) /* for debug print within C code */
6897 {
6898 VALUE str = rb_obj_as_string(rb_inspect(obj));
6899 if (RB_TYPE_P(rb_stdout, T_FILE) &&
6900 rb_method_basic_definition_p(CLASS_OF(rb_stdout), id_write)) {
6901 io_write(rb_stdout, str, 1);
6902 io_write(rb_stdout, rb_default_rs, 0);
6903 }
6904 else {
6905 rb_io_write(rb_stdout, str);
6906 rb_io_write(rb_stdout, rb_default_rs);
6907 }
6908 }
6909
6910 struct rb_f_p_arg {
6911 int argc;
6912 VALUE *argv;
6913 };
6914
6915 static VALUE
6916 rb_f_p_internal(VALUE arg)
6917 {
6918 struct rb_f_p_arg *arg1 = (struct rb_f_p_arg*)arg;
6919 int argc = arg1->argc;
6920 VALUE *argv = arg1->argv;
6921 int i;
6922 VALUE ret = Qnil;
6923
6924 for (i=0; i<argc; i++) {
6925 rb_p(argv[i]);
6926 }
6927 if (argc == 1) {
6928 ret = argv[0];
6929 }
6930 else if (argc > 1) {
6931 ret = rb_ary_new4(argc, argv);
6932 }
6933 if (RB_TYPE_P(rb_stdout, T_FILE)) {
6934 rb_io_flush(rb_stdout);
6935 }
6936 return ret;
6937 }
6938
6939 /*
6940 * call-seq:
6941 * p(obj) -> obj
6942 * p(obj1, obj2, ...) -> [obj, ...]
6943 * p() -> nil
6944 *
6945 * For each object, directly writes _obj_.+inspect+ followed by a
6946 * newline to the program's standard output.
6947 *
6948 * S = Struct.new(:name, :state)
6949 * s = S['dave', 'TX']
6950 * p s
6951 *
6952 * <em>produces:</em>
6953 *
6954 * #<S name="dave", state="TX">
6955 */
6956
6957 static VALUE
6958 rb_f_p(int argc, VALUE *argv, VALUE self)
6959 {
6960 struct rb_f_p_arg arg;
6961 arg.argc = argc;
6962 arg.argv = argv;
6963
6964 return rb_uninterruptible(rb_f_p_internal, (VALUE)&arg);
6965 }
6966
6967 /*
6968 * call-seq:
6969 * obj.display(port=$>) -> nil
6970 *
6971 * Prints <i>obj</i> on the given port (default <code>$></code>).
6972 * Equivalent to:
6973 *
6974 * def display(port=$>)
6975 * port.write self
6976 * end
6977 *
6978 * For example:
6979 *
6980 * 1.display
6981 * "cat".display
6982 * [ 4, 5, 6 ].display
6983 * puts
6984 *
6985 * <em>produces:</em>
6986 *
6987 * 1cat456
6988 */
6989
6990 static VALUE
6991 rb_obj_display(int argc, VALUE *argv, VALUE self)
6992 {
6993 VALUE out;
6994
6995 if (argc == 0) {
6996 out = rb_stdout;
6997 }
6998 else {
6999 rb_scan_args(argc, argv, "01", &out);
7000 }
7001 rb_io_write(out, self);
7002
7003 return Qnil;
7004 }
7005
7006 void
7007 rb_write_error2(const char *mesg, long len)
7008 {
7009 if (rb_stderr == orig_stderr || RFILE(orig_stderr)->fptr->fd < 0) {
7010 if (fwrite(mesg, sizeof(char), (size_t)len, stderr) < (size_t)len) {
7011 /* failed to write to stderr, what can we do? */
7012 return;
7013 }
7014 }
7015 else {
7016 rb_io_write(rb_stderr, rb_str_new(mesg, len));
7017 }
7018 }
7019
7020 void
7021 rb_write_error(const char *mesg)
7022 {
7023 rb_write_error2(mesg, strlen(mesg));
7024 }
7025
7026 void
7027 rb_write_error_str(VALUE mesg)
7028 {
7029 /* a stopgap measure for the time being */
7030 if (rb_stderr == orig_stderr || RFILE(orig_stderr)->fptr->fd < 0) {
7031 size_t len = (size_t)RSTRING_LEN(mesg);
7032 if (fwrite(RSTRING_PTR(mesg), sizeof(char), len, stderr) < len) {
7033 RB_GC_GUARD(mesg);
7034 return;
7035 }
7036 }
7037 else {
7038 /* may unlock GVL, and */
7039 rb_io_write(rb_stderr, mesg);
7040 }
7041 }
7042
7043 static void
7044 must_respond_to(ID mid, VALUE val, ID id)
7045 {
7046 if (!rb_respond_to(val, mid)) {
7047 rb_raise(rb_eTypeError, "%s must have %s method, %s given",
7048 rb_id2name(id), rb_id2name(mid),
7049 rb_obj_classname(val));
7050 }
7051 }
7052
7053 static void
7054 stdout_setter(VALUE val, ID id, VALUE *variable)
7055 {
7056 must_respond_to(id_write, val, id);
7057 *variable = val;
7058 }
7059
7060 static VALUE
7061 prep_io(int fd, int fmode, VALUE klass, const char *path)
7062 {
7063 rb_io_t *fp;
7064 VALUE io = io_alloc(klass);
7065
7066 MakeOpenFile(io, fp);
7067 fp->fd = fd;
7068 #ifdef __CYGWIN__
7069 if (!isatty(fd)) {
7070 fmode |= FMODE_BINMODE;
7071 setmode(fd, O_BINARY);
7072 }
7073 #endif
7074 fp->mode = fmode;
7075 io_check_tty(fp);
7076 if (path) fp->pathv = rb_obj_freeze(rb_str_new_cstr(path));
7077 rb_update_max_fd(fd);
7078
7079 return io;
7080 }
7081
7082 VALUE
7083 rb_io_fdopen(int fd, int oflags, const char *path)
7084 {
7085 VALUE klass = rb_cIO;
7086
7087 if (path && strcmp(path, "-")) klass = rb_cFile;
7088 return prep_io(fd, rb_io_oflags_fmode(oflags), klass, path);
7089 }
7090
7091 static VALUE
7092 prep_stdio(FILE *f, int fmode, VALUE klass, const char *path)
7093 {
7094 rb_io_t *fptr;
7095 VALUE io = prep_io(fileno(f), fmode|FMODE_PREP|DEFAULT_TEXTMODE, klass, path);
7096
7097 GetOpenFile(io, fptr);
7098 fptr->encs.ecflags |= ECONV_DEFAULT_NEWLINE_DECORATOR;
7099 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
7100 fptr->encs.ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
7101 if (fmode & FMODE_READABLE) {
7102 fptr->encs.ecflags |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;
7103 }
7104 #endif
7105 fptr->stdio_file = f;
7106
7107 return io;
7108 }
7109
7110 FILE *
7111 rb_io_stdio_file(rb_io_t *fptr)
7112 {
7113 if (!fptr->stdio_file) {
7114 int oflags = rb_io_fmode_oflags(fptr->mode);
7115 fptr->stdio_file = rb_fdopen(fptr->fd, rb_io_oflags_modestr(oflags));
7116 }
7117 return fptr->stdio_file;
7118 }
7119
7120 /*
7121 * call-seq:
7122 * IO.new(fd [, mode] [, opt]) -> io
7123 *
7124 * Returns a new IO object (a stream) for the given integer file descriptor
7125 * +fd+ and +mode+ string. +opt+ may be used to specify parts of +mode+ in a
7126 * more readable fashion. See also IO.sysopen and IO.for_fd.
7127 *
7128 * IO.new is called by various File and IO opening methods such as IO::open,
7129 * Kernel#open, and File::open.
7130 *
7131 * === Open Mode
7132 *
7133 * When +mode+ is an integer it must be combination of the modes defined in
7134 * File::Constants (+File::RDONLY+, +File::WRONLY | File::CREAT+). See the
7135 * open(2) man page for more information.
7136 *
7137 * When +mode+ is a string it must be in one of the following forms:
7138 *
7139 * fmode
7140 * fmode ":" ext_enc
7141 * fmode ":" ext_enc ":" int_enc
7142 * fmode ":" "BOM|UTF-*"
7143 *
7144 * +fmode+ is an IO open mode string, +ext_enc+ is the external encoding for
7145 * the IO and +int_enc+ is the internal encoding.
7146 *
7147 * ==== IO Open Mode
7148 *
7149 * Ruby allows the following open modes:
7150 *
7151 * "r" Read-only, starts at beginning of file (default mode).
7152 *
7153 * "r+" Read-write, starts at beginning of file.
7154 *
7155 * "w" Write-only, truncates existing file
7156 * to zero length or creates a new file for writing.
7157 *
7158 * "w+" Read-write, truncates existing file to zero length
7159 * or creates a new file for reading and writing.
7160 *
7161 * "a" Write-only, starts at end of file if file exists,
7162 * otherwise creates a new file for writing.
7163 *
7164 * "a+" Read-write, starts at end of file if file exists,
7165 * otherwise creates a new file for reading and
7166 * writing.
7167 *
7168 * The following modes must be used separately, and along with one or more of
7169 * the modes seen above.
7170 *
7171 * "b" Binary file mode
7172 * Suppresses EOL <-> CRLF conversion on Windows. And
7173 * sets external encoding to ASCII-8BIT unless explicitly
7174 * specified.
7175 *
7176 * "t" Text file mode
7177 *
7178 * When the open mode of original IO is read only, the mode cannot be
7179 * changed to be writable. Similarly, the open mode cannot be changed from
7180 * write only to readable.
7181 *
7182 * When such a change is attempted the error is raised in different locations
7183 * according to the platform.
7184 *
7185 * === IO Encoding
7186 *
7187 * When +ext_enc+ is specified, strings read will be tagged by the encoding
7188 * when reading, and strings output will be converted to the specified
7189 * encoding when writing.
7190 *
7191 * When +ext_enc+ and +int_enc+ are specified read strings will be converted
7192 * from +ext_enc+ to +int_enc+ upon input, and written strings will be
7193 * converted from +int_enc+ to +ext_enc+ upon output. See Encoding for
7194 * further details of transcoding on input and output.
7195 *
7196 * If "BOM|UTF-8", "BOM|UTF-16LE" or "BOM|UTF16-BE" are used, ruby checks for
7197 * a Unicode BOM in the input document to help determine the encoding. For
7198 * UTF-16 encodings the file open mode must be binary. When present, the BOM
7199 * is stripped and the external encoding from the BOM is used. When the BOM
7200 * is missing the given Unicode encoding is used as +ext_enc+. (The BOM-set
7201 * encoding option is case insensitive, so "bom|utf-8" is also valid.)
7202 *
7203 * === Options
7204 *
7205 * +opt+ can be used instead of +mode+ for improved readability. The
7206 * following keys are supported:
7207 *
7208 * :mode ::
7209 * Same as +mode+ parameter
7210 *
7211 * :\external_encoding ::
7212 * External encoding for the IO. "-" is a synonym for the default external
7213 * encoding.
7214 *
7215 * :\internal_encoding ::
7216 * Internal encoding for the IO. "-" is a synonym for the default internal
7217 * encoding.
7218 *
7219 * If the value is nil no conversion occurs.
7220 *
7221 * :encoding ::
7222 * Specifies external and internal encodings as "extern:intern".
7223 *
7224 * :textmode ::
7225 * If the value is truth value, same as "t" in argument +mode+.
7226 *
7227 * :binmode ::
7228 * If the value is truth value, same as "b" in argument +mode+.
7229 *
7230 * :autoclose ::
7231 * If the value is +false+, the +fd+ will be kept open after this IO
7232 * instance gets finalized.
7233 *
7234 * Also, +opt+ can have same keys in String#encode for controlling conversion
7235 * between the external encoding and the internal encoding.
7236 *
7237 * === Example 1
7238 *
7239 * fd = IO.sysopen("/dev/tty", "w")
7240 * a = IO.new(fd,"w")
7241 * $stderr.puts "Hello"
7242 * a.puts "World"
7243 *
7244 * Produces:
7245 *
7246 * Hello
7247 * World
7248 *
7249 * === Example 2
7250 *
7251 * require 'fcntl'
7252 *
7253 * fd = STDERR.fcntl(Fcntl::F_DUPFD)
7254 * io = IO.new(fd, mode: 'w:UTF-16LE', cr_newline: true)
7255 * io.puts "Hello, World!"
7256 *
7257 * fd = STDERR.fcntl(Fcntl::F_DUPFD)
7258 * io = IO.new(fd, mode: 'w', cr_newline: true,
7259 * external_encoding: Encoding::UTF_16LE)
7260 * io.puts "Hello, World!"
7261 *
7262 * Both of above print "Hello, World!" in UTF-16LE to standard error output
7263 * with converting EOL generated by <code>puts</code> to CR.
7264 */
7265
7266 static VALUE
7267 rb_io_initialize(int argc, VALUE *argv, VALUE io)
7268 {
7269 VALUE fnum, vmode;
7270 rb_io_t *fp;
7271 int fd, fmode, oflags = O_RDONLY;
7272 convconfig_t convconfig;
7273 VALUE opt;
7274 #if defined(HAVE_FCNTL) && defined(F_GETFL)
7275 int ofmode;
7276 #else
7277 struct stat st;
7278 #endif
7279
7280 rb_secure(4);
7281
7282 argc = rb_scan_args(argc, argv, "11:", &fnum, &vmode, &opt);
7283 rb_io_extract_modeenc(&vmode, 0, opt, &oflags, &fmode, &convconfig);
7284
7285 fd = NUM2INT(fnum);
7286 if (rb_reserved_fd_p(fd)) {
7287 rb_raise(rb_eArgError, "The given fd is not accessible because RubyVM reserves it");
7288 }
7289 #if defined(HAVE_FCNTL) && defined(F_GETFL)
7290 oflags = fcntl(fd, F_GETFL);
7291 if (oflags == -1) rb_sys_fail(0);
7292 #else
7293 if (fstat(fd, &st) == -1) rb_sys_fail(0);
7294 #endif
7295 rb_update_max_fd(fd);
7296 #if defined(HAVE_FCNTL) && defined(F_GETFL)
7297 ofmode = rb_io_oflags_fmode(oflags);
7298 if (NIL_P(vmode)) {
7299 fmode = ofmode;
7300 }
7301 else if ((~ofmode & fmode) & FMODE_READWRITE) {
7302 VALUE error = INT2FIX(EINVAL);
7303 rb_exc_raise(rb_class_new_instance(1, &error, rb_eSystemCallError));
7304 }
7305 #endif
7306 if (!NIL_P(opt) && rb_hash_aref(opt, sym_autoclose) == Qfalse) {
7307 fmode |= FMODE_PREP;
7308 }
7309 MakeOpenFile(io, fp);
7310 fp->fd = fd;
7311 fp->mode = fmode;
7312 fp->encs = convconfig;
7313 clear_codeconv(fp);
7314 io_check_tty(fp);
7315 if (fileno(stdin) == fd)
7316 fp->stdio_file = stdin;
7317 else if (fileno(stdout) == fd)
7318 fp->stdio_file = stdout;
7319 else if (fileno(stderr) == fd)
7320 fp->stdio_file = stderr;
7321
7322 if (fmode & FMODE_SETENC_BY_BOM) io_set_encoding_by_bom(io);
7323 return io;
7324 }
7325
7326 /*
7327 * call-seq:
7328 * File.new(filename, mode="r" [, opt]) -> file
7329 * File.new(filename [, mode [, perm]] [, opt]) -> file
7330 *
7331 * Opens the file named by +filename+ according to the given +mode+ and
7332 * returns a new File object.
7333 *
7334 * See IO.new for a description of +mode+ and +opt+.
7335 *
7336 * If a file is being created, permission bits may be given in +perm+. These
7337 * mode and permission bits are platform dependent; on Unix systems, see
7338 * open(2) and chmod(2) man pages for details.
7339 *
7340 * === Examples
7341 *
7342 * f = File.new("testfile", "r")
7343 * f = File.new("newfile", "w+")
7344 * f = File.new("newfile", File::CREAT|File::TRUNC|File::RDWR, 0644)
7345 */
7346
7347 static VALUE
7348 rb_file_initialize(int argc, VALUE *argv, VALUE io)
7349 {
7350 if (RFILE(io)->fptr) {
7351 rb_raise(rb_eRuntimeError, "reinitializing File");
7352 }
7353 if (0 < argc && argc < 3) {
7354 VALUE fd = rb_check_convert_type(argv[0], T_FIXNUM, "Fixnum", "to_int");
7355
7356 if (!NIL_P(fd)) {
7357 argv[0] = fd;
7358 return rb_io_initialize(argc, argv, io);
7359 }
7360 }
7361 rb_open_file(argc, argv, io);
7362
7363 return io;
7364 }
7365
7366 /* :nodoc: */
7367 static VALUE
7368 rb_io_s_new(int argc, VALUE *argv, VALUE klass)
7369 {
7370 if (rb_block_given_p()) {
7371 const char *cname = rb_class2name(klass);
7372
7373 rb_warn("%s::new() does not take block; use %s::open() instead",
7374 cname, cname);
7375 }
7376 return rb_class_new_instance(argc, argv, klass);
7377 }
7378
7379
7380 /*
7381 * call-seq:
7382 * IO.for_fd(fd, mode [, opt]) -> io
7383 *
7384 * Synonym for <code>IO.new</code>.
7385 *
7386 */
7387
7388 static VALUE
7389 rb_io_s_for_fd(int argc, VALUE *argv, VALUE klass)
7390 {
7391 VALUE io = rb_obj_alloc(klass);
7392 rb_io_initialize(argc, argv, io);
7393 return io;
7394 }
7395
7396 /*
7397 * call-seq:
7398 * ios.autoclose? -> true or false
7399 *
7400 * Returns +true+ if the underlying file descriptor of _ios_ will be
7401 * closed automatically at its finalization, otherwise +false+.
7402 */
7403
7404 static VALUE
7405 rb_io_autoclose_p(VALUE io)
7406 {
7407 rb_io_t *fptr;
7408 rb_secure(4);
7409 GetOpenFile(io, fptr);
7410 return (fptr->mode & FMODE_PREP) ? Qfalse : Qtrue;
7411 }
7412
7413 /*
7414 * call-seq:
7415 * io.autoclose = bool -> true or false
7416 *
7417 * Sets auto-close flag.
7418 *
7419 * f = open("/dev/null")
7420 * IO.for_fd(f.fileno)
7421 * # ...
7422 * f.gets # may cause IOError
7423 *
7424 * f = open("/dev/null")
7425 * IO.for_fd(f.fileno).autoclose = true
7426 * # ...
7427 * f.gets # won't cause IOError
7428 */
7429
7430 static VALUE
7431 rb_io_set_autoclose(VALUE io, VALUE autoclose)
7432 {
7433 rb_io_t *fptr;
7434 rb_secure(4);
7435 GetOpenFile(io, fptr);
7436 if (!RTEST(autoclose))
7437 fptr->mode |= FMODE_PREP;
7438 else
7439 fptr->mode &= ~FMODE_PREP;
7440 return io;
7441 }
7442
7443 static void
7444 argf_mark(void *ptr)
7445 {
7446 struct argf *p = ptr;
7447 rb_gc_mark(p->filename);
7448 rb_gc_mark(p->current_file);
7449 rb_gc_mark(p->argv);
7450 rb_gc_mark(p->encs.ecopts);
7451 }
7452
7453 static void
7454 argf_free(void *ptr)
7455 {
7456 struct argf *p = ptr;
7457 xfree(p->inplace);
7458 xfree(p);
7459 }
7460
7461 static size_t
7462 argf_memsize(const void *ptr)
7463 {
7464 const struct argf *p = ptr;
7465 size_t size = sizeof(*p);
7466 if (!ptr) return 0;
7467 if (p->inplace) size += strlen(p->inplace) + 1;
7468 return size;
7469 }
7470
7471 static const rb_data_type_t argf_type = {
7472 "ARGF",
7473 {argf_mark, argf_free, argf_memsize},
7474 };
7475
7476 static inline void
7477 argf_init(struct argf *p, VALUE v)
7478 {
7479 p->filename = Qnil;
7480 p->current_file = Qnil;
7481 p->lineno = 0;
7482 p->argv = v;
7483 }
7484
7485 static VALUE
7486 argf_alloc(VALUE klass)
7487 {
7488 struct argf *p;
7489 VALUE argf = TypedData_Make_Struct(klass, struct argf, &argf_type, p);
7490
7491 argf_init(p, Qnil);
7492 return argf;
7493 }
7494
7495 #undef rb_argv
7496
7497 /* :nodoc: */
7498 static VALUE
7499 argf_initialize(VALUE argf, VALUE argv)
7500 {
7501 memset(&ARGF, 0, sizeof(ARGF));
7502 argf_init(&ARGF, argv);
7503
7504 return argf;
7505 }
7506
7507 /* :nodoc: */
7508 static VALUE
7509 argf_initialize_copy(VALUE argf, VALUE orig)
7510 {
7511 if (!OBJ_INIT_COPY(argf, orig)) return argf;
7512 ARGF = argf_of(orig);
7513 ARGF.argv = rb_obj_dup(ARGF.argv);
7514 if (ARGF.inplace) {
7515 const char *inplace = ARGF.inplace;
7516 ARGF.inplace = 0;
7517 ARGF.inplace = ruby_strdup(inplace);
7518 }
7519 return argf;
7520 }
7521
7522 /*
7523 * call-seq:
7524 * ARGF.lineno = integer -> integer
7525 *
7526 * Sets the line number of +ARGF+ as a whole to the given +Integer+.
7527 *
7528 * +ARGF+ sets the line number automatically as you read data, so normally
7529 * you will not need to set it explicitly. To access the current line number
7530 * use +ARGF.lineno+.
7531 *
7532 * For example:
7533 *
7534 * ARGF.lineno #=> 0
7535 * ARGF.readline #=> "This is line 1\n"
7536 * ARGF.lineno #=> 1
7537 * ARGF.lineno = 0 #=> 0
7538 * ARGF.lineno #=> 0
7539 */
7540 static VALUE
7541 argf_set_lineno(VALUE argf, VALUE val)
7542 {
7543 ARGF.lineno = NUM2INT(val);
7544 ARGF.last_lineno = ARGF.lineno;
7545 return Qnil;
7546 }
7547
7548 /*
7549 * call-seq:
7550 * ARGF.lineno -> integer
7551 *
7552 * Returns the current line number of ARGF as a whole. This value
7553 * can be set manually with +ARGF.lineno=+.
7554 *
7555 * For example:
7556 *
7557 * ARGF.lineno #=> 0
7558 * ARGF.readline #=> "This is line 1\n"
7559 * ARGF.lineno #=> 1
7560 */
7561 static VALUE
7562 argf_lineno(VALUE argf)
7563 {
7564 return INT2FIX(ARGF.lineno);
7565 }
7566
7567 static VALUE
7568 argf_forward(int argc, VALUE *argv, VALUE argf)
7569 {
7570 return rb_funcall3(ARGF.current_file, rb_frame_this_func(), argc, argv);
7571 }
7572
7573 #define next_argv() argf_next_argv(argf)
7574 #define ARGF_GENERIC_INPUT_P() \
7575 (ARGF.current_file == rb_stdin && !RB_TYPE_P(ARGF.current_file, T_FILE))
7576 #define ARGF_FORWARD(argc, argv) do {\
7577 if (ARGF_GENERIC_INPUT_P())\
7578 return argf_forward((argc), (argv), argf);\
7579 } while (0)
7580 #define NEXT_ARGF_FORWARD(argc, argv) do {\
7581 if (!next_argv()) return Qnil;\
7582 ARGF_FORWARD((argc), (argv));\
7583 } while (0)
7584
7585 static void
7586 argf_close(VALUE file)
7587 {
7588 if (file == rb_stdin) return;
7589 if (RB_TYPE_P(file, T_FILE)) {
7590 rb_io_set_write_io(file, Qnil);
7591 }
7592 rb_funcall3(file, rb_intern("close"), 0, 0);
7593 }
7594
7595 static int
7596 argf_next_argv(VALUE argf)
7597 {
7598 char *fn;
7599 rb_io_t *fptr;
7600 int stdout_binmode = 0;
7601 int fmode;
7602
7603 if (RB_TYPE_P(rb_stdout, T_FILE)) {
7604 GetOpenFile(rb_stdout, fptr);
7605 if (fptr->mode & FMODE_BINMODE)
7606 stdout_binmode = 1;
7607 }
7608
7609 if (ARGF.init_p == 0) {
7610 if (!NIL_P(ARGF.argv) && RARRAY_LEN(ARGF.argv) > 0) {
7611 ARGF.next_p = 1;
7612 }
7613 else {
7614 ARGF.next_p = -1;
7615 }
7616 ARGF.init_p = 1;
7617 }
7618 else {
7619 if (NIL_P(ARGF.argv)) {
7620 ARGF.next_p = -1;
7621 }
7622 else if (ARGF.next_p == -1 && RARRAY_LEN(ARGF.argv) > 0) {
7623 ARGF.next_p = 1;
7624 }
7625 }
7626
7627 if (ARGF.next_p == 1) {
7628 retry:
7629 if (RARRAY_LEN(ARGF.argv) > 0) {
7630 ARGF.filename = rb_ary_shift(ARGF.argv);
7631 fn = StringValueCStr(ARGF.filename);
7632 if (strlen(fn) == 1 && fn[0] == '-') {
7633 ARGF.current_file = rb_stdin;
7634 if (ARGF.inplace) {
7635 rb_warn("Can't do inplace edit for stdio; skipping");
7636 goto retry;
7637 }
7638 }
7639 else {
7640 VALUE write_io = Qnil;
7641 int fr = rb_sysopen(ARGF.filename, O_RDONLY, 0);
7642
7643 if (ARGF.inplace) {
7644 struct stat st;
7645 #ifndef NO_SAFE_RENAME
7646 struct stat st2;
7647 #endif
7648 VALUE str;
7649 int fw;
7650
7651 if (RB_TYPE_P(rb_stdout, T_FILE) && rb_stdout != orig_stdout) {
7652 rb_io_close(rb_stdout);
7653 }
7654 fstat(fr, &st);
7655 if (*ARGF.inplace) {
7656 str = rb_str_new2(fn);
7657 rb_str_cat2(str, ARGF.inplace);
7658 #ifdef NO_SAFE_RENAME
7659 (void)close(fr);
7660 (void)unlink(RSTRING_PTR(str));
7661 if (rename(fn, RSTRING_PTR(str)) < 0) {
7662 rb_warn("Can't rename %s to %s: %s, skipping file",
7663 fn, RSTRING_PTR(str), strerror(errno));
7664 goto retry;
7665 }
7666 fr = rb_sysopen(str, O_RDONLY, 0);
7667 #else
7668 if (rename(fn, RSTRING_PTR(str)) < 0) {
7669 rb_warn("Can't rename %s to %s: %s, skipping file",
7670 fn, RSTRING_PTR(str), strerror(errno));
7671 close(fr);
7672 goto retry;
7673 }
7674 #endif
7675 }
7676 else {
7677 #ifdef NO_SAFE_RENAME
7678 rb_fatal("Can't do inplace edit without backup");
7679 #else
7680 if (unlink(fn) < 0) {
7681 rb_warn("Can't remove %s: %s, skipping file",
7682 fn, strerror(errno));
7683 close(fr);
7684 goto retry;
7685 }
7686 #endif
7687 }
7688 fw = rb_sysopen(ARGF.filename, O_WRONLY|O_CREAT|O_TRUNC, 0666);
7689 #ifndef NO_SAFE_RENAME
7690 fstat(fw, &st2);
7691 #ifdef HAVE_FCHMOD
7692 fchmod(fw, st.st_mode);
7693 #else
7694 chmod(fn, st.st_mode);
7695 #endif
7696 if (st.st_uid!=st2.st_uid || st.st_gid!=st2.st_gid) {
7697 int err;
7698 #ifdef HAVE_FCHOWN
7699 err = fchown(fw, st.st_uid, st.st_gid);
7700 #else
7701 err = chown(fn, st.st_uid, st.st_gid);
7702 #endif
7703 if (err && getuid() == 0 && st2.st_uid == 0) {
7704 const char *wkfn = RSTRING_PTR(ARGF.filename);
7705 rb_warn("Can't set owner/group of %s to same as %s: %s, skipping file",
7706 wkfn, fn, strerror(errno));
7707 (void)close(fr);
7708 (void)close(fw);
7709 (void)unlink(wkfn);
7710 goto retry;
7711 }
7712 }
7713 #endif
7714 write_io = prep_io(fw, FMODE_WRITABLE, rb_cFile, fn);
7715 rb_stdout = write_io;
7716 if (stdout_binmode) rb_io_binmode(rb_stdout);
7717 }
7718 fmode = FMODE_READABLE;
7719 if (!ARGF.binmode) {
7720 fmode |= DEFAULT_TEXTMODE;
7721 }
7722 ARGF.current_file = prep_io(fr, fmode, rb_cFile, fn);
7723 if (!NIL_P(write_io)) {
7724 rb_io_set_write_io(ARGF.current_file, write_io);
7725 }
7726 }
7727 if (ARGF.binmode) rb_io_ascii8bit_binmode(ARGF.current_file);
7728 GetOpenFile(ARGF.current_file, fptr);
7729 if (ARGF.encs.enc) {
7730 fptr->encs = ARGF.encs;
7731 clear_codeconv(fptr);
7732 }
7733 else {
7734 fptr->encs.ecflags &= ~ECONV_NEWLINE_DECORATOR_MASK;
7735 if (!ARGF.binmode) {
7736 fptr->encs.ecflags |= ECONV_DEFAULT_NEWLINE_DECORATOR;
7737 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
7738 fptr->encs.ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
7739 #endif
7740 }
7741 }
7742 ARGF.next_p = 0;
7743 }
7744 else {
7745 ARGF.next_p = 1;
7746 return FALSE;
7747 }
7748 }
7749 else if (ARGF.next_p == -1) {
7750 ARGF.current_file = rb_stdin;
7751 ARGF.filename = rb_str_new2("-");
7752 if (ARGF.inplace) {
7753 rb_warn("Can't do inplace edit for stdio");
7754 rb_stdout = orig_stdout;
7755 }
7756 }
7757 return TRUE;
7758 }
7759
7760 static VALUE
7761 argf_getline(int argc, VALUE *argv, VALUE argf)
7762 {
7763 VALUE line;
7764 long lineno = ARGF.lineno;
7765
7766 retry:
7767 if (!next_argv()) return Qnil;
7768 if (ARGF_GENERIC_INPUT_P()) {
7769 line = rb_funcall3(ARGF.current_file, idGets, argc, argv);
7770 }
7771 else {
7772 if (argc == 0 && rb_rs == rb_default_rs) {
7773 line = rb_io_gets(ARGF.current_file);
7774 }
7775 else {
7776 line = rb_io_getline(argc, argv, ARGF.current_file);
7777 }
7778 if (NIL_P(line) && ARGF.next_p != -1) {
7779 argf_close(ARGF.current_file);
7780 ARGF.next_p = 1;
7781 goto retry;
7782 }
7783 }
7784 if (!NIL_P(line)) {
7785 ARGF.lineno = ++lineno;
7786 ARGF.last_lineno = ARGF.lineno;
7787 }
7788 return line;
7789 }
7790
7791 static VALUE
7792 argf_lineno_getter(ID id, VALUE *var)
7793 {
7794 VALUE argf = *var;
7795 return INT2FIX(ARGF.last_lineno);
7796 }
7797
7798 static void
7799 argf_lineno_setter(VALUE val, ID id, VALUE *var)
7800 {
7801 VALUE argf = *var;
7802 int n = NUM2INT(val);
7803 ARGF.last_lineno = ARGF.lineno = n;
7804 }
7805
7806 static VALUE argf_gets(int, VALUE *, VALUE);
7807
7808 /*
7809 * call-seq:
7810 * gets(sep=$/) -> string or nil
7811 * gets(limit) -> string or nil
7812 * gets(sep,limit) -> string or nil
7813 *
7814 * Returns (and assigns to <code>$_</code>) the next line from the list
7815 * of files in +ARGV+ (or <code>$*</code>), or from standard input if
7816 * no files are present on the command line. Returns +nil+ at end of
7817 * file. The optional argument specifies the record separator. The
7818 * separator is included with the contents of each record. A separator
7819 * of +nil+ reads the entire contents, and a zero-length separator
7820 * reads the input one paragraph at a time, where paragraphs are
7821 * divided by two consecutive newlines. If the first argument is an
7822 * integer, or optional second argument is given, the returning string
7823 * would not be longer than the given value in bytes. If multiple
7824 * filenames are present in +ARGV+, +gets(nil)+ will read the contents
7825 * one file at a time.
7826 *
7827 * ARGV << "testfile"
7828 * print while gets
7829 *
7830 * <em>produces:</em>
7831 *
7832 * This is line one
7833 * This is line two
7834 * This is line three
7835 * And so on...
7836 *
7837 * The style of programming using <code>$_</code> as an implicit
7838 * parameter is gradually losing favor in the Ruby community.
7839 */
7840
7841 static VALUE
7842 rb_f_gets(int argc, VALUE *argv, VALUE recv)
7843 {
7844 if (recv == argf) {
7845 return argf_gets(argc, argv, argf);
7846 }
7847 return rb_funcall2(argf, idGets, argc, argv);
7848 }
7849
7850 /*
7851 * call-seq:
7852 * ARGF.gets(sep=$/) -> string
7853 * ARGF.gets(limit) -> string
7854 * ARGF.gets(sep, limit) -> string
7855 *
7856 * Returns the next line from the current file in +ARGF+.
7857 *
7858 * By default lines are assumed to be separated by +$/+; to use a different
7859 * character as a separator, supply it as a +String+ for the _sep_ argument.
7860 *
7861 * The optional _limit_ argument specifies how many characters of each line
7862 * to return. By default all characters are returned.
7863 *
7864 */
7865 static VALUE
7866 argf_gets(int argc, VALUE *argv, VALUE argf)
7867 {
7868 VALUE line;
7869
7870 line = argf_getline(argc, argv, argf);
7871 rb_lastline_set(line);
7872
7873 return line;
7874 }
7875
7876 VALUE
7877 rb_gets(void)
7878 {
7879 VALUE line;
7880
7881 if (rb_rs != rb_default_rs) {
7882 return rb_f_gets(0, 0, argf);
7883 }
7884
7885 retry:
7886 if (!next_argv()) return Qnil;
7887 line = rb_io_gets(ARGF.current_file);
7888 if (NIL_P(line) && ARGF.next_p != -1) {
7889 rb_io_close(ARGF.current_file);
7890 ARGF.next_p = 1;
7891 goto retry;
7892 }
7893 rb_lastline_set(line);
7894 if (!NIL_P(line)) {
7895 ARGF.lineno++;
7896 ARGF.last_lineno = ARGF.lineno;
7897 }
7898
7899 return line;
7900 }
7901
7902 static VALUE argf_readline(int, VALUE *, VALUE);
7903
7904 /*
7905 * call-seq:
7906 * readline(sep=$/) -> string
7907 * readline(limit) -> string
7908 * readline(sep, limit) -> string
7909 *
7910 * Equivalent to <code>Kernel::gets</code>, except
7911 * +readline+ raises +EOFError+ at end of file.
7912 */
7913
7914 static VALUE
7915 rb_f_readline(int argc, VALUE *argv, VALUE recv)
7916 {
7917 if (recv == argf) {
7918 return argf_readline(argc, argv, argf);
7919 }
7920 return rb_funcall2(argf, rb_intern("readline"), argc, argv);
7921 }
7922
7923
7924 /*
7925 * call-seq:
7926 * ARGF.readline(sep=$/) -> string
7927 * ARGF.readline(limit) -> string
7928 * ARGF.readline(sep, limit) -> string
7929 *
7930 * Returns the next line from the current file in +ARGF+.
7931 *
7932 * By default lines are assumed to be separated by +$/+; to use a different
7933 * character as a separator, supply it as a +String+ for the _sep_ argument.
7934 *
7935 * The optional _limit_ argument specifies how many characters of each line
7936 * to return. By default all characters are returned.
7937 *
7938 * An +EOFError+ is raised at the end of the file.
7939 */
7940 static VALUE
7941 argf_readline(int argc, VALUE *argv, VALUE argf)
7942 {
7943 VALUE line;
7944
7945 if (!next_argv()) rb_eof_error();
7946 ARGF_FORWARD(argc, argv);
7947 line = argf_gets(argc, argv, argf);
7948 if (NIL_P(line)) {
7949 rb_eof_error();
7950 }
7951
7952 return line;
7953 }
7954
7955 static VALUE argf_readlines(int, VALUE *, VALUE);
7956
7957 /*
7958 * call-seq:
7959 * readlines(sep=$/) -> array
7960 * readlines(limit) -> array
7961 * readlines(sep,limit) -> array
7962 *
7963 * Returns an array containing the lines returned by calling
7964 * <code>Kernel.gets(<i>sep</i>)</code> until the end of file.
7965 */
7966
7967 static VALUE
7968 rb_f_readlines(int argc, VALUE *argv, VALUE recv)
7969 {
7970 if (recv == argf) {
7971 return argf_readlines(argc, argv, argf);
7972 }
7973 return rb_funcall2(argf, rb_intern("readlines"), argc, argv);
7974 }
7975
7976 /*
7977 * call-seq:
7978 * ARGF.readlines(sep=$/) -> array
7979 * ARGF.readlines(limit) -> array
7980 * ARGF.readlines(sep, limit) -> array
7981 *
7982 * ARGF.to_a(sep=$/) -> array
7983 * ARGF.to_a(limit) -> array
7984 * ARGF.to_a(sep, limit) -> array
7985 *
7986 * Reads +ARGF+'s current file in its entirety, returning an +Array+ of its
7987 * lines, one line per element. Lines are assumed to be separated by _sep_.
7988 *
7989 * lines = ARGF.readlines
7990 * lines[0] #=> "This is line one\n"
7991 */
7992 static VALUE
7993 argf_readlines(int argc, VALUE *argv, VALUE argf)
7994 {
7995 long lineno = ARGF.lineno;
7996 VALUE lines, ary;
7997
7998 ary = rb_ary_new();
7999 while (next_argv()) {
8000 if (ARGF_GENERIC_INPUT_P()) {
8001 lines = rb_funcall3(ARGF.current_file, rb_intern("readlines"), argc, argv);
8002 }
8003 else {
8004 lines = rb_io_readlines(argc, argv, ARGF.current_file);
8005 argf_close(ARGF.current_file);
8006 }
8007 ARGF.next_p = 1;
8008 rb_ary_concat(ary, lines);
8009 ARGF.lineno = lineno + RARRAY_LEN(ary);
8010 ARGF.last_lineno = ARGF.lineno;
8011 }
8012 ARGF.init_p = 0;
8013 return ary;
8014 }
8015
8016 /*
8017 * call-seq:
8018 * `cmd` -> string
8019 *
8020 * Returns the standard output of running _cmd_ in a subshell.
8021 * The built-in syntax <code>%x{...}</code> uses
8022 * this method. Sets <code>$?</code> to the process status.
8023 *
8024 * `date` #=> "Wed Apr 9 08:56:30 CDT 2003\n"
8025 * `ls testdir`.split[1] #=> "main.rb"
8026 * `echo oops && exit 99` #=> "oops\n"
8027 * $?.exitstatus #=> 99
8028 */
8029
8030 static VALUE
8031 rb_f_backquote(VALUE obj, VALUE str)
8032 {
8033 volatile VALUE port;
8034 VALUE result;
8035 rb_io_t *fptr;
8036
8037 SafeStringValue(str);
8038 rb_last_status_clear();
8039 port = pipe_open_s(str, "r", FMODE_READABLE|DEFAULT_TEXTMODE, NULL);
8040 if (NIL_P(port)) return rb_str_new(0,0);
8041
8042 GetOpenFile(port, fptr);
8043 result = read_all(fptr, remain_size(fptr), Qnil);
8044 rb_io_close(port);
8045
8046 return result;
8047 }
8048
8049 #ifdef HAVE_SYS_SELECT_H
8050 #include <sys/select.h>
8051 #endif
8052
8053 static VALUE
8054 select_internal(VALUE read, VALUE write, VALUE except, struct timeval *tp, rb_fdset_t *fds)
8055 {
8056 VALUE res, list;
8057 rb_fdset_t *rp, *wp, *ep;
8058 rb_io_t *fptr;
8059 long i;
8060 int max = 0, n;
8061 int pending = 0;
8062 struct timeval timerec;
8063
8064 if (!NIL_P(read)) {
8065 Check_Type(read, T_ARRAY);
8066 for (i=0; i<RARRAY_LEN(read); i++) {
8067 GetOpenFile(rb_io_get_io(RARRAY_PTR(read)[i]), fptr);
8068 rb_fd_set(fptr->fd, &fds[0]);
8069 if (READ_DATA_PENDING(fptr) || READ_CHAR_PENDING(fptr)) { /* check for buffered data */
8070 pending++;
8071 rb_fd_set(fptr->fd, &fds[3]);
8072 }
8073 if (max < fptr->fd) max = fptr->fd;
8074 }
8075 if (pending) { /* no blocking if there's buffered data */
8076 timerec.tv_sec = timerec.tv_usec = 0;
8077 tp = &timerec;
8078 }
8079 rp = &fds[0];
8080 }
8081 else
8082 rp = 0;
8083
8084 if (!NIL_P(write)) {
8085 Check_Type(write, T_ARRAY);
8086 for (i=0; i<RARRAY_LEN(write); i++) {
8087 VALUE write_io = GetWriteIO(rb_io_get_io(RARRAY_PTR(write)[i]));
8088 GetOpenFile(write_io, fptr);
8089 rb_fd_set(fptr->fd, &fds[1]);
8090 if (max < fptr->fd) max = fptr->fd;
8091 }
8092 wp = &fds[1];
8093 }
8094 else
8095 wp = 0;
8096
8097 if (!NIL_P(except)) {
8098 Check_Type(except, T_ARRAY);
8099 for (i=0; i<RARRAY_LEN(except); i++) {
8100 VALUE io = rb_io_get_io(RARRAY_PTR(except)[i]);
8101 VALUE write_io = GetWriteIO(io);
8102 GetOpenFile(io, fptr);
8103 rb_fd_set(fptr->fd, &fds[2]);
8104 if (max < fptr->fd) max = fptr->fd;
8105 if (io != write_io) {
8106 GetOpenFile(write_io, fptr);
8107 rb_fd_set(fptr->fd, &fds[2]);
8108 if (max < fptr->fd) max = fptr->fd;
8109 }
8110 }
8111 ep = &fds[2];
8112 }
8113 else {
8114 ep = 0;
8115 }
8116
8117 max++;
8118
8119 n = rb_thread_fd_select(max, rp, wp, ep, tp);
8120 if (n < 0) {
8121 rb_sys_fail(0);
8122 }
8123 if (!pending && n == 0) return Qnil; /* returns nil on timeout */
8124
8125 res = rb_ary_new2(3);
8126 rb_ary_push(res, rp?rb_ary_new():rb_ary_new2(0));
8127 rb_ary_push(res, wp?rb_ary_new():rb_ary_new2(0));
8128 rb_ary_push(res, ep?rb_ary_new():rb_ary_new2(0));
8129
8130 if (rp) {
8131 list = RARRAY_PTR(res)[0];
8132 for (i=0; i< RARRAY_LEN(read); i++) {
8133 VALUE obj = rb_ary_entry(read, i);
8134 VALUE io = rb_io_get_io(obj);
8135 GetOpenFile(io, fptr);
8136 if (rb_fd_isset(fptr->fd, &fds[0]) ||
8137 rb_fd_isset(fptr->fd, &fds[3])) {
8138 rb_ary_push(list, obj);
8139 }
8140 }
8141 }
8142
8143 if (wp) {
8144 list = RARRAY_PTR(res)[1];
8145 for (i=0; i< RARRAY_LEN(write); i++) {
8146 VALUE obj = rb_ary_entry(write, i);
8147 VALUE io = rb_io_get_io(obj);
8148 VALUE write_io = GetWriteIO(io);
8149 GetOpenFile(write_io, fptr);
8150 if (rb_fd_isset(fptr->fd, &fds[1])) {
8151 rb_ary_push(list, obj);
8152 }
8153 }
8154 }
8155
8156 if (ep) {
8157 list = RARRAY_PTR(res)[2];
8158 for (i=0; i< RARRAY_LEN(except); i++) {
8159 VALUE obj = rb_ary_entry(except, i);
8160 VALUE io = rb_io_get_io(obj);
8161 VALUE write_io = GetWriteIO(io);
8162 GetOpenFile(io, fptr);
8163 if (rb_fd_isset(fptr->fd, &fds[2])) {
8164 rb_ary_push(list, obj);
8165 }
8166 else if (io != write_io) {
8167 GetOpenFile(write_io, fptr);
8168 if (rb_fd_isset(fptr->fd, &fds[2])) {
8169 rb_ary_push(list, obj);
8170 }
8171 }
8172 }
8173 }
8174
8175 return res; /* returns an empty array on interrupt */
8176 }
8177
8178 struct select_args {
8179 VALUE read, write, except;
8180 struct timeval *timeout;
8181 rb_fdset_t fdsets[4];
8182 };
8183
8184 static VALUE
8185 select_call(VALUE arg)
8186 {
8187 struct select_args *p = (struct select_args *)arg;
8188
8189 return select_internal(p->read, p->write, p->except, p->timeout, p->fdsets);
8190 }
8191
8192 static VALUE
8193 select_end(VALUE arg)
8194 {
8195 struct select_args *p = (struct select_args *)arg;
8196 int i;
8197
8198 for (i = 0; i < numberof(p->fdsets); ++i)
8199 rb_fd_term(&p->fdsets[i]);
8200 return Qnil;
8201 }
8202
8203 static VALUE sym_normal, sym_sequential, sym_random,
8204 sym_willneed, sym_dontneed, sym_noreuse;
8205
8206 #ifdef HAVE_POSIX_FADVISE
8207 struct io_advise_struct {
8208 int fd;
8209 off_t offset;
8210 off_t len;
8211 int advice;
8212 };
8213
8214 static VALUE
8215 io_advise_internal(void *arg)
8216 {
8217 struct io_advise_struct *ptr = arg;
8218 return posix_fadvise(ptr->fd, ptr->offset, ptr->len, ptr->advice);
8219 }
8220
8221 static VALUE
8222 io_advise_sym_to_const(VALUE sym)
8223 {
8224 #ifdef POSIX_FADV_NORMAL
8225 if (sym == sym_normal)
8226 return INT2NUM(POSIX_FADV_NORMAL);
8227 #endif
8228
8229 #ifdef POSIX_FADV_RANDOM
8230 if (sym == sym_random)
8231 return INT2NUM(POSIX_FADV_RANDOM);
8232 #endif
8233
8234 #ifdef POSIX_FADV_SEQUENTIAL
8235 if (sym == sym_sequential)
8236 return INT2NUM(POSIX_FADV_SEQUENTIAL);
8237 #endif
8238
8239 #ifdef POSIX_FADV_WILLNEED
8240 if (sym == sym_willneed)
8241 return INT2NUM(POSIX_FADV_WILLNEED);
8242 #endif
8243
8244 #ifdef POSIX_FADV_DONTNEED
8245 if (sym == sym_dontneed)
8246 return INT2NUM(POSIX_FADV_DONTNEED);
8247 #endif
8248
8249 #ifdef POSIX_FADV_NOREUSE
8250 if (sym == sym_noreuse)
8251 return INT2NUM(POSIX_FADV_NOREUSE);
8252 #endif
8253
8254 return Qnil;
8255 }
8256
8257 static VALUE
8258 do_io_advise(rb_io_t *fptr, VALUE advice, off_t offset, off_t len)
8259 {
8260 int rv;
8261 struct io_advise_struct ias;
8262 VALUE num_adv;
8263
8264 num_adv = io_advise_sym_to_const(advice);
8265
8266 /*
8267 * The platform doesn't support this hint. We don't raise exception, instead
8268 * silently ignore it. Because IO::advise is only hint.
8269 */
8270 if (NIL_P(num_adv))
8271 return Qnil;
8272
8273 ias.fd = fptr->fd;
8274 ias.advice = NUM2INT(num_adv);
8275 ias.offset = offset;
8276 ias.len = len;
8277
8278 rv = (int)rb_thread_io_blocking_region(io_advise_internal, &ias, fptr->fd);
8279 if (rv) {
8280 /* posix_fadvise(2) doesn't set errno. On success it returns 0; otherwise
8281 it returns the error code. */
8282 rb_syserr_fail_str(rv, fptr->pathv);
8283 }
8284
8285 return Qnil;
8286 }
8287
8288 #endif /* HAVE_POSIX_FADVISE */
8289
8290 static void
8291 advice_arg_check(VALUE advice)
8292 {
8293 if (!SYMBOL_P(advice))
8294 rb_raise(rb_eTypeError, "advice must be a Symbol");
8295
8296 if (advice != sym_normal &&
8297 advice != sym_sequential &&
8298 advice != sym_random &&
8299 advice != sym_willneed &&
8300 advice != sym_dontneed &&
8301 advice != sym_noreuse) {
8302 VALUE symname = rb_inspect(advice);
8303 rb_raise(rb_eNotImpError, "Unsupported advice: %s",
8304 StringValuePtr(symname));
8305 }
8306 }
8307
8308 /*
8309 * call-seq:
8310 * ios.advise(advice, offset=0, len=0) -> nil
8311 *
8312 * Announce an intention to access data from the current file in a
8313 * specific pattern. On platforms that do not support the
8314 * <em>posix_fadvise(2)</em> system call, this method is a no-op.
8315 *
8316 * _advice_ is one of the following symbols:
8317 *
8318 * * :normal - No advice to give; the default assumption for an open file.
8319 * * :sequential - The data will be accessed sequentially:
8320 * with lower offsets read before higher ones.
8321 * * :random - The data will be accessed in random order.
8322 * * :willneed - The data will be accessed in the near future.
8323 * * :dontneed - The data will not be accessed in the near future.
8324 * * :noreuse - The data will only be accessed once.
8325 *
8326 * The semantics of a piece of advice are platform-dependent. See
8327 * <em>man 2 posix_fadvise</em> for details.
8328 *
8329 * "data" means the region of the current file that begins at
8330 * _offset_ and extends for _len_ bytes. If _len_ is 0, the region
8331 * ends at the last byte of the file. By default, both _offset_ and
8332 * _len_ are 0, meaning that the advice applies to the entire file.
8333 *
8334 * If an error occurs, one of the following exceptions will be raised:
8335 *
8336 * * <code>IOError</code> - The <code>IO</code> stream is closed.
8337 * * <code>Errno::EBADF</code> - The file descriptor of the current file is
8338 invalid.
8339 * * <code>Errno::EINVAL</code> - An invalid value for _advice_ was given.
8340 * * <code>Errno::ESPIPE</code> - The file descriptor of the current
8341 * * file refers to a FIFO or pipe. (Linux raises <code>Errno::EINVAL</code>
8342 * * in this case).
8343 * * <code>TypeError</code> - Either _advice_ was not a Symbol, or one of the
8344 other arguments was not an <code>Integer</code>.
8345 * * <code>RangeError</code> - One of the arguments given was too big/small.
8346 *
8347 * This list is not exhaustive; other Errno:: exceptions are also possible.
8348 */
8349 static VALUE
8350 rb_io_advise(int argc, VALUE *argv, VALUE io)
8351 {
8352 VALUE advice, offset, len;
8353 off_t off, l;
8354 rb_io_t *fptr;
8355
8356 rb_scan_args(argc, argv, "12", &advice, &offset, &len);
8357 advice_arg_check(advice);
8358
8359 io = GetWriteIO(io);
8360 GetOpenFile(io, fptr);
8361
8362 off = NIL_P(offset) ? 0 : NUM2OFFT(offset);
8363 l = NIL_P(len) ? 0 : NUM2OFFT(len);
8364
8365 #ifdef HAVE_POSIX_FADVISE
8366 return do_io_advise(fptr, advice, off, l);
8367 #else
8368 ((void)off, (void)l); /* Ignore all hint */
8369 return Qnil;
8370 #endif
8371 }
8372
8373 /*
8374 * call-seq:
8375 * IO.select(read_array
8376 * [, write_array
8377 * [, error_array
8378 * [, timeout]]]) -> array or nil
8379 *
8380 * Calls select(2) system call.
8381 * It monitors given arrays of <code>IO</code> objects, waits one or more
8382 * of <code>IO</code> objects ready for reading, are ready for writing,
8383 * and have pending exceptions respectably, and returns an array that
8384 * contains arrays of those IO objects. It will return <code>nil</code>
8385 * if optional <i>timeout</i> value is given and no <code>IO</code> object
8386 * is ready in <i>timeout</i> seconds.
8387 *
8388 * === Parameters
8389 * read_array:: an array of <code>IO</code> objects that wait until ready for read
8390 * write_array:: an array of <code>IO</code> objects that wait until ready for write
8391 * error_array:: an array of <code>IO</code> objects that wait for exceptions
8392 * timeout:: a numeric value in second
8393 *
8394 * === Example
8395 *
8396 * rp, wp = IO.pipe
8397 * mesg = "ping "
8398 * 100.times {
8399 * rs, ws, = IO.select([rp], [wp])
8400 * if r = rs[0]
8401 * ret = r.read(5)
8402 * print ret
8403 * case ret
8404 * when /ping/
8405 * mesg = "pong\n"
8406 * when /pong/
8407 * mesg = "ping "
8408 * end
8409 * end
8410 * if w = ws[0]
8411 * w.write(mesg)
8412 * end
8413 * }
8414 *
8415 * <em>produces:</em>
8416 *
8417 * ping pong
8418 * ping pong
8419 * ping pong
8420 * (snipped)
8421 * ping
8422 */
8423
8424 static VALUE
8425 rb_f_select(int argc, VALUE *argv, VALUE obj)
8426 {
8427 VALUE timeout;
8428 struct select_args args;
8429 struct timeval timerec;
8430 int i;
8431
8432 rb_scan_args(argc, argv, "13", &args.read, &args.write, &args.except, &timeout);
8433 if (NIL_P(timeout)) {
8434 args.timeout = 0;
8435 }
8436 else {
8437 timerec = rb_time_interval(timeout);
8438 args.timeout = &timerec;
8439 }
8440
8441 for (i = 0; i < numberof(args.fdsets); ++i)
8442 rb_fd_init(&args.fdsets[i]);
8443
8444 return rb_ensure(select_call, (VALUE)&args, select_end, (VALUE)&args);
8445 }
8446
8447 #if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
8448 typedef unsigned long ioctl_req_t;
8449 # define NUM2IOCTLREQ(num) NUM2ULONG(num)
8450 #else
8451 typedef int ioctl_req_t;
8452 # define NUM2IOCTLREQ(num) NUM2INT(num)
8453 #endif
8454
8455 struct ioctl_arg {
8456 int fd;
8457 ioctl_req_t cmd;
8458 long narg;
8459 };
8460
8461 static VALUE
8462 nogvl_ioctl(void *ptr)
8463 {
8464 struct ioctl_arg *arg = ptr;
8465
8466 return (VALUE)ioctl(arg->fd, arg->cmd, arg->narg);
8467 }
8468
8469 static int
8470 do_ioctl(int fd, ioctl_req_t cmd, long narg)
8471 {
8472 int retval;
8473 struct ioctl_arg arg;
8474
8475 arg.fd = fd;
8476 arg.cmd = cmd;
8477 arg.narg = narg;
8478
8479 retval = (int)rb_thread_io_blocking_region(nogvl_ioctl, &arg, fd);
8480
8481 return retval;
8482 }
8483
8484 #define DEFULT_IOCTL_NARG_LEN (256)
8485
8486 #ifdef __linux__
8487 static long
8488 linux_iocparm_len(ioctl_req_t cmd)
8489 {
8490 long len;
8491
8492 if ((cmd & 0xFFFF0000) == 0) {
8493 /* legacy and unstructured ioctl number. */
8494 return DEFULT_IOCTL_NARG_LEN;
8495 }
8496
8497 len = _IOC_SIZE(cmd);
8498
8499 /* paranoia check for silly drivers which don't keep ioctl convention */
8500 if (len < DEFULT_IOCTL_NARG_LEN)
8501 len = DEFULT_IOCTL_NARG_LEN;
8502
8503 return len;
8504 }
8505 #endif
8506
8507 static long
8508 ioctl_narg_len(ioctl_req_t cmd)
8509 {
8510 long len;
8511
8512 #ifdef IOCPARM_MASK
8513 #ifndef IOCPARM_LEN
8514 #define IOCPARM_LEN(x) (((x) >> 16) & IOCPARM_MASK)
8515 #endif
8516 #endif
8517 #ifdef IOCPARM_LEN
8518 len = IOCPARM_LEN(cmd); /* on BSDish systems we're safe */
8519 #elif defined(__linux__)
8520 len = linux_iocparm_len(cmd);
8521 #else
8522 /* otherwise guess at what's safe */
8523 len = DEFULT_IOCTL_NARG_LEN;
8524 #endif
8525
8526 return len;
8527 }
8528
8529 #ifdef HAVE_FCNTL
8530 #ifdef __linux__
8531 typedef long fcntl_arg_t;
8532 #else
8533 /* posix */
8534 typedef int fcntl_arg_t;
8535 #endif
8536
8537 static long
8538 fcntl_narg_len(int cmd)
8539 {
8540 long len;
8541
8542 switch (cmd) {
8543 #ifdef F_DUPFD
8544 case F_DUPFD:
8545 len = sizeof(fcntl_arg_t);
8546 break;
8547 #endif
8548 #ifdef F_DUP2FD /* bsd specific */
8549 case F_DUP2FD:
8550 len = sizeof(int);
8551 break;
8552 #endif
8553 #ifdef F_DUPFD_CLOEXEC /* linux specific */
8554 case F_DUPFD_CLOEXEC:
8555 len = sizeof(fcntl_arg_t);
8556 break;
8557 #endif
8558 #ifdef F_GETFD
8559 case F_GETFD:
8560 len = 1;
8561 break;
8562 #endif
8563 #ifdef F_SETFD
8564 case F_SETFD:
8565 len = sizeof(fcntl_arg_t);
8566 break;
8567 #endif
8568 #ifdef F_GETFL
8569 case F_GETFL:
8570 len = 1;
8571 break;
8572 #endif
8573 #ifdef F_SETFL
8574 case F_SETFL:
8575 len = sizeof(fcntl_arg_t);
8576 break;
8577 #endif
8578 #ifdef F_GETOWN
8579 case F_GETOWN:
8580 len = 1;
8581 break;
8582 #endif
8583 #ifdef F_SETOWN
8584 case F_SETOWN:
8585 len = sizeof(fcntl_arg_t);
8586 break;
8587 #endif
8588 #ifdef F_GETOWN_EX /* linux specific */
8589 case F_GETOWN_EX:
8590 len = sizeof(struct f_owner_ex);
8591 break;
8592 #endif
8593 #ifdef F_SETOWN_EX /* linux specific */
8594 case F_SETOWN_EX:
8595 len = sizeof(struct f_owner_ex);
8596 break;
8597 #endif
8598 #ifdef F_GETLK
8599 case F_GETLK:
8600 len = sizeof(struct flock);
8601 break;
8602 #endif
8603 #ifdef F_SETLK
8604 case F_SETLK:
8605 len = sizeof(struct flock);
8606 break;
8607 #endif
8608 #ifdef F_SETLKW
8609 case F_SETLKW:
8610 len = sizeof(struct flock);
8611 break;
8612 #endif
8613 #ifdef F_READAHEAD /* bsd specific */
8614 case F_READAHEAD:
8615 len = sizeof(int);
8616 break;
8617 #endif
8618 #ifdef F_RDAHEAD /* Darwin specific */
8619 case F_RDAHEAD:
8620 len = sizeof(int);
8621 break;
8622 #endif
8623 #ifdef F_GETSIG /* linux specific */
8624 case F_GETSIG:
8625 len = 1;
8626 break;
8627 #endif
8628 #ifdef F_SETSIG /* linux specific */
8629 case F_SETSIG:
8630 len = sizeof(fcntl_arg_t);
8631 break;
8632 #endif
8633 #ifdef F_GETLEASE /* linux specific */
8634 case F_GETLEASE:
8635 len = 1;
8636 break;
8637 #endif
8638 #ifdef F_SETLEASE /* linux specific */
8639 case F_SETLEASE:
8640 len = sizeof(fcntl_arg_t);
8641 break;
8642 #endif
8643 #ifdef F_NOTIFY /* linux specific */
8644 case F_NOTIFY:
8645 len = sizeof(fcntl_arg_t);
8646 break;
8647 #endif
8648
8649 default:
8650 len = 256;
8651 break;
8652 }
8653
8654 return len;
8655 }
8656 #else /* HAVE_FCNTL */
8657 static long
8658 fcntl_narg_len(int cmd)
8659 {
8660 return 0;
8661 }
8662 #endif /* HAVE_FCNTL */
8663
8664 static long
8665 setup_narg(ioctl_req_t cmd, VALUE *argp, int io_p)
8666 {
8667 long narg = 0;
8668 VALUE arg = *argp;
8669
8670 if (NIL_P(arg) || arg == Qfalse) {
8671 narg = 0;
8672 }
8673 else if (FIXNUM_P(arg)) {
8674 narg = FIX2LONG(arg);
8675 }
8676 else if (arg == Qtrue) {
8677 narg = 1;
8678 }
8679 else {
8680 VALUE tmp = rb_check_string_type(arg);
8681
8682 if (NIL_P(tmp)) {
8683 narg = NUM2LONG(arg);
8684 }
8685 else {
8686 long len;
8687
8688 *argp = arg = tmp;
8689 if (io_p)
8690 len = ioctl_narg_len(cmd);
8691 else
8692 len = fcntl_narg_len((int)cmd);
8693 rb_str_modify(arg);
8694
8695 /* expand for data + sentinel. */
8696 if (RSTRING_LEN(arg) < len+1) {
8697 rb_str_resize(arg, len+1);
8698 }
8699 /* a little sanity check here */
8700 RSTRING_PTR(arg)[RSTRING_LEN(arg) - 1] = 17;
8701 narg = (long)(SIGNED_VALUE)RSTRING_PTR(arg);
8702 }
8703 }
8704
8705 return narg;
8706 }
8707
8708 static VALUE
8709 rb_ioctl(VALUE io, VALUE req, VALUE arg)
8710 {
8711 ioctl_req_t cmd = NUM2IOCTLREQ(req);
8712 rb_io_t *fptr;
8713 long narg;
8714 int retval;
8715
8716 rb_secure(2);
8717
8718 narg = setup_narg(cmd, &arg, 1);
8719 GetOpenFile(io, fptr);
8720 retval = do_ioctl(fptr->fd, cmd, narg);
8721 if (retval < 0) rb_sys_fail_path(fptr->pathv);
8722 if (RB_TYPE_P(arg, T_STRING)) {
8723 if (RSTRING_PTR(arg)[RSTRING_LEN(arg)-1] != 17)
8724 rb_raise(rb_eArgError, "return value overflowed string");
8725 RSTRING_PTR(arg)[RSTRING_LEN(arg)-1] = '\0';
8726 }
8727
8728 return INT2NUM(retval);
8729 }
8730
8731 /*
8732 * call-seq:
8733 * ios.ioctl(integer_cmd, arg) -> integer
8734 *
8735 * Provides a mechanism for issuing low-level commands to control or
8736 * query I/O devices. Arguments and results are platform dependent. If
8737 * <i>arg</i> is a number, its value is passed directly. If it is a
8738 * string, it is interpreted as a binary sequence of bytes. On Unix
8739 * platforms, see <code>ioctl(2)</code> for details. Not implemented on
8740 * all platforms.
8741 */
8742
8743 static VALUE
8744 rb_io_ioctl(int argc, VALUE *argv, VALUE io)
8745 {
8746 VALUE req, arg;
8747
8748 rb_scan_args(argc, argv, "11", &req, &arg);
8749 return rb_ioctl(io, req, arg);
8750 }
8751
8752 #ifdef HAVE_FCNTL
8753 struct fcntl_arg {
8754 int fd;
8755 int cmd;
8756 long narg;
8757 };
8758
8759 static VALUE
8760 nogvl_fcntl(void *ptr)
8761 {
8762 struct fcntl_arg *arg = ptr;
8763
8764 #if defined(F_DUPFD)
8765 if (arg->cmd == F_DUPFD)
8766 return (VALUE)rb_cloexec_fcntl_dupfd(arg->fd, (int)arg->narg);
8767 #endif
8768 return (VALUE)fcntl(arg->fd, arg->cmd, arg->narg);
8769 }
8770
8771 static int
8772 do_fcntl(int fd, int cmd, long narg)
8773 {
8774 int retval;
8775 struct fcntl_arg arg;
8776
8777 arg.fd = fd;
8778 arg.cmd = cmd;
8779 arg.narg = narg;
8780
8781 retval = (int)rb_thread_io_blocking_region(nogvl_fcntl, &arg, fd);
8782 #if defined(F_DUPFD)
8783 if (retval != -1 && cmd == F_DUPFD) {
8784 rb_update_max_fd(retval);
8785 }
8786 #endif
8787
8788 return retval;
8789 }
8790
8791 static VALUE
8792 rb_fcntl(VALUE io, VALUE req, VALUE arg)
8793 {
8794 int cmd = NUM2INT(req);
8795 rb_io_t *fptr;
8796 long narg;
8797 int retval;
8798
8799 rb_secure(2);
8800
8801 narg = setup_narg(cmd, &arg, 0);
8802 GetOpenFile(io, fptr);
8803 retval = do_fcntl(fptr->fd, cmd, narg);
8804 if (retval < 0) rb_sys_fail_path(fptr->pathv);
8805 if (RB_TYPE_P(arg, T_STRING)) {
8806 if (RSTRING_PTR(arg)[RSTRING_LEN(arg)-1] != 17)
8807 rb_raise(rb_eArgError, "return value overflowed string");
8808 RSTRING_PTR(arg)[RSTRING_LEN(arg)-1] = '\0';
8809 }
8810
8811 if (cmd == F_SETFL) {
8812 if (narg & O_NONBLOCK) {
8813 fptr->mode |= FMODE_WSPLIT_INITIALIZED;
8814 fptr->mode &= ~FMODE_WSPLIT;
8815 }
8816 else {
8817 fptr->mode &= ~(FMODE_WSPLIT_INITIALIZED|FMODE_WSPLIT);
8818 }
8819 }
8820
8821 return INT2NUM(retval);
8822 }
8823
8824 /*
8825 * call-seq:
8826 * ios.fcntl(integer_cmd, arg) -> integer
8827 *
8828 * Provides a mechanism for issuing low-level commands to control or
8829 * query file-oriented I/O streams. Arguments and results are platform
8830 * dependent. If <i>arg</i> is a number, its value is passed
8831 * directly. If it is a string, it is interpreted as a binary sequence
8832 * of bytes (<code>Array#pack</code> might be a useful way to build this
8833 * string). On Unix platforms, see <code>fcntl(2)</code> for details.
8834 * Not implemented on all platforms.
8835 */
8836
8837 static VALUE
8838 rb_io_fcntl(int argc, VALUE *argv, VALUE io)
8839 {
8840 VALUE req, arg;
8841
8842 rb_scan_args(argc, argv, "11", &req, &arg);
8843 return rb_fcntl(io, req, arg);
8844 }
8845 #else
8846 #define rb_io_fcntl rb_f_notimplement
8847 #endif
8848
8849 #if defined(HAVE_SYSCALL) || defined(HAVE___SYSCALL)
8850 /*
8851 * call-seq:
8852 * syscall(num [, args...]) -> integer
8853 *
8854 * Calls the operating system function identified by _num_ and
8855 * returns the result of the function or raises SystemCallError if
8856 * it failed.
8857 *
8858 * Arguments for the function can follow _num_. They must be either
8859 * +String+ objects or +Integer+ objects. A +String+ object is passed
8860 * as a pointer to the byte sequence. An +Integer+ object is passed
8861 * as an integer whose bit size is same as a pointer.
8862 * Up to nine parameters may be passed (14 on the Atari-ST).
8863 *
8864 * The function identified by _num_ is system
8865 * dependent. On some Unix systems, the numbers may be obtained from a
8866 * header file called <code>syscall.h</code>.
8867 *
8868 * syscall 4, 1, "hello\n", 6 # '4' is write(2) on our box
8869 *
8870 * <em>produces:</em>
8871 *
8872 * hello
8873 *
8874 *
8875 * Calling +syscall+ on a platform which does not have any way to
8876 * an arbitrary system function just fails with NotImplementedError.
8877 *
8878 * Note::
8879 * +syscall+ is essentially unsafe and unportable. Feel free to shoot your foot.
8880 * DL (Fiddle) library is preferred for safer and a bit more portable programming.
8881 */
8882
8883 static VALUE
8884 rb_f_syscall(int argc, VALUE *argv)
8885 {
8886 #ifdef atarist
8887 VALUE arg[13]; /* yes, we really need that many ! */
8888 #else
8889 VALUE arg[8];
8890 #endif
8891 #if SIZEOF_VOIDP == 8 && defined(HAVE___SYSCALL) && SIZEOF_INT != 8 /* mainly *BSD */
8892 # define SYSCALL __syscall
8893 # define NUM2SYSCALLID(x) NUM2LONG(x)
8894 # define RETVAL2NUM(x) LONG2NUM(x)
8895 # if SIZEOF_LONG == 8
8896 long num, retval = -1;
8897 # elif SIZEOF_LONG_LONG == 8
8898 long long num, retval = -1;
8899 # else
8900 # error ---->> it is asserted that __syscall takes the first argument and returns retval in 64bit signed integer. <<----
8901 # endif
8902 #elif defined(__linux__)
8903 # define SYSCALL syscall
8904 # define NUM2SYSCALLID(x) NUM2LONG(x)
8905 # define RETVAL2NUM(x) LONG2NUM(x)
8906 /*
8907 * Linux man page says, syscall(2) function prototype is below.
8908 *
8909 * int syscall(int number, ...);
8910 *
8911 * But, it's incorrect. Actual one takes and returned long. (see unistd.h)
8912 */
8913 long num, retval = -1;
8914 #else
8915 # define SYSCALL syscall
8916 # define NUM2SYSCALLID(x) NUM2INT(x)
8917 # define RETVAL2NUM(x) INT2NUM(x)
8918 int num, retval = -1;
8919 #endif
8920 int i;
8921
8922 if (RTEST(ruby_verbose)) {
8923 rb_warning("We plan to remove a syscall function at future release. DL(Fiddle) provides safer alternative.");
8924 }
8925
8926 rb_secure(2);
8927 if (argc == 0)
8928 rb_raise(rb_eArgError, "too few arguments for syscall");
8929 if (argc > numberof(arg))
8930 rb_raise(rb_eArgError, "too many arguments for syscall");
8931 num = NUM2SYSCALLID(argv[0]); ++argv;
8932 for (i = argc - 1; i--; ) {
8933 VALUE v = rb_check_string_type(argv[i]);
8934
8935 if (!NIL_P(v)) {
8936 SafeStringValue(v);
8937 rb_str_modify(v);
8938 arg[i] = (VALUE)StringValueCStr(v);
8939 }
8940 else {
8941 arg[i] = (VALUE)NUM2LONG(argv[i]);
8942 }
8943 }
8944
8945 switch (argc) {
8946 case 1:
8947 retval = SYSCALL(num);
8948 break;
8949 case 2:
8950 retval = SYSCALL(num, arg[0]);
8951 break;
8952 case 3:
8953 retval = SYSCALL(num, arg[0],arg[1]);
8954 break;
8955 case 4:
8956 retval = SYSCALL(num, arg[0],arg[1],arg[2]);
8957 break;
8958 case 5:
8959 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3]);
8960 break;
8961 case 6:
8962 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4]);
8963 break;
8964 case 7:
8965 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5]);
8966 break;
8967 case 8:
8968 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6]);
8969 break;
8970 #ifdef atarist
8971 case 9:
8972 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
8973 arg[7]);
8974 break;
8975 case 10:
8976 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
8977 arg[7], arg[8]);
8978 break;
8979 case 11:
8980 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
8981 arg[7], arg[8], arg[9]);
8982 break;
8983 case 12:
8984 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
8985 arg[7], arg[8], arg[9], arg[10]);
8986 break;
8987 case 13:
8988 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
8989 arg[7], arg[8], arg[9], arg[10], arg[11]);
8990 break;
8991 case 14:
8992 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
8993 arg[7], arg[8], arg[9], arg[10], arg[11], arg[12]);
8994 break;
8995 #endif
8996 }
8997
8998 if (retval == -1)
8999 rb_sys_fail(0);
9000 return RETVAL2NUM(retval);
9001 #undef SYSCALL
9002 #undef NUM2SYSCALLID
9003 #undef RETVAL2NUM
9004 }
9005 #else
9006 #define rb_f_syscall rb_f_notimplement
9007 #endif
9008
9009 static VALUE
9010 io_new_instance(VALUE args)
9011 {
9012 return rb_class_new_instance(2, (VALUE*)args+1, *(VALUE*)args);
9013 }
9014
9015 static rb_encoding *
9016 find_encoding(VALUE v)
9017 {
9018 rb_encoding *enc = rb_find_encoding(v);
9019 if (!enc) unsupported_encoding(StringValueCStr(v));
9020 return enc;
9021 }
9022
9023 static void
9024 io_encoding_set(rb_io_t *fptr, VALUE v1, VALUE v2, VALUE opt)
9025 {
9026 rb_encoding *enc, *enc2;
9027 int ecflags = fptr->encs.ecflags;
9028 VALUE ecopts, tmp;
9029
9030 if (!NIL_P(v2)) {
9031 enc2 = find_encoding(v1);
9032 tmp = rb_check_string_type(v2);
9033 if (!NIL_P(tmp)) {
9034 if (RSTRING_LEN(tmp) == 1 && RSTRING_PTR(tmp)[0] == '-') {
9035 /* Special case - "-" => no transcoding */
9036 enc = enc2;
9037 enc2 = NULL;
9038 }
9039 else
9040 enc = find_encoding(v2);
9041 if (enc == enc2) {
9042 /* Special case - "-" => no transcoding */
9043 enc2 = NULL;
9044 }
9045 }
9046 else {
9047 enc = find_encoding(v2);
9048 if (enc == enc2) {
9049 /* Special case - "-" => no transcoding */
9050 enc2 = NULL;
9051 }
9052 }
9053 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
9054 ecflags = rb_econv_prepare_options(opt, &ecopts, ecflags);
9055 }
9056 else {
9057 if (NIL_P(v1)) {
9058 /* Set to default encodings */
9059 rb_io_ext_int_to_encs(NULL, NULL, &enc, &enc2, 0);
9060 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
9061 ecopts = Qnil;
9062 }
9063 else {
9064 tmp = rb_check_string_type(v1);
9065 if (!NIL_P(tmp) && rb_enc_asciicompat(rb_enc_get(tmp))) {
9066 parse_mode_enc(RSTRING_PTR(tmp), &enc, &enc2, NULL);
9067 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
9068 ecflags = rb_econv_prepare_options(opt, &ecopts, ecflags);
9069 }
9070 else {
9071 rb_io_ext_int_to_encs(find_encoding(v1), NULL, &enc, &enc2, 0);
9072 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
9073 ecopts = Qnil;
9074 }
9075 }
9076 }
9077 validate_enc_binmode(&fptr->mode, ecflags, enc, enc2);
9078 fptr->encs.enc = enc;
9079 fptr->encs.enc2 = enc2;
9080 fptr->encs.ecflags = ecflags;
9081 fptr->encs.ecopts = ecopts;
9082 clear_codeconv(fptr);
9083
9084 }
9085
9086 static VALUE
9087 pipe_pair_close(VALUE rw)
9088 {
9089 VALUE *rwp = (VALUE *)rw;
9090 return rb_ensure(io_close, rwp[0], io_close, rwp[1]);
9091 }
9092
9093 /*
9094 * call-seq:
9095 * IO.pipe -> [read_io, write_io]
9096 * IO.pipe(ext_enc) -> [read_io, write_io]
9097 * IO.pipe("ext_enc:int_enc" [, opt]) -> [read_io, write_io]
9098 * IO.pipe(ext_enc, int_enc [, opt]) -> [read_io, write_io]
9099 *
9100 * IO.pipe(...) {|read_io, write_io| ... }
9101 *
9102 * Creates a pair of pipe endpoints (connected to each other) and
9103 * returns them as a two-element array of <code>IO</code> objects:
9104 * <code>[</code> <i>read_io</i>, <i>write_io</i> <code>]</code>.
9105 *
9106 * If a block is given, the block is called and
9107 * returns the value of the block.
9108 * <i>read_io</i> and <i>write_io</i> are sent to the block as arguments.
9109 * If read_io and write_io are not closed when the block exits, they are closed.
9110 * i.e. closing read_io and/or write_io doesn't cause an error.
9111 *
9112 * Not available on all platforms.
9113 *
9114 * If an encoding (encoding name or encoding object) is specified as an optional argument,
9115 * read string from pipe is tagged with the encoding specified.
9116 * If the argument is a colon separated two encoding names "A:B",
9117 * the read string is converted from encoding A (external encoding)
9118 * to encoding B (internal encoding), then tagged with B.
9119 * If two optional arguments are specified, those must be
9120 * encoding objects or encoding names,
9121 * and the first one is the external encoding,
9122 * and the second one is the internal encoding.
9123 * If the external encoding and the internal encoding is specified,
9124 * optional hash argument specify the conversion option.
9125 *
9126 * In the example below, the two processes close the ends of the pipe
9127 * that they are not using. This is not just a cosmetic nicety. The
9128 * read end of a pipe will not generate an end of file condition if
9129 * there are any writers with the pipe still open. In the case of the
9130 * parent process, the <code>rd.read</code> will never return if it
9131 * does not first issue a <code>wr.close</code>.
9132 *
9133 * rd, wr = IO.pipe
9134 *
9135 * if fork
9136 * wr.close
9137 * puts "Parent got: <#{rd.read}>"
9138 * rd.close
9139 * Process.wait
9140 * else
9141 * rd.close
9142 * puts "Sending message to parent"
9143 * wr.write "Hi Dad"
9144 * wr.close
9145 * end
9146 *
9147 * <em>produces:</em>
9148 *
9149 * Sending message to parent
9150 * Parent got: <Hi Dad>
9151 */
9152
9153 static VALUE
9154 rb_io_s_pipe(int argc, VALUE *argv, VALUE klass)
9155 {
9156 int pipes[2], state;
9157 VALUE r, w, args[3], v1, v2;
9158 VALUE opt;
9159 rb_io_t *fptr, *fptr2;
9160 int fmode = 0;
9161 VALUE ret;
9162
9163 argc = rb_scan_args(argc, argv, "02:", &v1, &v2, &opt);
9164 if (rb_pipe(pipes) == -1)
9165 rb_sys_fail(0);
9166
9167 args[0] = klass;
9168 args[1] = INT2NUM(pipes[0]);
9169 args[2] = INT2FIX(O_RDONLY);
9170 r = rb_protect(io_new_instance, (VALUE)args, &state);
9171 if (state) {
9172 close(pipes[0]);
9173 close(pipes[1]);
9174 rb_jump_tag(state);
9175 }
9176 GetOpenFile(r, fptr);
9177 io_encoding_set(fptr, v1, v2, opt);
9178 args[1] = INT2NUM(pipes[1]);
9179 args[2] = INT2FIX(O_WRONLY);
9180 w = rb_protect(io_new_instance, (VALUE)args, &state);
9181 if (state) {
9182 close(pipes[1]);
9183 if (!NIL_P(r)) rb_io_close(r);
9184 rb_jump_tag(state);
9185 }
9186 GetOpenFile(w, fptr2);
9187 rb_io_synchronized(fptr2);
9188
9189 extract_binmode(opt, &fmode);
9190 #if DEFAULT_TEXTMODE
9191 if ((fptr->mode & FMODE_TEXTMODE) && (fmode & FMODE_BINMODE)) {
9192 fptr->mode &= ~FMODE_TEXTMODE;
9193 setmode(fptr->fd, O_BINARY);
9194 }
9195 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
9196 if (fptr->encs.ecflags & ECONV_DEFAULT_NEWLINE_DECORATOR) {
9197 fptr->encs.ecflags |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;
9198 }
9199 #endif
9200 #endif
9201 fptr->mode |= fmode;
9202 #if DEFAULT_TEXTMODE
9203 if ((fptr2->mode & FMODE_TEXTMODE) && (fmode & FMODE_BINMODE)) {
9204 fptr2->mode &= ~FMODE_TEXTMODE;
9205 setmode(fptr2->fd, O_BINARY);
9206 }
9207 #endif
9208 fptr2->mode |= fmode;
9209
9210 ret = rb_assoc_new(r, w);
9211 if (rb_block_given_p()) {
9212 VALUE rw[2];
9213 rw[0] = r;
9214 rw[1] = w;
9215 return rb_ensure(rb_yield, ret, pipe_pair_close, (VALUE)rw);
9216 }
9217 return ret;
9218 }
9219
9220 struct foreach_arg {
9221 int argc;
9222 VALUE *argv;
9223 VALUE io;
9224 };
9225
9226 static void
9227 open_key_args(int argc, VALUE *argv, VALUE opt, struct foreach_arg *arg)
9228 {
9229 VALUE path, v;
9230
9231 path = *argv++;
9232 argc--;
9233 FilePathValue(path);
9234 arg->io = 0;
9235 arg->argc = argc;
9236 arg->argv = argv;
9237 if (NIL_P(opt)) {
9238 arg->io = rb_io_open(path, INT2NUM(O_RDONLY), INT2FIX(0666), Qnil);
9239 return;
9240 }
9241 v = rb_hash_aref(opt, sym_open_args);
9242 if (!NIL_P(v)) {
9243 VALUE args;
9244 long n;
9245
9246 v = rb_convert_type(v, T_ARRAY, "Array", "to_ary");
9247 n = RARRAY_LEN(v) + 1;
9248 #if SIZEOF_LONG > SIZEOF_INT
9249 if (n > INT_MAX) {
9250 rb_raise(rb_eArgError, "too many arguments");
9251 }
9252 #endif
9253 args = rb_ary_tmp_new(n);
9254 rb_ary_push(args, path);
9255 rb_ary_concat(args, v);
9256 arg->io = rb_io_open_with_args((int)n, RARRAY_PTR(args));
9257 rb_ary_clear(args); /* prevent from GC */
9258 return;
9259 }
9260 arg->io = rb_io_open(path, Qnil, Qnil, opt);
9261 }
9262
9263 static VALUE
9264 io_s_foreach(struct foreach_arg *arg)
9265 {
9266 VALUE str;
9267
9268 while (!NIL_P(str = rb_io_gets_m(arg->argc, arg->argv, arg->io))) {
9269 rb_yield(str);
9270 }
9271 return Qnil;
9272 }
9273
9274 /*
9275 * call-seq:
9276 * IO.foreach(name, sep=$/ [, open_args]) {|line| block } -> nil
9277 * IO.foreach(name, limit [, open_args]) {|line| block } -> nil
9278 * IO.foreach(name, sep, limit [, open_args]) {|line| block } -> nil
9279 * IO.foreach(...) -> an_enumerator
9280 *
9281 * Executes the block for every line in the named I/O port, where lines
9282 * are separated by <em>sep</em>.
9283 *
9284 * If no block is given, an enumerator is returned instead.
9285 *
9286 * IO.foreach("testfile") {|x| print "GOT ", x }
9287 *
9288 * <em>produces:</em>
9289 *
9290 * GOT This is line one
9291 * GOT This is line two
9292 * GOT This is line three
9293 * GOT And so on...
9294 *
9295 * If the last argument is a hash, it's the keyword argument to open.
9296 * See <code>IO.read</code> for detail.
9297 *
9298 */
9299
9300 static VALUE
9301 rb_io_s_foreach(int argc, VALUE *argv, VALUE self)
9302 {
9303 VALUE opt;
9304 int orig_argc = argc;
9305 struct foreach_arg arg;
9306
9307 argc = rb_scan_args(argc, argv, "13:", NULL, NULL, NULL, NULL, &opt);
9308 RETURN_ENUMERATOR(self, orig_argc, argv);
9309 open_key_args(argc, argv, opt, &arg);
9310 if (NIL_P(arg.io)) return Qnil;
9311 return rb_ensure(io_s_foreach, (VALUE)&arg, rb_io_close, arg.io);
9312 }
9313
9314 static VALUE
9315 io_s_readlines(struct foreach_arg *arg)
9316 {
9317 return rb_io_readlines(arg->argc, arg->argv, arg->io);
9318 }
9319
9320 /*
9321 * call-seq:
9322 * IO.readlines(name, sep=$/ [, open_args]) -> array
9323 * IO.readlines(name, limit [, open_args]) -> array
9324 * IO.readlines(name, sep, limit [, open_args]) -> array
9325 *
9326 * Reads the entire file specified by <i>name</i> as individual
9327 * lines, and returns those lines in an array. Lines are separated by
9328 * <i>sep</i>.
9329 *
9330 * a = IO.readlines("testfile")
9331 * a[0] #=> "This is line one\n"
9332 *
9333 * If the last argument is a hash, it's the keyword argument to open.
9334 * See <code>IO.read</code> for detail.
9335 *
9336 */
9337
9338 static VALUE
9339 rb_io_s_readlines(int argc, VALUE *argv, VALUE io)
9340 {
9341 VALUE opt;
9342 struct foreach_arg arg;
9343
9344 argc = rb_scan_args(argc, argv, "13:", NULL, NULL, NULL, NULL, &opt);
9345 open_key_args(argc, argv, opt, &arg);
9346 if (NIL_P(arg.io)) return Qnil;
9347 return rb_ensure(io_s_readlines, (VALUE)&arg, rb_io_close, arg.io);
9348 }
9349
9350 static VALUE
9351 io_s_read(struct foreach_arg *arg)
9352 {
9353 return io_read(arg->argc, arg->argv, arg->io);
9354 }
9355
9356 struct seek_arg {
9357 VALUE io;
9358 VALUE offset;
9359 int mode;
9360 };
9361
9362 static VALUE
9363 seek_before_access(VALUE argp)
9364 {
9365 struct seek_arg *arg = (struct seek_arg *)argp;
9366 rb_io_binmode(arg->io);
9367 return rb_io_seek(arg->io, arg->offset, arg->mode);
9368 }
9369
9370 /*
9371 * call-seq:
9372 * IO.read(name, [length [, offset]] ) -> string
9373 * IO.read(name, [length [, offset]], open_args) -> string
9374 *
9375 * Opens the file, optionally seeks to the given +offset+, then returns
9376 * +length+ bytes (defaulting to the rest of the file). <code>read</code>
9377 * ensures the file is closed before returning.
9378 *
9379 * If the last argument is a hash, it specifies option for internal
9380 * open(). The key would be the following. open_args: is exclusive
9381 * to others.
9382 *
9383 * encoding::
9384 * string or encoding
9385 *
9386 * specifies encoding of the read string. +encoding+ will be ignored
9387 * if length is specified.
9388 *
9389 * mode::
9390 * string
9391 *
9392 * specifies mode argument for open(). It should start with "r"
9393 * otherwise it will cause an error.
9394 *
9395 * open_args:: array of strings
9396 *
9397 * specifies arguments for open() as an array.
9398 *
9399 * Examples:
9400 *
9401 * IO.read("testfile") #=> "This is line one\nThis is line two\nThis is line three\nAnd so on...\n"
9402 * IO.read("testfile", 20) #=> "This is line one\nThi"
9403 * IO.read("testfile", 20, 10) #=> "ne one\nThis is line "
9404 */
9405
9406 static VALUE
9407 rb_io_s_read(int argc, VALUE *argv, VALUE io)
9408 {
9409 VALUE opt, offset;
9410 struct foreach_arg arg;
9411
9412 argc = rb_scan_args(argc, argv, "13:", NULL, NULL, &offset, NULL, &opt);
9413 open_key_args(argc, argv, opt, &arg);
9414 if (NIL_P(arg.io)) return Qnil;
9415 if (!NIL_P(offset)) {
9416 struct seek_arg sarg;
9417 int state = 0;
9418 sarg.io = arg.io;
9419 sarg.offset = offset;
9420 sarg.mode = SEEK_SET;
9421 rb_protect(seek_before_access, (VALUE)&sarg, &state);
9422 if (state) {
9423 rb_io_close(arg.io);
9424 rb_jump_tag(state);
9425 }
9426 if (arg.argc == 2) arg.argc = 1;
9427 }
9428 return rb_ensure(io_s_read, (VALUE)&arg, rb_io_close, arg.io);
9429 }
9430
9431 /*
9432 * call-seq:
9433 * IO.binread(name, [length [, offset]] ) -> string
9434 *
9435 * Opens the file, optionally seeks to the given <i>offset</i>, then returns
9436 * <i>length</i> bytes (defaulting to the rest of the file).
9437 * <code>binread</code> ensures the file is closed before returning.
9438 * The open mode would be "rb:ASCII-8BIT".
9439 *
9440 * IO.binread("testfile") #=> "This is line one\nThis is line two\nThis is line three\nAnd so on...\n"
9441 * IO.binread("testfile", 20) #=> "This is line one\nThi"
9442 * IO.binread("testfile", 20, 10) #=> "ne one\nThis is line "
9443 */
9444
9445 static VALUE
9446 rb_io_s_binread(int argc, VALUE *argv, VALUE io)
9447 {
9448 VALUE offset;
9449 struct foreach_arg arg;
9450
9451 rb_scan_args(argc, argv, "12", NULL, NULL, &offset);
9452 FilePathValue(argv[0]);
9453 arg.io = rb_io_open(argv[0], rb_str_new_cstr("rb:ASCII-8BIT"), Qnil, Qnil);
9454 if (NIL_P(arg.io)) return Qnil;
9455 arg.argv = argv+1;
9456 arg.argc = (argc > 1) ? 1 : 0;
9457 if (!NIL_P(offset)) {
9458 rb_io_seek(arg.io, offset, SEEK_SET);
9459 }
9460 return rb_ensure(io_s_read, (VALUE)&arg, rb_io_close, arg.io);
9461 }
9462
9463 static VALUE
9464 io_s_write0(struct write_arg *arg)
9465 {
9466 return io_write(arg->io,arg->str,arg->nosync);
9467 }
9468
9469 static VALUE
9470 io_s_write(int argc, VALUE *argv, int binary)
9471 {
9472 VALUE string, offset, opt;
9473 struct foreach_arg arg;
9474 struct write_arg warg;
9475
9476 rb_scan_args(argc, argv, "21:", NULL, &string, &offset, &opt);
9477
9478 if (NIL_P(opt)) opt = rb_hash_new();
9479 else opt = rb_hash_dup(opt);
9480
9481
9482 if (NIL_P(rb_hash_aref(opt,sym_mode))) {
9483 int mode = O_WRONLY|O_CREAT;
9484 #ifdef O_BINARY
9485 if (binary) mode |= O_BINARY;
9486 #endif
9487 if (NIL_P(offset)) mode |= O_TRUNC;
9488 rb_hash_aset(opt,sym_mode,INT2NUM(mode));
9489 }
9490 open_key_args(argc,argv,opt,&arg);
9491
9492 #ifndef O_BINARY
9493 if (binary) rb_io_binmode_m(arg.io);
9494 #endif
9495
9496 if (NIL_P(arg.io)) return Qnil;
9497 if (!NIL_P(offset)) {
9498 struct seek_arg sarg;
9499 int state = 0;
9500 sarg.io = arg.io;
9501 sarg.offset = offset;
9502 sarg.mode = SEEK_SET;
9503 rb_protect(seek_before_access, (VALUE)&sarg, &state);
9504 if (state) {
9505 rb_io_close(arg.io);
9506 rb_jump_tag(state);
9507 }
9508 }
9509
9510 warg.io = arg.io;
9511 warg.str = string;
9512 warg.nosync = 0;
9513
9514 return rb_ensure(io_s_write0, (VALUE)&warg, rb_io_close, arg.io);
9515 }
9516
9517 /*
9518 * call-seq:
9519 * IO.write(name, string, [offset] ) => fixnum
9520 * IO.write(name, string, [offset], open_args ) => fixnum
9521 *
9522 * Opens the file, optionally seeks to the given <i>offset</i>, writes
9523 * <i>string</i>, then returns the length written.
9524 * <code>write</code> ensures the file is closed before returning.
9525 * If <i>offset</i> is not given, the file is truncated. Otherwise,
9526 * it is not truncated.
9527 *
9528 * If the last argument is a hash, it specifies option for internal
9529 * open(). The key would be the following. open_args: is exclusive
9530 * to others.
9531 *
9532 * encoding: string or encoding
9533 *
9534 * specifies encoding of the read string. encoding will be ignored
9535 * if length is specified.
9536 *
9537 * mode: string
9538 *
9539 * specifies mode argument for open(). it should start with "w" or "a" or "r+"
9540 * otherwise it would cause error.
9541 *
9542 * perm: fixnum
9543 *
9544 * specifies perm argument for open().
9545 *
9546 * open_args: array
9547 *
9548 * specifies arguments for open() as an array.
9549 *
9550 * IO.write("testfile", "0123456789", 20) # => 10
9551 * # File could contain: "This is line one\nThi0123456789two\nThis is line three\nAnd so on...\n"
9552 * IO.write("testfile", "0123456789") #=> 10
9553 * # File would now read: "0123456789"
9554 */
9555
9556 static VALUE
9557 rb_io_s_write(int argc, VALUE *argv, VALUE io)
9558 {
9559 return io_s_write(argc, argv, 0);
9560 }
9561
9562 /*
9563 * call-seq:
9564 * IO.binwrite(name, string, [offset] ) => fixnum
9565 * IO.binwrite(name, string, [offset], open_args ) => fixnum
9566 *
9567 * Same as <code>IO.write</code> except opening the file in binary mode
9568 * and ASCII-8BIT encoding ("wb:ASCII-8BIT").
9569 *
9570 */
9571
9572 static VALUE
9573 rb_io_s_binwrite(int argc, VALUE *argv, VALUE io)
9574 {
9575 return io_s_write(argc, argv, 1);
9576 }
9577
9578 struct copy_stream_struct {
9579 VALUE src;
9580 VALUE dst;
9581 off_t copy_length; /* (off_t)-1 if not specified */
9582 off_t src_offset; /* (off_t)-1 if not specified */
9583
9584 int src_fd;
9585 int dst_fd;
9586 int close_src;
9587 int close_dst;
9588 off_t total;
9589 const char *syserr;
9590 int error_no;
9591 const char *notimp;
9592 rb_fdset_t fds;
9593 VALUE th;
9594 };
9595
9596 static void *
9597 exec_interrupts(void *arg)
9598 {
9599 VALUE th = (VALUE)arg;
9600 rb_thread_execute_interrupts(th);
9601 return NULL;
9602 }
9603
9604 /*
9605 * returns TRUE if the preceding system call was interrupted
9606 * so we can continue. If the thread was interrupted, we
9607 * reacquire the GVL to execute interrupts before continuing.
9608 */
9609 static int
9610 maygvl_copy_stream_continue_p(int has_gvl, struct copy_stream_struct *stp)
9611 {
9612 switch (errno) {
9613 case EINTR:
9614 #if defined(ERESTART)
9615 case ERESTART:
9616 #endif
9617 if (rb_thread_interrupted(stp->th)) {
9618 if (has_gvl)
9619 rb_thread_execute_interrupts(stp->th);
9620 else
9621 rb_thread_call_with_gvl(exec_interrupts, (void *)stp->th);
9622 }
9623 return TRUE;
9624 }
9625 return FALSE;
9626 }
9627
9628 static int
9629 maygvl_select(int has_gvl, int n, rb_fdset_t *rfds, rb_fdset_t *wfds, rb_fdset_t *efds, struct timeval *timeout)
9630 {
9631 if (has_gvl)
9632 return rb_thread_fd_select(n, rfds, wfds, efds, timeout);
9633 else
9634 return rb_fd_select(n, rfds, wfds, efds, timeout);
9635 }
9636
9637 static int
9638 maygvl_copy_stream_wait_read(int has_gvl, struct copy_stream_struct *stp)
9639 {
9640 int ret;
9641
9642 do {
9643 rb_fd_zero(&stp->fds);
9644 rb_fd_set(stp->src_fd, &stp->fds);
9645 ret = maygvl_select(has_gvl, rb_fd_max(&stp->fds), &stp->fds, NULL, NULL, NULL);
9646 } while (ret == -1 && maygvl_copy_stream_continue_p(has_gvl, stp));
9647
9648 if (ret == -1) {
9649 stp->syserr = "select";
9650 stp->error_no = errno;
9651 return -1;
9652 }
9653 return 0;
9654 }
9655
9656 static int
9657 nogvl_copy_stream_wait_write(struct copy_stream_struct *stp)
9658 {
9659 int ret;
9660
9661 do {
9662 rb_fd_zero(&stp->fds);
9663 rb_fd_set(stp->dst_fd, &stp->fds);
9664 ret = rb_fd_select(rb_fd_max(&stp->fds), NULL, &stp->fds, NULL, NULL);
9665 } while (ret == -1 && maygvl_copy_stream_continue_p(0, stp));
9666
9667 if (ret == -1) {
9668 stp->syserr = "select";
9669 stp->error_no = errno;
9670 return -1;
9671 }
9672 return 0;
9673 }
9674
9675 #ifdef HAVE_SENDFILE
9676
9677 # ifdef __linux__
9678 # define USE_SENDFILE
9679
9680 # ifdef HAVE_SYS_SENDFILE_H
9681 # include <sys/sendfile.h>
9682 # endif
9683
9684 static ssize_t
9685 simple_sendfile(int out_fd, int in_fd, off_t *offset, off_t count)
9686 {
9687 return sendfile(out_fd, in_fd, offset, (size_t)count);
9688 }
9689
9690 # elif 0 /* defined(__FreeBSD__) || defined(__DragonFly__) */ || defined(__APPLE__)
9691 /* This runs on FreeBSD8.1 r30210, but sendfiles blocks its execution
9692 * without cpuset -l 0.
9693 */
9694 # define USE_SENDFILE
9695
9696 # ifdef HAVE_SYS_UIO_H
9697 # include <sys/uio.h>
9698 # endif
9699
9700 static ssize_t
9701 simple_sendfile(int out_fd, int in_fd, off_t *offset, off_t count)
9702 {
9703 int r;
9704 off_t pos = offset ? *offset : lseek(in_fd, 0, SEEK_CUR);
9705 off_t sbytes;
9706 # ifdef __APPLE__
9707 r = sendfile(in_fd, out_fd, pos, &count, NULL, 0);
9708 sbytes = count;
9709 # else
9710 r = sendfile(in_fd, out_fd, pos, (size_t)count, NULL, &sbytes, 0);
9711 # endif
9712 if (r != 0 && sbytes == 0) return -1;
9713 if (offset) {
9714 *offset += sbytes;
9715 }
9716 else {
9717 lseek(in_fd, sbytes, SEEK_CUR);
9718 }
9719 return (ssize_t)sbytes;
9720 }
9721
9722 # endif
9723
9724 #endif
9725
9726 #ifdef USE_SENDFILE
9727 static int
9728 nogvl_copy_stream_sendfile(struct copy_stream_struct *stp)
9729 {
9730 struct stat src_stat, dst_stat;
9731 ssize_t ss;
9732 int ret;
9733
9734 off_t copy_length;
9735 off_t src_offset;
9736 int use_pread;
9737
9738 ret = fstat(stp->src_fd, &src_stat);
9739 if (ret == -1) {
9740 stp->syserr = "fstat";
9741 stp->error_no = errno;
9742 return -1;
9743 }
9744 if (!S_ISREG(src_stat.st_mode))
9745 return 0;
9746
9747 ret = fstat(stp->dst_fd, &dst_stat);
9748 if (ret == -1) {
9749 stp->syserr = "fstat";
9750 stp->error_no = errno;
9751 return -1;
9752 }
9753 if ((dst_stat.st_mode & S_IFMT) != S_IFSOCK)
9754 return 0;
9755
9756 src_offset = stp->src_offset;
9757 use_pread = src_offset != (off_t)-1;
9758
9759 copy_length = stp->copy_length;
9760 if (copy_length == (off_t)-1) {
9761 if (use_pread)
9762 copy_length = src_stat.st_size - src_offset;
9763 else {
9764 off_t cur;
9765 errno = 0;
9766 cur = lseek(stp->src_fd, 0, SEEK_CUR);
9767 if (cur == (off_t)-1 && errno) {
9768 stp->syserr = "lseek";
9769 stp->error_no = errno;
9770 return -1;
9771 }
9772 copy_length = src_stat.st_size - cur;
9773 }
9774 }
9775
9776 retry_sendfile:
9777 # if SIZEOF_OFF_T > SIZEOF_SIZE_T
9778 /* we are limited by the 32-bit ssize_t return value on 32-bit */
9779 ss = (copy_length > (off_t)SSIZE_MAX) ? SSIZE_MAX : (ssize_t)copy_length;
9780 # else
9781 ss = (ssize_t)copy_length;
9782 # endif
9783 if (use_pread) {
9784 ss = simple_sendfile(stp->dst_fd, stp->src_fd, &src_offset, ss);
9785 }
9786 else {
9787 ss = simple_sendfile(stp->dst_fd, stp->src_fd, NULL, ss);
9788 }
9789 if (0 < ss) {
9790 stp->total += ss;
9791 copy_length -= ss;
9792 if (0 < copy_length) {
9793 goto retry_sendfile;
9794 }
9795 }
9796 if (ss == -1) {
9797 if (maygvl_copy_stream_continue_p(0, stp))
9798 goto retry_sendfile;
9799 switch (errno) {
9800 case EINVAL:
9801 #ifdef ENOSYS
9802 case ENOSYS:
9803 #endif
9804 return 0;
9805 case EAGAIN:
9806 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
9807 case EWOULDBLOCK:
9808 #endif
9809 #ifndef __linux__
9810 /*
9811 * Linux requires stp->src_fd to be a mmap-able (regular) file,
9812 * select() reports regular files to always be "ready", so
9813 * there is no need to select() on it.
9814 * Other OSes may have the same limitation for sendfile() which
9815 * allow us to bypass maygvl_copy_stream_wait_read()...
9816 */
9817 if (maygvl_copy_stream_wait_read(0, stp) == -1)
9818 return -1;
9819 #endif
9820 if (nogvl_copy_stream_wait_write(stp) == -1)
9821 return -1;
9822 goto retry_sendfile;
9823 }
9824 stp->syserr = "sendfile";
9825 stp->error_no = errno;
9826 return -1;
9827 }
9828 return 1;
9829 }
9830 #endif
9831
9832 static ssize_t
9833 maygvl_read(int has_gvl, int fd, void *buf, size_t count)
9834 {
9835 if (has_gvl)
9836 return rb_read_internal(fd, buf, count);
9837 else
9838 return read(fd, buf, count);
9839 }
9840
9841 static ssize_t
9842 maygvl_copy_stream_read(int has_gvl, struct copy_stream_struct *stp, char *buf, size_t len, off_t offset)
9843 {
9844 ssize_t ss;
9845 retry_read:
9846 if (offset == (off_t)-1) {
9847 ss = maygvl_read(has_gvl, stp->src_fd, buf, len);
9848 }
9849 else {
9850 #ifdef HAVE_PREAD
9851 ss = pread(stp->src_fd, buf, len, offset);
9852 #else
9853 stp->notimp = "pread";
9854 return -1;
9855 #endif
9856 }
9857 if (ss == 0) {
9858 return 0;
9859 }
9860 if (ss == -1) {
9861 if (maygvl_copy_stream_continue_p(has_gvl, stp))
9862 goto retry_read;
9863 switch (errno) {
9864 case EAGAIN:
9865 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
9866 case EWOULDBLOCK:
9867 #endif
9868 if (maygvl_copy_stream_wait_read(has_gvl, stp) == -1)
9869 return -1;
9870 goto retry_read;
9871 #ifdef ENOSYS
9872 case ENOSYS:
9873 #endif
9874 stp->notimp = "pread";
9875 return -1;
9876 }
9877 stp->syserr = offset == (off_t)-1 ? "read" : "pread";
9878 stp->error_no = errno;
9879 return -1;
9880 }
9881 return ss;
9882 }
9883
9884 static int
9885 nogvl_copy_stream_write(struct copy_stream_struct *stp, char *buf, size_t len)
9886 {
9887 ssize_t ss;
9888 int off = 0;
9889 while (len) {
9890 ss = write(stp->dst_fd, buf+off, len);
9891 if (ss == -1) {
9892 if (maygvl_copy_stream_continue_p(0, stp))
9893 continue;
9894 if (errno == EAGAIN || errno == EWOULDBLOCK) {
9895 if (nogvl_copy_stream_wait_write(stp) == -1)
9896 return -1;
9897 continue;
9898 }
9899 stp->syserr = "write";
9900 stp->error_no = errno;
9901 return -1;
9902 }
9903 off += (int)ss;
9904 len -= (int)ss;
9905 stp->total += ss;
9906 }
9907 return 0;
9908 }
9909
9910 static void
9911 nogvl_copy_stream_read_write(struct copy_stream_struct *stp)
9912 {
9913 char buf[1024*16];
9914 size_t len;
9915 ssize_t ss;
9916 int ret;
9917 off_t copy_length;
9918 int use_eof;
9919 off_t src_offset;
9920 int use_pread;
9921
9922 copy_length = stp->copy_length;
9923 use_eof = copy_length == (off_t)-1;
9924 src_offset = stp->src_offset;
9925 use_pread = src_offset != (off_t)-1;
9926
9927 if (use_pread && stp->close_src) {
9928 off_t r;
9929 errno = 0;
9930 r = lseek(stp->src_fd, src_offset, SEEK_SET);
9931 if (r == (off_t)-1 && errno) {
9932 stp->syserr = "lseek";
9933 stp->error_no = errno;
9934 return;
9935 }
9936 src_offset = (off_t)-1;
9937 use_pread = 0;
9938 }
9939
9940 while (use_eof || 0 < copy_length) {
9941 if (!use_eof && copy_length < (off_t)sizeof(buf)) {
9942 len = (size_t)copy_length;
9943 }
9944 else {
9945 len = sizeof(buf);
9946 }
9947 if (use_pread) {
9948 ss = maygvl_copy_stream_read(0, stp, buf, len, src_offset);
9949 if (0 < ss)
9950 src_offset += ss;
9951 }
9952 else {
9953 ss = maygvl_copy_stream_read(0, stp, buf, len, (off_t)-1);
9954 }
9955 if (ss <= 0) /* EOF or error */
9956 return;
9957
9958 ret = nogvl_copy_stream_write(stp, buf, ss);
9959 if (ret < 0)
9960 return;
9961
9962 if (!use_eof)
9963 copy_length -= ss;
9964 }
9965 }
9966
9967 static void *
9968 nogvl_copy_stream_func(void *arg)
9969 {
9970 struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
9971 #ifdef USE_SENDFILE
9972 int ret;
9973 #endif
9974
9975 #ifdef USE_SENDFILE
9976 ret = nogvl_copy_stream_sendfile(stp);
9977 if (ret != 0)
9978 goto finish; /* error or success */
9979 #endif
9980
9981 nogvl_copy_stream_read_write(stp);
9982
9983 #ifdef USE_SENDFILE
9984 finish:
9985 #endif
9986 return 0;
9987 }
9988
9989 static VALUE
9990 copy_stream_fallback_body(VALUE arg)
9991 {
9992 struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
9993 const int buflen = 16*1024;
9994 VALUE n;
9995 VALUE buf = rb_str_buf_new(buflen);
9996 off_t rest = stp->copy_length;
9997 off_t off = stp->src_offset;
9998 ID read_method = id_readpartial;
9999
10000 if (stp->src_fd == -1) {
10001 if (!rb_respond_to(stp->src, read_method)) {
10002 read_method = id_read;
10003 }
10004 }
10005
10006 while (1) {
10007 long numwrote;
10008 long l;
10009 if (stp->copy_length == (off_t)-1) {
10010 l = buflen;
10011 }
10012 else {
10013 if (rest == 0)
10014 break;
10015 l = buflen < rest ? buflen : (long)rest;
10016 }
10017 if (stp->src_fd == -1) {
10018 VALUE rc = rb_funcall(stp->src, read_method, 2, INT2FIX(l), buf);
10019
10020 if (read_method == id_read && NIL_P(rc))
10021 break;
10022 }
10023 else {
10024 ssize_t ss;
10025 rb_str_resize(buf, buflen);
10026 ss = maygvl_copy_stream_read(1, stp, RSTRING_PTR(buf), l, off);
10027 if (ss == -1)
10028 return Qnil;
10029 if (ss == 0)
10030 rb_eof_error();
10031 rb_str_resize(buf, ss);
10032 if (off != (off_t)-1)
10033 off += ss;
10034 }
10035 n = rb_io_write(stp->dst, buf);
10036 numwrote = NUM2LONG(n);
10037 stp->total += numwrote;
10038 rest -= numwrote;
10039 if (read_method == id_read && RSTRING_LEN(buf) == 0) {
10040 break;
10041 }
10042 }
10043
10044 return Qnil;
10045 }
10046
10047 static VALUE
10048 copy_stream_fallback(struct copy_stream_struct *stp)
10049 {
10050 if (stp->src_fd == -1 && stp->src_offset != (off_t)-1) {
10051 rb_raise(rb_eArgError, "cannot specify src_offset for non-IO");
10052 }
10053 rb_rescue2(copy_stream_fallback_body, (VALUE)stp,
10054 (VALUE (*) (ANYARGS))0, (VALUE)0,
10055 rb_eEOFError, (VALUE)0);
10056 return Qnil;
10057 }
10058
10059 static VALUE
10060 copy_stream_body(VALUE arg)
10061 {
10062 struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
10063 VALUE src_io, dst_io;
10064 rb_io_t *src_fptr = 0, *dst_fptr = 0;
10065 int src_fd, dst_fd;
10066
10067 stp->th = rb_thread_current();
10068
10069 stp->total = 0;
10070
10071 if (stp->src == argf ||
10072 !(RB_TYPE_P(stp->src, T_FILE) ||
10073 RB_TYPE_P(stp->src, T_STRING) ||
10074 rb_respond_to(stp->src, rb_intern("to_path")))) {
10075 src_fd = -1;
10076 }
10077 else {
10078 src_io = RB_TYPE_P(stp->src, T_FILE) ? stp->src : Qnil;
10079 if (NIL_P(src_io)) {
10080 VALUE args[2];
10081 int oflags = O_RDONLY;
10082 #ifdef O_NOCTTY
10083 oflags |= O_NOCTTY;
10084 #endif
10085 FilePathValue(stp->src);
10086 args[0] = stp->src;
10087 args[1] = INT2NUM(oflags);
10088 src_io = rb_class_new_instance(2, args, rb_cFile);
10089 stp->src = src_io;
10090 stp->close_src = 1;
10091 }
10092 GetOpenFile(src_io, src_fptr);
10093 rb_io_check_byte_readable(src_fptr);
10094 src_fd = src_fptr->fd;
10095 }
10096 stp->src_fd = src_fd;
10097
10098 if (stp->dst == argf ||
10099 !(RB_TYPE_P(stp->dst, T_FILE) ||
10100 RB_TYPE_P(stp->dst, T_STRING) ||
10101 rb_respond_to(stp->dst, rb_intern("to_path")))) {
10102 dst_fd = -1;
10103 }
10104 else {
10105 dst_io = RB_TYPE_P(stp->dst, T_FILE) ? stp->dst : Qnil;
10106 if (NIL_P(dst_io)) {
10107 VALUE args[3];
10108 int oflags = O_WRONLY|O_CREAT|O_TRUNC;
10109 #ifdef O_NOCTTY
10110 oflags |= O_NOCTTY;
10111 #endif
10112 FilePathValue(stp->dst);
10113 args[0] = stp->dst;
10114 args[1] = INT2NUM(oflags);
10115 args[2] = INT2FIX(0666);
10116 dst_io = rb_class_new_instance(3, args, rb_cFile);
10117 stp->dst = dst_io;
10118 stp->close_dst = 1;
10119 }
10120 else {
10121 dst_io = GetWriteIO(dst_io);
10122 stp->dst = dst_io;
10123 }
10124 GetOpenFile(dst_io, dst_fptr);
10125 rb_io_check_writable(dst_fptr);
10126 dst_fd = dst_fptr->fd;
10127 }
10128 stp->dst_fd = dst_fd;
10129
10130 #ifdef O_BINARY
10131 if (src_fptr)
10132 SET_BINARY_MODE_WITH_SEEK_CUR(src_fptr);
10133 if (dst_fptr)
10134 setmode(dst_fd, O_BINARY);
10135 #endif
10136
10137 if (stp->src_offset == (off_t)-1 && src_fptr && src_fptr->rbuf.len) {
10138 size_t len = src_fptr->rbuf.len;
10139 VALUE str;
10140 if (stp->copy_length != (off_t)-1 && stp->copy_length < (off_t)len) {
10141 len = (size_t)stp->copy_length;
10142 }
10143 str = rb_str_buf_new(len);
10144 rb_str_resize(str,len);
10145 read_buffered_data(RSTRING_PTR(str), len, src_fptr);
10146 if (dst_fptr) { /* IO or filename */
10147 if (io_binwrite(str, RSTRING_PTR(str), RSTRING_LEN(str), dst_fptr, 0) < 0)
10148 rb_sys_fail(0);
10149 }
10150 else /* others such as StringIO */
10151 rb_io_write(stp->dst, str);
10152 stp->total += len;
10153 if (stp->copy_length != (off_t)-1)
10154 stp->copy_length -= len;
10155 }
10156
10157 if (dst_fptr && io_fflush(dst_fptr) < 0) {
10158 rb_raise(rb_eIOError, "flush failed");
10159 }
10160
10161 if (stp->copy_length == 0)
10162 return Qnil;
10163
10164 if (src_fd == -1 || dst_fd == -1) {
10165 return copy_stream_fallback(stp);
10166 }
10167
10168 rb_fd_set(src_fd, &stp->fds);
10169 rb_fd_set(dst_fd, &stp->fds);
10170
10171 rb_thread_call_without_gvl(nogvl_copy_stream_func, (void*)stp, RUBY_UBF_IO, 0);
10172 return Qnil;
10173 }
10174
10175 static VALUE
10176 copy_stream_finalize(VALUE arg)
10177 {
10178 struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
10179 if (stp->close_src) {
10180 rb_io_close_m(stp->src);
10181 }
10182 if (stp->close_dst) {
10183 rb_io_close_m(stp->dst);
10184 }
10185 rb_fd_term(&stp->fds);
10186 if (stp->syserr) {
10187 errno = stp->error_no;
10188 rb_sys_fail(stp->syserr);
10189 }
10190 if (stp->notimp) {
10191 rb_raise(rb_eNotImpError, "%s() not implemented", stp->notimp);
10192 }
10193 return Qnil;
10194 }
10195
10196 /*
10197 * call-seq:
10198 * IO.copy_stream(src, dst)
10199 * IO.copy_stream(src, dst, copy_length)
10200 * IO.copy_stream(src, dst, copy_length, src_offset)
10201 *
10202 * IO.copy_stream copies <i>src</i> to <i>dst</i>.
10203 * <i>src</i> and <i>dst</i> is either a filename or an IO.
10204 *
10205 * This method returns the number of bytes copied.
10206 *
10207 * If optional arguments are not given,
10208 * the start position of the copy is
10209 * the beginning of the filename or
10210 * the current file offset of the IO.
10211 * The end position of the copy is the end of file.
10212 *
10213 * If <i>copy_length</i> is given,
10214 * No more than <i>copy_length</i> bytes are copied.
10215 *
10216 * If <i>src_offset</i> is given,
10217 * it specifies the start position of the copy.
10218 *
10219 * When <i>src_offset</i> is specified and
10220 * <i>src</i> is an IO,
10221 * IO.copy_stream doesn't move the current file offset.
10222 *
10223 */
10224 static VALUE
10225 rb_io_s_copy_stream(int argc, VALUE *argv, VALUE io)
10226 {
10227 VALUE src, dst, length, src_offset;
10228 struct copy_stream_struct st;
10229
10230 MEMZERO(&st, struct copy_stream_struct, 1);
10231
10232 rb_scan_args(argc, argv, "22", &src, &dst, &length, &src_offset);
10233
10234 st.src = src;
10235 st.dst = dst;
10236
10237 if (NIL_P(length))
10238 st.copy_length = (off_t)-1;
10239 else
10240 st.copy_length = NUM2OFFT(length);
10241
10242 if (NIL_P(src_offset))
10243 st.src_offset = (off_t)-1;
10244 else
10245 st.src_offset = NUM2OFFT(src_offset);
10246
10247 rb_fd_init(&st.fds);
10248 rb_ensure(copy_stream_body, (VALUE)&st, copy_stream_finalize, (VALUE)&st);
10249
10250 return OFFT2NUM(st.total);
10251 }
10252
10253 /*
10254 * call-seq:
10255 * io.external_encoding -> encoding
10256 *
10257 * Returns the Encoding object that represents the encoding of the file.
10258 * If io is write mode and no encoding is specified, returns <code>nil</code>.
10259 */
10260
10261 static VALUE
10262 rb_io_external_encoding(VALUE io)
10263 {
10264 rb_io_t *fptr;
10265
10266 GetOpenFile(io, fptr);
10267 if (fptr->encs.enc2) {
10268 return rb_enc_from_encoding(fptr->encs.enc2);
10269 }
10270 if (fptr->mode & FMODE_WRITABLE) {
10271 if (fptr->encs.enc)
10272 return rb_enc_from_encoding(fptr->encs.enc);
10273 return Qnil;
10274 }
10275 return rb_enc_from_encoding(io_read_encoding(fptr));
10276 }
10277
10278 /*
10279 * call-seq:
10280 * io.internal_encoding -> encoding
10281 *
10282 * Returns the Encoding of the internal string if conversion is
10283 * specified. Otherwise returns nil.
10284 */
10285
10286 static VALUE
10287 rb_io_internal_encoding(VALUE io)
10288 {
10289 rb_io_t *fptr;
10290
10291 GetOpenFile(io, fptr);
10292 if (!fptr->encs.enc2) return Qnil;
10293 return rb_enc_from_encoding(io_read_encoding(fptr));
10294 }
10295
10296 /*
10297 * call-seq:
10298 * io.set_encoding(ext_enc) -> io
10299 * io.set_encoding("ext_enc:int_enc") -> io
10300 * io.set_encoding(ext_enc, int_enc) -> io
10301 * io.set_encoding("ext_enc:int_enc", opt) -> io
10302 * io.set_encoding(ext_enc, int_enc, opt) -> io
10303 *
10304 * If single argument is specified, read string from io is tagged
10305 * with the encoding specified. If encoding is a colon separated two
10306 * encoding names "A:B", the read string is converted from encoding A
10307 * (external encoding) to encoding B (internal encoding), then tagged
10308 * with B. If two arguments are specified, those must be encoding
10309 * objects or encoding names, and the first one is the external encoding, and the
10310 * second one is the internal encoding.
10311 * If the external encoding and the internal encoding is specified,
10312 * optional hash argument specify the conversion option.
10313 */
10314
10315 static VALUE
10316 rb_io_set_encoding(int argc, VALUE *argv, VALUE io)
10317 {
10318 rb_io_t *fptr;
10319 VALUE v1, v2, opt;
10320
10321 if (!RB_TYPE_P(io, T_FILE)) {
10322 return rb_funcall2(io, id_set_encoding, argc, argv);
10323 }
10324
10325 argc = rb_scan_args(argc, argv, "11:", &v1, &v2, &opt);
10326 GetOpenFile(io, fptr);
10327 io_encoding_set(fptr, v1, v2, opt);
10328 return io;
10329 }
10330
10331 void
10332 rb_stdio_set_default_encoding(void)
10333 {
10334 extern VALUE rb_stdin, rb_stdout, rb_stderr;
10335 VALUE val = Qnil;
10336
10337 rb_io_set_encoding(1, &val, rb_stdin);
10338 rb_io_set_encoding(1, &val, rb_stdout);
10339 rb_io_set_encoding(1, &val, rb_stderr);
10340 }
10341
10342 /*
10343 * call-seq:
10344 * ARGF.external_encoding -> encoding
10345 *
10346 * Returns the external encoding for files read from +ARGF+ as an +Encoding+
10347 * object. The external encoding is the encoding of the text as stored in a
10348 * file. Contrast with +ARGF.internal_encoding+, which is the encoding used
10349 * to represent this text within Ruby.
10350 *
10351 * To set the external encoding use +ARGF.set_encoding+.
10352 *
10353 * For example:
10354 *
10355 * ARGF.external_encoding #=> #<Encoding:UTF-8>
10356 *
10357 */
10358 static VALUE
10359 argf_external_encoding(VALUE argf)
10360 {
10361 if (!RTEST(ARGF.current_file)) {
10362 return rb_enc_from_encoding(rb_default_external_encoding());
10363 }
10364 return rb_io_external_encoding(rb_io_check_io(ARGF.current_file));
10365 }
10366
10367 /*
10368 * call-seq:
10369 * ARGF.internal_encoding -> encoding
10370 *
10371 * Returns the internal encoding for strings read from +ARGF+ as an
10372 * +Encoding+ object.
10373 *
10374 * If +ARGF.set_encoding+ has been called with two encoding names, the second
10375 * is returned. Otherwise, if +Encoding.default_external+ has been set, that
10376 * value is returned. Failing that, if a default external encoding was
10377 * specified on the command-line, that value is used. If the encoding is
10378 * unknown, nil is returned.
10379 */
10380 static VALUE
10381 argf_internal_encoding(VALUE argf)
10382 {
10383 if (!RTEST(ARGF.current_file)) {
10384 return rb_enc_from_encoding(rb_default_external_encoding());
10385 }
10386 return rb_io_internal_encoding(rb_io_check_io(ARGF.current_file));
10387 }
10388
10389 /*
10390 * call-seq:
10391 * ARGF.set_encoding(ext_enc) -> ARGF
10392 * ARGF.set_encoding("ext_enc:int_enc") -> ARGF
10393 * ARGF.set_encoding(ext_enc, int_enc) -> ARGF
10394 * ARGF.set_encoding("ext_enc:int_enc", opt) -> ARGF
10395 * ARGF.set_encoding(ext_enc, int_enc, opt) -> ARGF
10396 *
10397 * If single argument is specified, strings read from ARGF are tagged with
10398 * the encoding specified.
10399 *
10400 * If two encoding names separated by a colon are given, e.g. "ascii:utf-8",
10401 * the read string is converted from the first encoding (external encoding)
10402 * to the second encoding (internal encoding), then tagged with the second
10403 * encoding.
10404 *
10405 * If two arguments are specified, they must be encoding objects or encoding
10406 * names. Again, the first specifies the external encoding; the second
10407 * specifies the internal encoding.
10408 *
10409 * If the external encoding and the internal encoding are specified, the
10410 * optional +Hash+ argument can be used to adjust the conversion process. The
10411 * structure of this hash is explained in the +String#encode+ documentation.
10412 *
10413 * For example:
10414 *
10415 * ARGF.set_encoding('ascii') # Tag the input as US-ASCII text
10416 * ARGF.set_encoding(Encoding::UTF_8) # Tag the input as UTF-8 text
10417 * ARGF.set_encoding('utf-8','ascii') # Transcode the input from US-ASCII
10418 * # to UTF-8.
10419 */
10420 static VALUE
10421 argf_set_encoding(int argc, VALUE *argv, VALUE argf)
10422 {
10423 rb_io_t *fptr;
10424
10425 if (!next_argv()) {
10426 rb_raise(rb_eArgError, "no stream to set encoding");
10427 }
10428 rb_io_set_encoding(argc, argv, ARGF.current_file);
10429 GetOpenFile(ARGF.current_file, fptr);
10430 ARGF.encs = fptr->encs;
10431 return argf;
10432 }
10433
10434 /*
10435 * call-seq:
10436 * ARGF.tell -> Integer
10437 * ARGF.pos -> Integer
10438 *
10439 * Returns the current offset (in bytes) of the current file in +ARGF+.
10440 *
10441 * ARGF.pos #=> 0
10442 * ARGF.gets #=> "This is line one\n"
10443 * ARGF.pos #=> 17
10444 *
10445 */
10446 static VALUE
10447 argf_tell(VALUE argf)
10448 {
10449 if (!next_argv()) {
10450 rb_raise(rb_eArgError, "no stream to tell");
10451 }
10452 ARGF_FORWARD(0, 0);
10453 return rb_io_tell(ARGF.current_file);
10454 }
10455
10456 /*
10457 * call-seq:
10458 * ARGF.seek(amount, whence=IO::SEEK_SET) -> 0
10459 *
10460 * Seeks to offset _amount_ (an +Integer+) in the +ARGF+ stream according to
10461 * the value of _whence_. See +IO#seek+ for further details.
10462 */
10463 static VALUE
10464 argf_seek_m(int argc, VALUE *argv, VALUE argf)
10465 {
10466 if (!next_argv()) {
10467 rb_raise(rb_eArgError, "no stream to seek");
10468 }
10469 ARGF_FORWARD(argc, argv);
10470 return rb_io_seek_m(argc, argv, ARGF.current_file);
10471 }
10472
10473 /*
10474 * call-seq:
10475 * ARGF.pos = position -> Integer
10476 *
10477 * Seeks to the position given by _position_ (in bytes) in +ARGF+.
10478 *
10479 * For example:
10480 *
10481 * ARGF.pos = 17
10482 * ARGF.gets #=> "This is line two\n"
10483 */
10484 static VALUE
10485 argf_set_pos(VALUE argf, VALUE offset)
10486 {
10487 if (!next_argv()) {
10488 rb_raise(rb_eArgError, "no stream to set position");
10489 }
10490 ARGF_FORWARD(1, &offset);
10491 return rb_io_set_pos(ARGF.current_file, offset);
10492 }
10493
10494 /*
10495 * call-seq:
10496 * ARGF.rewind -> 0
10497 *
10498 * Positions the current file to the beginning of input, resetting
10499 * +ARGF.lineno+ to zero.
10500 *
10501 * ARGF.readline #=> "This is line one\n"
10502 * ARGF.rewind #=> 0
10503 * ARGF.lineno #=> 0
10504 * ARGF.readline #=> "This is line one\n"
10505 */
10506 static VALUE
10507 argf_rewind(VALUE argf)
10508 {
10509 if (!next_argv()) {
10510 rb_raise(rb_eArgError, "no stream to rewind");
10511 }
10512 ARGF_FORWARD(0, 0);
10513 return rb_io_rewind(ARGF.current_file);
10514 }
10515
10516 /*
10517 * call-seq:
10518 * ARGF.fileno -> fixnum
10519 * ARGF.to_i -> fixnum
10520 *
10521 * Returns an integer representing the numeric file descriptor for
10522 * the current file. Raises an +ArgumentError+ if there isn't a current file.
10523 *
10524 * ARGF.fileno #=> 3
10525 */
10526 static VALUE
10527 argf_fileno(VALUE argf)
10528 {
10529 if (!next_argv()) {
10530 rb_raise(rb_eArgError, "no stream");
10531 }
10532 ARGF_FORWARD(0, 0);
10533 return rb_io_fileno(ARGF.current_file);
10534 }
10535
10536 /*
10537 * call-seq:
10538 * ARGF.to_io -> IO
10539 *
10540 * Returns an +IO+ object representing the current file. This will be a
10541 * +File+ object unless the current file is a stream such as STDIN.
10542 *
10543 * For example:
10544 *
10545 * ARGF.to_io #=> #<File:glark.txt>
10546 * ARGF.to_io #=> #<IO:<STDIN>>
10547 */
10548 static VALUE
10549 argf_to_io(VALUE argf)
10550 {
10551 next_argv();
10552 ARGF_FORWARD(0, 0);
10553 return ARGF.current_file;
10554 }
10555
10556 /*
10557 * call-seq:
10558 * ARGF.eof? -> true or false
10559 * ARGF.eof -> true or false
10560 *
10561 * Returns true if the current file in +ARGF+ is at end of file, i.e. it has
10562 * no data to read. The stream must be opened for reading or an +IOError+
10563 * will be raised.
10564 *
10565 * $ echo "eof" | ruby argf.rb
10566 *
10567 * ARGF.eof? #=> false
10568 * 3.times { ARGF.readchar }
10569 * ARGF.eof? #=> false
10570 * ARGF.readchar #=> "\n"
10571 * ARGF.eof? #=> true
10572 */
10573
10574 static VALUE
10575 argf_eof(VALUE argf)
10576 {
10577 next_argv();
10578 if (RTEST(ARGF.current_file)) {
10579 if (ARGF.init_p == 0) return Qtrue;
10580 next_argv();
10581 ARGF_FORWARD(0, 0);
10582 if (rb_io_eof(ARGF.current_file)) {
10583 return Qtrue;
10584 }
10585 }
10586 return Qfalse;
10587 }
10588
10589 /*
10590 * call-seq:
10591 * ARGF.read([length [, outbuf]]) -> string, outbuf, or nil
10592 *
10593 * Reads _length_ bytes from ARGF. The files named on the command line
10594 * are concatenated and treated as a single file by this method, so when
10595 * called without arguments the contents of this pseudo file are returned in
10596 * their entirety.
10597 *
10598 * _length_ must be a non-negative integer or nil. If it is a positive
10599 * integer, +read+ tries to read at most _length_ bytes. It returns nil
10600 * if an EOF was encountered before anything could be read. Fewer than
10601 * _length_ bytes may be returned if an EOF is encountered during the read.
10602 *
10603 * If _length_ is omitted or is _nil_, it reads until EOF. A String is
10604 * returned even if EOF is encountered before any data is read.
10605 *
10606 * If _length_ is zero, it returns _""_.
10607 *
10608 * If the optional _outbuf_ argument is present, it must reference a String,
10609 * which will receive the data.
10610 * The <i>outbuf</i> will contain only the received data after the method call
10611 * even if it is not empty at the beginning.
10612 *
10613 * For example:
10614 *
10615 * $ echo "small" > small.txt
10616 * $ echo "large" > large.txt
10617 * $ ./glark.rb small.txt large.txt
10618 *
10619 * ARGF.read #=> "small\nlarge"
10620 * ARGF.read(200) #=> "small\nlarge"
10621 * ARGF.read(2) #=> "sm"
10622 * ARGF.read(0) #=> ""
10623 *
10624 * Note that this method behaves like fread() function in C. If you need the
10625 * behavior like read(2) system call, consider +ARGF.readpartial+.
10626 */
10627
10628 static VALUE
10629 argf_read(int argc, VALUE *argv, VALUE argf)
10630 {
10631 VALUE tmp, str, length;
10632 long len = 0;
10633
10634 rb_scan_args(argc, argv, "02", &length, &str);
10635 if (!NIL_P(length)) {
10636 len = NUM2LONG(argv[0]);
10637 }
10638 if (!NIL_P(str)) {
10639 StringValue(str);
10640 rb_str_resize(str,0);
10641 argv[1] = Qnil;
10642 }
10643
10644 retry:
10645 if (!next_argv()) {
10646 return str;
10647 }
10648 if (ARGF_GENERIC_INPUT_P()) {
10649 tmp = argf_forward(argc, argv, argf);
10650 }
10651 else {
10652 tmp = io_read(argc, argv, ARGF.current_file);
10653 }
10654 if (NIL_P(str)) str = tmp;
10655 else if (!NIL_P(tmp)) rb_str_append(str, tmp);
10656 if (NIL_P(tmp) || NIL_P(length)) {
10657 if (ARGF.next_p != -1) {
10658 argf_close(ARGF.current_file);
10659 ARGF.next_p = 1;
10660 goto retry;
10661 }
10662 }
10663 else if (argc >= 1) {
10664 if (RSTRING_LEN(str) < len) {
10665 len -= RSTRING_LEN(str);
10666 argv[0] = INT2NUM(len);
10667 goto retry;
10668 }
10669 }
10670 return str;
10671 }
10672
10673 struct argf_call_arg {
10674 int argc;
10675 VALUE *argv;
10676 VALUE argf;
10677 };
10678
10679 static VALUE
10680 argf_forward_call(VALUE arg)
10681 {
10682 struct argf_call_arg *p = (struct argf_call_arg *)arg;
10683 argf_forward(p->argc, p->argv, p->argf);
10684 return Qnil;
10685 }
10686
10687 static VALUE argf_getpartial(int argc, VALUE *argv, VALUE argf, int nonblock);
10688
10689 /*
10690 * call-seq:
10691 * ARGF.readpartial(maxlen) -> string
10692 * ARGF.readpartial(maxlen, outbuf) -> outbuf
10693 *
10694 * Reads at most _maxlen_ bytes from the ARGF stream. It blocks only if
10695 * +ARGF+ has no data immediately available. If the optional _outbuf_
10696 * argument is present, it must reference a String, which will receive the
10697 * data.
10698 * The <i>outbuf</i> will contain only the received data after the method call
10699 * even if it is not empty at the beginning.
10700 * It raises <code>EOFError</code> on end of file.
10701 *
10702 * +readpartial+ is designed for streams such as pipes, sockets, and ttys. It
10703 * blocks only when no data is immediately available. This means that it
10704 * blocks only when following all conditions hold:
10705 *
10706 * * The byte buffer in the +IO+ object is empty.
10707 * * The content of the stream is empty.
10708 * * The stream has not reached EOF.
10709 *
10710 * When +readpartial+ blocks, it waits for data or EOF. If some data is read,
10711 * +readpartial+ returns with the data. If EOF is reached, readpartial raises
10712 * an +EOFError+.
10713 *
10714 * When +readpartial+ doesn't block, it returns or raises immediately. If
10715 * the byte buffer is not empty, it returns the data in the buffer. Otherwise, if
10716 * the stream has some content, it returns the data in the stream. If the
10717 * stream reaches EOF an +EOFError+ is raised.
10718 */
10719
10720 static VALUE
10721 argf_readpartial(int argc, VALUE *argv, VALUE argf)
10722 {
10723 return argf_getpartial(argc, argv, argf, 0);
10724 }
10725
10726 /*
10727 * call-seq:
10728 * ARGF.read_nonblock(maxlen) -> string
10729 * ARGF.read_nonblock(maxlen, outbuf) -> outbuf
10730 *
10731 * Reads at most _maxlen_ bytes from the ARGF stream in non-blocking mode.
10732 */
10733
10734 static VALUE
10735 argf_read_nonblock(int argc, VALUE *argv, VALUE argf)
10736 {
10737 return argf_getpartial(argc, argv, argf, 1);
10738 }
10739
10740 static VALUE
10741 argf_getpartial(int argc, VALUE *argv, VALUE argf, int nonblock)
10742 {
10743 VALUE tmp, str, length;
10744
10745 rb_scan_args(argc, argv, "11", &length, &str);
10746 if (!NIL_P(str)) {
10747 StringValue(str);
10748 argv[1] = str;
10749 }
10750
10751 if (!next_argv()) {
10752 rb_str_resize(str, 0);
10753 rb_eof_error();
10754 }
10755 if (ARGF_GENERIC_INPUT_P()) {
10756 struct argf_call_arg arg;
10757 arg.argc = argc;
10758 arg.argv = argv;
10759 arg.argf = argf;
10760 tmp = rb_rescue2(argf_forward_call, (VALUE)&arg,
10761 RUBY_METHOD_FUNC(0), Qnil, rb_eEOFError, (VALUE)0);
10762 }
10763 else {
10764 tmp = io_getpartial(argc, argv, ARGF.current_file, nonblock);
10765 }
10766 if (NIL_P(tmp)) {
10767 if (ARGF.next_p == -1) {
10768 rb_eof_error();
10769 }
10770 argf_close(ARGF.current_file);
10771 ARGF.next_p = 1;
10772 if (RARRAY_LEN(ARGF.argv) == 0)
10773 rb_eof_error();
10774 if (NIL_P(str))
10775 str = rb_str_new(NULL, 0);
10776 return str;
10777 }
10778 return tmp;
10779 }
10780
10781 /*
10782 * call-seq:
10783 * ARGF.getc -> String or nil
10784 *
10785 * Reads the next character from +ARGF+ and returns it as a +String+. Returns
10786 * +nil+ at the end of the stream.
10787 *
10788 * +ARGF+ treats the files named on the command line as a single file created
10789 * by concatenating their contents. After returning the last character of the
10790 * first file, it returns the first character of the second file, and so on.
10791 *
10792 * For example:
10793 *
10794 * $ echo "foo" > file
10795 * $ ruby argf.rb file
10796 *
10797 * ARGF.getc #=> "f"
10798 * ARGF.getc #=> "o"
10799 * ARGF.getc #=> "o"
10800 * ARGF.getc #=> "\n"
10801 * ARGF.getc #=> nil
10802 * ARGF.getc #=> nil
10803 */
10804 static VALUE
10805 argf_getc(VALUE argf)
10806 {
10807 VALUE ch;
10808
10809 retry:
10810 if (!next_argv()) return Qnil;
10811 if (ARGF_GENERIC_INPUT_P()) {
10812 ch = rb_funcall3(ARGF.current_file, rb_intern("getc"), 0, 0);
10813 }
10814 else {
10815 ch = rb_io_getc(ARGF.current_file);
10816 }
10817 if (NIL_P(ch) && ARGF.next_p != -1) {
10818 argf_close(ARGF.current_file);
10819 ARGF.next_p = 1;
10820 goto retry;
10821 }
10822
10823 return ch;
10824 }
10825
10826 /*
10827 * call-seq:
10828 * ARGF.getbyte -> Fixnum or nil
10829 *
10830 * Gets the next 8-bit byte (0..255) from +ARGF+. Returns +nil+ if called at
10831 * the end of the stream.
10832 *
10833 * For example:
10834 *
10835 * $ echo "foo" > file
10836 * $ ruby argf.rb file
10837 *
10838 * ARGF.getbyte #=> 102
10839 * ARGF.getbyte #=> 111
10840 * ARGF.getbyte #=> 111
10841 * ARGF.getbyte #=> 10
10842 * ARGF.getbyte #=> nil
10843 */
10844 static VALUE
10845 argf_getbyte(VALUE argf)
10846 {
10847 VALUE ch;
10848
10849 retry:
10850 if (!next_argv()) return Qnil;
10851 if (!RB_TYPE_P(ARGF.current_file, T_FILE)) {
10852 ch = rb_funcall3(ARGF.current_file, rb_intern("getbyte"), 0, 0);
10853 }
10854 else {
10855 ch = rb_io_getbyte(ARGF.current_file);
10856 }
10857 if (NIL_P(ch) && ARGF.next_p != -1) {
10858 argf_close(ARGF.current_file);
10859 ARGF.next_p = 1;
10860 goto retry;
10861 }
10862
10863 return ch;
10864 }
10865
10866 /*
10867 * call-seq:
10868 * ARGF.readchar -> String or nil
10869 *
10870 * Reads the next character from +ARGF+ and returns it as a +String+. Raises
10871 * an +EOFError+ after the last character of the last file has been read.
10872 *
10873 * For example:
10874 *
10875 * $ echo "foo" > file
10876 * $ ruby argf.rb file
10877 *
10878 * ARGF.readchar #=> "f"
10879 * ARGF.readchar #=> "o"
10880 * ARGF.readchar #=> "o"
10881 * ARGF.readchar #=> "\n"
10882 * ARGF.readchar #=> end of file reached (EOFError)
10883 */
10884 static VALUE
10885 argf_readchar(VALUE argf)
10886 {
10887 VALUE ch;
10888
10889 retry:
10890 if (!next_argv()) rb_eof_error();
10891 if (!RB_TYPE_P(ARGF.current_file, T_FILE)) {
10892 ch = rb_funcall3(ARGF.current_file, rb_intern("getc"), 0, 0);
10893 }
10894 else {
10895 ch = rb_io_getc(ARGF.current_file);
10896 }
10897 if (NIL_P(ch) && ARGF.next_p != -1) {
10898 argf_close(ARGF.current_file);
10899 ARGF.next_p = 1;
10900 goto retry;
10901 }
10902
10903 return ch;
10904 }
10905
10906 /*
10907 * call-seq:
10908 * ARGF.readbyte -> Fixnum
10909 *
10910 * Reads the next 8-bit byte from ARGF and returns it as a +Fixnum+. Raises
10911 * an +EOFError+ after the last byte of the last file has been read.
10912 *
10913 * For example:
10914 *
10915 * $ echo "foo" > file
10916 * $ ruby argf.rb file
10917 *
10918 * ARGF.readbyte #=> 102
10919 * ARGF.readbyte #=> 111
10920 * ARGF.readbyte #=> 111
10921 * ARGF.readbyte #=> 10
10922 * ARGF.readbyte #=> end of file reached (EOFError)
10923 */
10924 static VALUE
10925 argf_readbyte(VALUE argf)
10926 {
10927 VALUE c;
10928
10929 NEXT_ARGF_FORWARD(0, 0);
10930 c = argf_getbyte(argf);
10931 if (NIL_P(c)) {
10932 rb_eof_error();
10933 }
10934 return c;
10935 }
10936
10937 /*
10938 * call-seq:
10939 * ARGF.each(sep=$/) {|line| block } -> ARGF
10940 * ARGF.each(sep=$/,limit) {|line| block } -> ARGF
10941 * ARGF.each(...) -> an_enumerator
10942 *
10943 * ARGF.each_line(sep=$/) {|line| block } -> ARGF
10944 * ARGF.each_line(sep=$/,limit) {|line| block } -> ARGF
10945 * ARGF.each_line(...) -> an_enumerator
10946 *
10947 * Returns an enumerator which iterates over each line (separated by _sep_,
10948 * which defaults to your platform's newline character) of each file in
10949 * +ARGV+. If a block is supplied, each line in turn will be yielded to the
10950 * block, otherwise an enumerator is returned.
10951 * The optional _limit_ argument is a +Fixnum+ specifying the maximum
10952 * length of each line; longer lines will be split according to this limit.
10953 *
10954 * This method allows you to treat the files supplied on the command line as
10955 * a single file consisting of the concatenation of each named file. After
10956 * the last line of the first file has been returned, the first line of the
10957 * second file is returned. The +ARGF.filename+ and +ARGF.lineno+ methods can
10958 * be used to determine the filename and line number, respectively, of the
10959 * current line.
10960 *
10961 * For example, the following code prints out each line of each named file
10962 * prefixed with its line number, displaying the filename once per file:
10963 *
10964 * ARGF.lines do |line|
10965 * puts ARGF.filename if ARGF.lineno == 1
10966 * puts "#{ARGF.lineno}: #{line}"
10967 * end
10968 */
10969 static VALUE
10970 argf_each_line(int argc, VALUE *argv, VALUE argf)
10971 {
10972 RETURN_ENUMERATOR(argf, argc, argv);
10973 for (;;) {
10974 if (!next_argv()) return argf;
10975 rb_block_call(ARGF.current_file, rb_intern("each_line"), argc, argv, 0, 0);
10976 ARGF.next_p = 1;
10977 }
10978 }
10979
10980 /*
10981 * This is a deprecated alias for <code>each_line</code>.
10982 */
10983
10984 static VALUE
10985 argf_lines(int argc, VALUE *argv, VALUE argf)
10986 {
10987 rb_warn("ARGF#lines is deprecated; use #each_line instead");
10988 if (!rb_block_given_p())
10989 return rb_enumeratorize(argf, ID2SYM(rb_intern("each_line")), argc, argv);
10990 return argf_each_line(argc, argv, argf);
10991 }
10992
10993 /*
10994 * call-seq:
10995 * ARGF.bytes {|byte| block } -> ARGF
10996 * ARGF.bytes -> an_enumerator
10997 *
10998 * ARGF.each_byte {|byte| block } -> ARGF
10999 * ARGF.each_byte -> an_enumerator
11000 *
11001 * Iterates over each byte of each file in +ARGV+.
11002 * A byte is returned as a +Fixnum+ in the range 0..255.
11003 *
11004 * This method allows you to treat the files supplied on the command line as
11005 * a single file consisting of the concatenation of each named file. After
11006 * the last byte of the first file has been returned, the first byte of the
11007 * second file is returned. The +ARGF.filename+ method can be used to
11008 * determine the filename of the current byte.
11009 *
11010 * If no block is given, an enumerator is returned instead.
11011 *
11012 * For example:
11013 *
11014 * ARGF.bytes.to_a #=> [35, 32, ... 95, 10]
11015 *
11016 */
11017 static VALUE
11018 argf_each_byte(VALUE argf)
11019 {
11020 RETURN_ENUMERATOR(argf, 0, 0);
11021 for (;;) {
11022 if (!next_argv()) return argf;
11023 rb_block_call(ARGF.current_file, rb_intern("each_byte"), 0, 0, 0, 0);
11024 ARGF.next_p = 1;
11025 }
11026 }
11027
11028 /*
11029 * This is a deprecated alias for <code>each_byte</code>.
11030 */
11031
11032 static VALUE
11033 argf_bytes(VALUE argf)
11034 {
11035 rb_warn("ARGF#bytes is deprecated; use #each_byte instead");
11036 if (!rb_block_given_p())
11037 return rb_enumeratorize(argf, ID2SYM(rb_intern("each_byte")), 0, 0);
11038 return argf_each_byte(argf);
11039 }
11040
11041 /*
11042 * call-seq:
11043 * ARGF.each_char {|char| block } -> ARGF
11044 * ARGF.each_char -> an_enumerator
11045 *
11046 * Iterates over each character of each file in +ARGF+.
11047 *
11048 * This method allows you to treat the files supplied on the command line as
11049 * a single file consisting of the concatenation of each named file. After
11050 * the last character of the first file has been returned, the first
11051 * character of the second file is returned. The +ARGF.filename+ method can
11052 * be used to determine the name of the file in which the current character
11053 * appears.
11054 *
11055 * If no block is given, an enumerator is returned instead.
11056 */
11057 static VALUE
11058 argf_each_char(VALUE argf)
11059 {
11060 RETURN_ENUMERATOR(argf, 0, 0);
11061 for (;;) {
11062 if (!next_argv()) return argf;
11063 rb_block_call(ARGF.current_file, rb_intern("each_char"), 0, 0, 0, 0);
11064 ARGF.next_p = 1;
11065 }
11066 }
11067
11068 /*
11069 * This is a deprecated alias for <code>each_char</code>.
11070 */
11071
11072 static VALUE
11073 argf_chars(VALUE argf)
11074 {
11075 rb_warn("ARGF#chars is deprecated; use #each_char instead");
11076 if (!rb_block_given_p())
11077 return rb_enumeratorize(argf, ID2SYM(rb_intern("each_char")), 0, 0);
11078 return argf_each_char(argf);
11079 }
11080
11081 /*
11082 * call-seq:
11083 * ARGF.each_codepoint {|codepoint| block } -> ARGF
11084 * ARGF.each_codepoint -> an_enumerator
11085 *
11086 * Iterates over each codepoint of each file in +ARGF+.
11087 *
11088 * This method allows you to treat the files supplied on the command line as
11089 * a single file consisting of the concatenation of each named file. After
11090 * the last codepoint of the first file has been returned, the first
11091 * codepoint of the second file is returned. The +ARGF.filename+ method can
11092 * be used to determine the name of the file in which the current codepoint
11093 * appears.
11094 *
11095 * If no block is given, an enumerator is returned instead.
11096 */
11097 static VALUE
11098 argf_each_codepoint(VALUE argf)
11099 {
11100 RETURN_ENUMERATOR(argf, 0, 0);
11101 for (;;) {
11102 if (!next_argv()) return argf;
11103 rb_block_call(ARGF.current_file, rb_intern("each_codepoint"), 0, 0, 0, 0);
11104 ARGF.next_p = 1;
11105 }
11106 }
11107
11108 /*
11109 * This is a deprecated alias for <code>each_codepoint</code>.
11110 */
11111
11112 static VALUE
11113 argf_codepoints(VALUE argf)
11114 {
11115 rb_warn("ARGF#codepoints is deprecated; use #each_codepoint instead");
11116 if (!rb_block_given_p())
11117 return rb_enumeratorize(argf, ID2SYM(rb_intern("each_codepoint")), 0, 0);
11118 return argf_each_codepoint(argf);
11119 }
11120
11121 /*
11122 * call-seq:
11123 * ARGF.filename -> String
11124 * ARGF.path -> String
11125 *
11126 * Returns the current filename. "-" is returned when the current file is
11127 * STDIN.
11128 *
11129 * For example:
11130 *
11131 * $ echo "foo" > foo
11132 * $ echo "bar" > bar
11133 * $ echo "glark" > glark
11134 *
11135 * $ ruby argf.rb foo bar glark
11136 *
11137 * ARGF.filename #=> "foo"
11138 * ARGF.read(5) #=> "foo\nb"
11139 * ARGF.filename #=> "bar"
11140 * ARGF.skip
11141 * ARGF.filename #=> "glark"
11142 */
11143 static VALUE
11144 argf_filename(VALUE argf)
11145 {
11146 next_argv();
11147 return ARGF.filename;
11148 }
11149
11150 static VALUE
11151 argf_filename_getter(ID id, VALUE *var)
11152 {
11153 return argf_filename(*var);
11154 }
11155
11156 /*
11157 * call-seq:
11158 * ARGF.file -> IO or File object
11159 *
11160 * Returns the current file as an +IO+ or +File+ object. #<IO:<STDIN>> is
11161 * returned when the current file is STDIN.
11162 *
11163 * For example:
11164 *
11165 * $ echo "foo" > foo
11166 * $ echo "bar" > bar
11167 *
11168 * $ ruby argf.rb foo bar
11169 *
11170 * ARGF.file #=> #<File:foo>
11171 * ARGF.read(5) #=> "foo\nb"
11172 * ARGF.file #=> #<File:bar>
11173 */
11174 static VALUE
11175 argf_file(VALUE argf)
11176 {
11177 next_argv();
11178 return ARGF.current_file;
11179 }
11180
11181 /*
11182 * call-seq:
11183 * ARGF.binmode -> ARGF
11184 *
11185 * Puts +ARGF+ into binary mode. Once a stream is in binary mode, it cannot
11186 * be reset to non-binary mode. This option has the following effects:
11187 *
11188 * * Newline conversion is disabled.
11189 * * Encoding conversion is disabled.
11190 * * Content is treated as ASCII-8BIT.
11191 */
11192 static VALUE
11193 argf_binmode_m(VALUE argf)
11194 {
11195 ARGF.binmode = 1;
11196 next_argv();
11197 ARGF_FORWARD(0, 0);
11198 rb_io_ascii8bit_binmode(ARGF.current_file);
11199 return argf;
11200 }
11201
11202 /*
11203 * call-seq:
11204 * ARGF.binmode? -> true or false
11205 *
11206 * Returns true if +ARGF+ is being read in binary mode; false otherwise. (To
11207 * enable binary mode use +ARGF.binmode+.
11208 *
11209 * For example:
11210 *
11211 * ARGF.binmode? #=> false
11212 * ARGF.binmode
11213 * ARGF.binmode? #=> true
11214 */
11215 static VALUE
11216 argf_binmode_p(VALUE argf)
11217 {
11218 return ARGF.binmode ? Qtrue : Qfalse;
11219 }
11220
11221 /*
11222 * call-seq:
11223 * ARGF.skip -> ARGF
11224 *
11225 * Sets the current file to the next file in ARGV. If there aren't any more
11226 * files it has no effect.
11227 *
11228 * For example:
11229 *
11230 * $ ruby argf.rb foo bar
11231 * ARGF.filename #=> "foo"
11232 * ARGF.skip
11233 * ARGF.filename #=> "bar"
11234 */
11235 static VALUE
11236 argf_skip(VALUE argf)
11237 {
11238 if (ARGF.init_p && ARGF.next_p == 0) {
11239 argf_close(ARGF.current_file);
11240 ARGF.next_p = 1;
11241 }
11242 return argf;
11243 }
11244
11245 /*
11246 * call-seq:
11247 * ARGF.close -> ARGF
11248 *
11249 * Closes the current file and skips to the next in the stream. Trying to
11250 * close a file that has already been closed causes an +IOError+ to be
11251 * raised.
11252 *
11253 * For example:
11254 *
11255 * $ ruby argf.rb foo bar
11256 *
11257 * ARGF.filename #=> "foo"
11258 * ARGF.close
11259 * ARGF.filename #=> "bar"
11260 * ARGF.close
11261 * ARGF.close #=> closed stream (IOError)
11262 */
11263 static VALUE
11264 argf_close_m(VALUE argf)
11265 {
11266 next_argv();
11267 argf_close(ARGF.current_file);
11268 if (ARGF.next_p != -1) {
11269 ARGF.next_p = 1;
11270 }
11271 ARGF.lineno = 0;
11272 return argf;
11273 }
11274
11275 /*
11276 * call-seq:
11277 * ARGF.closed? -> true or false
11278 *
11279 * Returns _true_ if the current file has been closed; _false_ otherwise. Use
11280 * +ARGF.close+ to actually close the current file.
11281 */
11282 static VALUE
11283 argf_closed(VALUE argf)
11284 {
11285 next_argv();
11286 ARGF_FORWARD(0, 0);
11287 return rb_io_closed(ARGF.current_file);
11288 }
11289
11290 /*
11291 * call-seq:
11292 * ARGF.to_s -> String
11293 *
11294 * Returns "ARGF".
11295 */
11296 static VALUE
11297 argf_to_s(VALUE argf)
11298 {
11299 return rb_str_new2("ARGF");
11300 }
11301
11302 /*
11303 * call-seq:
11304 * ARGF.inplace_mode -> String
11305 *
11306 * Returns the file extension appended to the names of modified files under
11307 * inplace-edit mode. This value can be set using +ARGF.inplace_mode=+ or
11308 * passing the +-i+ switch to the Ruby binary.
11309 */
11310 static VALUE
11311 argf_inplace_mode_get(VALUE argf)
11312 {
11313 if (!ARGF.inplace) return Qnil;
11314 return rb_str_new2(ARGF.inplace);
11315 }
11316
11317 static VALUE
11318 opt_i_get(ID id, VALUE *var)
11319 {
11320 return argf_inplace_mode_get(*var);
11321 }
11322
11323 /*
11324 * call-seq:
11325 * ARGF.inplace_mode = ext -> ARGF
11326 *
11327 * Sets the filename extension for inplace editing mode to the given String.
11328 * Each file being edited has this value appended to its filename. The
11329 * modified file is saved under this new name.
11330 *
11331 * For example:
11332 *
11333 * $ ruby argf.rb file.txt
11334 *
11335 * ARGF.inplace_mode = '.bak'
11336 * ARGF.lines do |line|
11337 * print line.sub("foo","bar")
11338 * end
11339 *
11340 * Each line of _file.txt_ has the first occurrence of "foo" replaced with
11341 * "bar", then the new line is written out to _file.txt.bak_.
11342 */
11343 static VALUE
11344 argf_inplace_mode_set(VALUE argf, VALUE val)
11345 {
11346 if (rb_safe_level() >= 1 && OBJ_TAINTED(val))
11347 rb_insecure_operation();
11348
11349 if (!RTEST(val)) {
11350 if (ARGF.inplace) free(ARGF.inplace);
11351 ARGF.inplace = 0;
11352 }
11353 else {
11354 StringValue(val);
11355 if (ARGF.inplace) free(ARGF.inplace);
11356 ARGF.inplace = 0;
11357 ARGF.inplace = strdup(RSTRING_PTR(val));
11358 }
11359 return argf;
11360 }
11361
11362 static void
11363 opt_i_set(VALUE val, ID id, VALUE *var)
11364 {
11365 argf_inplace_mode_set(*var, val);
11366 }
11367
11368 const char *
11369 ruby_get_inplace_mode(void)
11370 {
11371 return ARGF.inplace;
11372 }
11373
11374 void
11375 ruby_set_inplace_mode(const char *suffix)
11376 {
11377 if (ARGF.inplace) free(ARGF.inplace);
11378 ARGF.inplace = 0;
11379 if (suffix) ARGF.inplace = strdup(suffix);
11380 }
11381
11382 /*
11383 * call-seq:
11384 * ARGF.argv -> ARGV
11385 *
11386 * Returns the +ARGV+ array, which contains the arguments passed to your
11387 * script, one per element.
11388 *
11389 * For example:
11390 *
11391 * $ ruby argf.rb -v glark.txt
11392 *
11393 * ARGF.argv #=> ["-v", "glark.txt"]
11394 *
11395 */
11396 static VALUE
11397 argf_argv(VALUE argf)
11398 {
11399 return ARGF.argv;
11400 }
11401
11402 static VALUE
11403 argf_argv_getter(ID id, VALUE *var)
11404 {
11405 return argf_argv(*var);
11406 }
11407
11408 VALUE
11409 rb_get_argv(void)
11410 {
11411 return ARGF.argv;
11412 }
11413
11414 /*
11415 * call-seq:
11416 * ARGF.to_write_io -> io
11417 *
11418 * Returns IO instance tied to _ARGF_ for writing if inplace mode is
11419 * enabled.
11420 */
11421 static VALUE
11422 argf_write_io(VALUE argf)
11423 {
11424 if (!RTEST(ARGF.current_file)) {
11425 rb_raise(rb_eIOError, "not opened for writing");
11426 }
11427 return GetWriteIO(ARGF.current_file);
11428 }
11429
11430 /*
11431 * call-seq:
11432 * ARGF.write(string) -> integer
11433 *
11434 * Writes _string_ if inplace mode.
11435 */
11436 static VALUE
11437 argf_write(VALUE argf, VALUE str)
11438 {
11439 return rb_io_write(argf_write_io(argf), str);
11440 }
11441
11442 /*
11443 * Document-class: IOError
11444 *
11445 * Raised when an IO operation fails.
11446 *
11447 * File.open("/etc/hosts") {|f| f << "example"}
11448 * #=> IOError: not opened for writing
11449 *
11450 * File.open("/etc/hosts") {|f| f.close; f.read }
11451 * #=> IOError: closed stream
11452 *
11453 * Note that some IO failures raise +SystemCallError+s and these are not
11454 * subclasses of IOError:
11455 *
11456 * File.open("does/not/exist")
11457 * #=> Errno::ENOENT: No such file or directory - does/not/exist
11458 */
11459
11460 /*
11461 * Document-class: EOFError
11462 *
11463 * Raised by some IO operations when reaching the end of file. Many IO
11464 * methods exist in two forms,
11465 *
11466 * one that returns +nil+ when the end of file is reached, the other
11467 * raises EOFError +EOFError+.
11468 *
11469 * +EOFError+ is a subclass of +IOError+.
11470 *
11471 * file = File.open("/etc/hosts")
11472 * file.read
11473 * file.gets #=> nil
11474 * file.readline #=> EOFError: end of file reached
11475 */
11476
11477 /*
11478 * Document-class: ARGF
11479 *
11480 * +ARGF+ is a stream designed for use in scripts that process files given as
11481 * command-line arguments or passed in via STDIN.
11482 *
11483 * The arguments passed to your script are stored in the +ARGV+ Array, one
11484 * argument per element. +ARGF+ assumes that any arguments that aren't
11485 * filenames have been removed from +ARGV+. For example:
11486 *
11487 * $ ruby argf.rb --verbose file1 file2
11488 *
11489 * ARGV #=> ["--verbose", "file1", "file2"]
11490 * option = ARGV.shift #=> "--verbose"
11491 * ARGV #=> ["file1", "file2"]
11492 *
11493 * You can now use +ARGF+ to work with a concatenation of each of these named
11494 * files. For instance, +ARGF.read+ will return the contents of _file1_
11495 * followed by the contents of _file2_.
11496 *
11497 * After a file in +ARGV+ has been read +ARGF+ removes it from the Array.
11498 * Thus, after all files have been read +ARGV+ will be empty.
11499 *
11500 * You can manipulate +ARGV+ yourself to control what +ARGF+ operates on. If
11501 * you remove a file from +ARGV+, it is ignored by +ARGF+; if you add files to
11502 * +ARGV+, they are treated as if they were named on the command line. For
11503 * example:
11504 *
11505 * ARGV.replace ["file1"]
11506 * ARGF.readlines # Returns the contents of file1 as an Array
11507 * ARGV #=> []
11508 * ARGV.replace ["file2", "file3"]
11509 * ARGF.read # Returns the contents of file2 and file3
11510 *
11511 * If +ARGV+ is empty, +ARGF+ acts as if it contained STDIN, i.e. the data
11512 * piped to your script. For example:
11513 *
11514 * $ echo "glark" | ruby -e 'p ARGF.read'
11515 * "glark\n"
11516 */
11517
11518 /*
11519 * The IO class is the basis for all input and output in Ruby.
11520 * An I/O stream may be <em>duplexed</em> (that is, bidirectional), and
11521 * so may use more than one native operating system stream.
11522 *
11523 * Many of the examples in this section use the File class, the only standard
11524 * subclass of IO. The two classes are closely associated. Like the File
11525 * class, the Socket library subclasses from IO (such as TCPSocket or
11526 * UDPSocket).
11527 *
11528 * The Kernel#open method can create an IO (or File) object for these types
11529 * of arguments:
11530 *
11531 * * A plain string represents a filename suitable for the underlying
11532 * operating system.
11533 *
11534 * * A string starting with <code>"|"</code> indicates a subprocess.
11535 * The remainder of the string following the <code>"|"</code> is
11536 * invoked as a process with appropriate input/output channels
11537 * connected to it.
11538 *
11539 * * A string equal to <code>"|-"</code> will create another Ruby
11540 * instance as a subprocess.
11541 *
11542 * The IO may be opened with different file modes (read-only, write-only) and
11543 * encodings for proper conversion. See IO.new for these options. See
11544 * Kernel#open for details of the various command formats described above.
11545 *
11546 * IO.popen, the Open3 library, or Process#spawn may also be used to
11547 * communicate with subprocesses through an IO.
11548 *
11549 * Ruby will convert pathnames between different operating system
11550 * conventions if possible. For instance, on a Windows system the
11551 * filename <code>"/gumby/ruby/test.rb"</code> will be opened as
11552 * <code>"\gumby\ruby\test.rb"</code>. When specifying a Windows-style
11553 * filename in a Ruby string, remember to escape the backslashes:
11554 *
11555 * "c:\\gumby\\ruby\\test.rb"
11556 *
11557 * Our examples here will use the Unix-style forward slashes;
11558 * File::ALT_SEPARATOR can be used to get the platform-specific separator
11559 * character.
11560 *
11561 * The global constant ARGF (also accessible as $<) provides an
11562 * IO-like stream which allows access to all files mentioned on the
11563 * command line (or STDIN if no files are mentioned). ARGF#path and its alias
11564 * ARGF#filename are provided to access the name of the file currently being
11565 * read.
11566 *
11567 * == io/console
11568 *
11569 * The io/console extension provides methods for interacting with the
11570 * console. The console can be accessed from IO.console or the standard
11571 * input/output/error IO objects.
11572 *
11573 * Requiring io/console adds the following methods:
11574 *
11575 * * IO::console
11576 * * IO#raw
11577 * * IO#raw!
11578 * * IO#cooked
11579 * * IO#cooked!
11580 * * IO#getch
11581 * * IO#echo=
11582 * * IO#echo?
11583 * * IO#noecho
11584 * * IO#winsize
11585 * * IO#winsize=
11586 * * IO#iflush
11587 * * IO#ioflush
11588 * * IO#oflush
11589 *
11590 * Example:
11591 *
11592 * require 'io/console'
11593 * rows, columns = $stdin.winsize
11594 * puts "Your screen is #{columns} wide and #{rows} tall"
11595 */
11596
11597 void
11598 Init_IO(void)
11599 {
11600 #undef rb_intern
11601 #define rb_intern(str) rb_intern_const(str)
11602
11603 VALUE rb_cARGF;
11604 #ifdef __CYGWIN__
11605 #include <sys/cygwin.h>
11606 static struct __cygwin_perfile pf[] =
11607 {
11608 {"", O_RDONLY | O_BINARY},
11609 {"", O_WRONLY | O_BINARY},
11610 {"", O_RDWR | O_BINARY},
11611 {"", O_APPEND | O_BINARY},
11612 {NULL, 0}
11613 };
11614 cygwin_internal(CW_PERFILE, pf);
11615 #endif
11616
11617 rb_eIOError = rb_define_class("IOError", rb_eStandardError);
11618 rb_eEOFError = rb_define_class("EOFError", rb_eIOError);
11619
11620 id_write = rb_intern("write");
11621 id_read = rb_intern("read");
11622 id_getc = rb_intern("getc");
11623 id_flush = rb_intern("flush");
11624 id_readpartial = rb_intern("readpartial");
11625 id_set_encoding = rb_intern("set_encoding");
11626
11627 rb_define_global_function("syscall", rb_f_syscall, -1);
11628
11629 rb_define_global_function("open", rb_f_open, -1);
11630 rb_define_global_function("printf", rb_f_printf, -1);
11631 rb_define_global_function("print", rb_f_print, -1);
11632 rb_define_global_function("putc", rb_f_putc, 1);
11633 rb_define_global_function("puts", rb_f_puts, -1);
11634 rb_define_global_function("gets", rb_f_gets, -1);
11635 rb_define_global_function("readline", rb_f_readline, -1);
11636 rb_define_global_function("select", rb_f_select, -1);
11637
11638 rb_define_global_function("readlines", rb_f_readlines, -1);
11639
11640 rb_define_global_function("`", rb_f_backquote, 1);
11641
11642 rb_define_global_function("p", rb_f_p, -1);
11643 rb_define_method(rb_mKernel, "display", rb_obj_display, -1);
11644
11645 rb_cIO = rb_define_class("IO", rb_cObject);
11646 rb_include_module(rb_cIO, rb_mEnumerable);
11647
11648 rb_mWaitReadable = rb_define_module_under(rb_cIO, "WaitReadable");
11649 rb_mWaitWritable = rb_define_module_under(rb_cIO, "WaitWritable");
11650
11651 #if 0
11652 /* This is necessary only for forcing rdoc handle File::open */
11653 rb_define_singleton_method(rb_cFile, "open", rb_io_s_open, -1);
11654 #endif
11655
11656 rb_define_alloc_func(rb_cIO, io_alloc);
11657 rb_define_singleton_method(rb_cIO, "new", rb_io_s_new, -1);
11658 rb_define_singleton_method(rb_cIO, "open", rb_io_s_open, -1);
11659 rb_define_singleton_method(rb_cIO, "sysopen", rb_io_s_sysopen, -1);
11660 rb_define_singleton_method(rb_cIO, "for_fd", rb_io_s_for_fd, -1);
11661 rb_define_singleton_method(rb_cIO, "popen", rb_io_s_popen, -1);
11662 rb_define_singleton_method(rb_cIO, "foreach", rb_io_s_foreach, -1);
11663 rb_define_singleton_method(rb_cIO, "readlines", rb_io_s_readlines, -1);
11664 rb_define_singleton_method(rb_cIO, "read", rb_io_s_read, -1);
11665 rb_define_singleton_method(rb_cIO, "binread", rb_io_s_binread, -1);
11666 rb_define_singleton_method(rb_cIO, "write", rb_io_s_write, -1);
11667 rb_define_singleton_method(rb_cIO, "binwrite", rb_io_s_binwrite, -1);
11668 rb_define_singleton_method(rb_cIO, "select", rb_f_select, -1);
11669 rb_define_singleton_method(rb_cIO, "pipe", rb_io_s_pipe, -1);
11670 rb_define_singleton_method(rb_cIO, "try_convert", rb_io_s_try_convert, 1);
11671 rb_define_singleton_method(rb_cIO, "copy_stream", rb_io_s_copy_stream, -1);
11672
11673 rb_define_method(rb_cIO, "initialize", rb_io_initialize, -1);
11674
11675 rb_output_fs = Qnil;
11676 rb_define_hooked_variable("$,", &rb_output_fs, 0, rb_str_setter);
11677
11678 rb_rs = rb_default_rs = rb_usascii_str_new2("\n");
11679 rb_gc_register_mark_object(rb_default_rs);
11680 rb_output_rs = Qnil;
11681 OBJ_FREEZE(rb_default_rs); /* avoid modifying RS_default */
11682 rb_define_hooked_variable("$/", &rb_rs, 0, rb_str_setter);
11683 rb_define_hooked_variable("$-0", &rb_rs, 0, rb_str_setter);
11684 rb_define_hooked_variable("$\\", &rb_output_rs, 0, rb_str_setter);
11685
11686 rb_define_virtual_variable("$_", rb_lastline_get, rb_lastline_set);
11687
11688 rb_define_method(rb_cIO, "initialize_copy", rb_io_init_copy, 1);
11689 rb_define_method(rb_cIO, "reopen", rb_io_reopen, -1);
11690
11691 rb_define_method(rb_cIO, "print", rb_io_print, -1);
11692 rb_define_method(rb_cIO, "putc", rb_io_putc, 1);
11693 rb_define_method(rb_cIO, "puts", rb_io_puts, -1);
11694 rb_define_method(rb_cIO, "printf", rb_io_printf, -1);
11695
11696 rb_define_method(rb_cIO, "each", rb_io_each_line, -1);
11697 rb_define_method(rb_cIO, "each_line", rb_io_each_line, -1);
11698 rb_define_method(rb_cIO, "each_byte", rb_io_each_byte, 0);
11699 rb_define_method(rb_cIO, "each_char", rb_io_each_char, 0);
11700 rb_define_method(rb_cIO, "each_codepoint", rb_io_each_codepoint, 0);
11701 rb_define_method(rb_cIO, "lines", rb_io_lines, -1);
11702 rb_define_method(rb_cIO, "bytes", rb_io_bytes, 0);
11703 rb_define_method(rb_cIO, "chars", rb_io_chars, 0);
11704 rb_define_method(rb_cIO, "codepoints", rb_io_codepoints, 0);
11705
11706 rb_define_method(rb_cIO, "syswrite", rb_io_syswrite, 1);
11707 rb_define_method(rb_cIO, "sysread", rb_io_sysread, -1);
11708
11709 rb_define_method(rb_cIO, "fileno", rb_io_fileno, 0);
11710 rb_define_alias(rb_cIO, "to_i", "fileno");
11711 rb_define_method(rb_cIO, "to_io", rb_io_to_io, 0);
11712
11713 rb_define_method(rb_cIO, "fsync", rb_io_fsync, 0);
11714 rb_define_method(rb_cIO, "fdatasync", rb_io_fdatasync, 0);
11715 rb_define_method(rb_cIO, "sync", rb_io_sync, 0);
11716 rb_define_method(rb_cIO, "sync=", rb_io_set_sync, 1);
11717
11718 rb_define_method(rb_cIO, "lineno", rb_io_lineno, 0);
11719 rb_define_method(rb_cIO, "lineno=", rb_io_set_lineno, 1);
11720
11721 rb_define_method(rb_cIO, "readlines", rb_io_readlines, -1);
11722
11723 rb_define_method(rb_cIO, "read_nonblock", io_read_nonblock, -1);
11724 rb_define_method(rb_cIO, "write_nonblock", rb_io_write_nonblock, 1);
11725 rb_define_method(rb_cIO, "readpartial", io_readpartial, -1);
11726 rb_define_method(rb_cIO, "read", io_read, -1);
11727 rb_define_method(rb_cIO, "write", io_write_m, 1);
11728 rb_define_method(rb_cIO, "gets", rb_io_gets_m, -1);
11729 rb_define_method(rb_cIO, "readline", rb_io_readline, -1);
11730 rb_define_method(rb_cIO, "getc", rb_io_getc, 0);
11731 rb_define_method(rb_cIO, "getbyte", rb_io_getbyte, 0);
11732 rb_define_method(rb_cIO, "readchar", rb_io_readchar, 0);
11733 rb_define_method(rb_cIO, "readbyte", rb_io_readbyte, 0);
11734 rb_define_method(rb_cIO, "ungetbyte",rb_io_ungetbyte, 1);
11735 rb_define_method(rb_cIO, "ungetc",rb_io_ungetc, 1);
11736 rb_define_method(rb_cIO, "<<", rb_io_addstr, 1);
11737 rb_define_method(rb_cIO, "flush", rb_io_flush, 0);
11738 rb_define_method(rb_cIO, "tell", rb_io_tell, 0);
11739 rb_define_method(rb_cIO, "seek", rb_io_seek_m, -1);
11740 rb_define_const(rb_cIO, "SEEK_SET", INT2FIX(SEEK_SET));
11741 rb_define_const(rb_cIO, "SEEK_CUR", INT2FIX(SEEK_CUR));
11742 rb_define_const(rb_cIO, "SEEK_END", INT2FIX(SEEK_END));
11743 rb_define_method(rb_cIO, "rewind", rb_io_rewind, 0);
11744 rb_define_method(rb_cIO, "pos", rb_io_tell, 0);
11745 rb_define_method(rb_cIO, "pos=", rb_io_set_pos, 1);
11746 rb_define_method(rb_cIO, "eof", rb_io_eof, 0);
11747 rb_define_method(rb_cIO, "eof?", rb_io_eof, 0);
11748
11749 rb_define_method(rb_cIO, "close_on_exec?", rb_io_close_on_exec_p, 0);
11750 rb_define_method(rb_cIO, "close_on_exec=", rb_io_set_close_on_exec, 1);
11751
11752 rb_define_method(rb_cIO, "close", rb_io_close_m, 0);
11753 rb_define_method(rb_cIO, "closed?", rb_io_closed, 0);
11754 rb_define_method(rb_cIO, "close_read", rb_io_close_read, 0);
11755 rb_define_method(rb_cIO, "close_write", rb_io_close_write, 0);
11756
11757 rb_define_method(rb_cIO, "isatty", rb_io_isatty, 0);
11758 rb_define_method(rb_cIO, "tty?", rb_io_isatty, 0);
11759 rb_define_method(rb_cIO, "binmode", rb_io_binmode_m, 0);
11760 rb_define_method(rb_cIO, "binmode?", rb_io_binmode_p, 0);
11761 rb_define_method(rb_cIO, "sysseek", rb_io_sysseek, -1);
11762 rb_define_method(rb_cIO, "advise", rb_io_advise, -1);
11763
11764 rb_define_method(rb_cIO, "ioctl", rb_io_ioctl, -1);
11765 rb_define_method(rb_cIO, "fcntl", rb_io_fcntl, -1);
11766 rb_define_method(rb_cIO, "pid", rb_io_pid, 0);
11767 rb_define_method(rb_cIO, "inspect", rb_io_inspect, 0);
11768
11769 rb_define_method(rb_cIO, "external_encoding", rb_io_external_encoding, 0);
11770 rb_define_method(rb_cIO, "internal_encoding", rb_io_internal_encoding, 0);
11771 rb_define_method(rb_cIO, "set_encoding", rb_io_set_encoding, -1);
11772
11773 rb_define_method(rb_cIO, "autoclose?", rb_io_autoclose_p, 0);
11774 rb_define_method(rb_cIO, "autoclose=", rb_io_set_autoclose, 1);
11775
11776 rb_define_variable("$stdin", &rb_stdin);
11777 rb_stdin = prep_stdio(stdin, FMODE_READABLE, rb_cIO, "<STDIN>");
11778 rb_define_hooked_variable("$stdout", &rb_stdout, 0, stdout_setter);
11779 rb_stdout = prep_stdio(stdout, FMODE_WRITABLE, rb_cIO, "<STDOUT>");
11780 rb_define_hooked_variable("$stderr", &rb_stderr, 0, stdout_setter);
11781 rb_stderr = prep_stdio(stderr, FMODE_WRITABLE|FMODE_SYNC, rb_cIO, "<STDERR>");
11782 rb_define_hooked_variable("$>", &rb_stdout, 0, stdout_setter);
11783 orig_stdout = rb_stdout;
11784 rb_deferr = orig_stderr = rb_stderr;
11785
11786 /* Holds the original stdin */
11787 rb_define_global_const("STDIN", rb_stdin);
11788 /* Holds the original stdout */
11789 rb_define_global_const("STDOUT", rb_stdout);
11790 /* Holds the original stderr */
11791 rb_define_global_const("STDERR", rb_stderr);
11792
11793 #if 0
11794 /* Hack to get rdoc to regard ARGF as a class: */
11795 rb_cARGF = rb_define_class("ARGF", rb_cObject);
11796 #endif
11797
11798 rb_cARGF = rb_class_new(rb_cObject);
11799 rb_set_class_path(rb_cARGF, rb_cObject, "ARGF.class");
11800 rb_define_alloc_func(rb_cARGF, argf_alloc);
11801
11802 rb_include_module(rb_cARGF, rb_mEnumerable);
11803
11804 rb_define_method(rb_cARGF, "initialize", argf_initialize, -2);
11805 rb_define_method(rb_cARGF, "initialize_copy", argf_initialize_copy, 1);
11806 rb_define_method(rb_cARGF, "to_s", argf_to_s, 0);
11807 rb_define_alias(rb_cARGF, "inspect", "to_s");
11808 rb_define_method(rb_cARGF, "argv", argf_argv, 0);
11809
11810 rb_define_method(rb_cARGF, "fileno", argf_fileno, 0);
11811 rb_define_method(rb_cARGF, "to_i", argf_fileno, 0);
11812 rb_define_method(rb_cARGF, "to_io", argf_to_io, 0);
11813 rb_define_method(rb_cARGF, "to_write_io", argf_write_io, 0);
11814 rb_define_method(rb_cARGF, "each", argf_each_line, -1);
11815 rb_define_method(rb_cARGF, "each_line", argf_each_line, -1);
11816 rb_define_method(rb_cARGF, "each_byte", argf_each_byte, 0);
11817 rb_define_method(rb_cARGF, "each_char", argf_each_char, 0);
11818 rb_define_method(rb_cARGF, "each_codepoint", argf_each_codepoint, 0);
11819 rb_define_method(rb_cARGF, "lines", argf_lines, -1);
11820 rb_define_method(rb_cARGF, "bytes", argf_bytes, 0);
11821 rb_define_method(rb_cARGF, "chars", argf_chars, 0);
11822 rb_define_method(rb_cARGF, "codepoints", argf_codepoints, 0);
11823
11824 rb_define_method(rb_cARGF, "read", argf_read, -1);
11825 rb_define_method(rb_cARGF, "readpartial", argf_readpartial, -1);
11826 rb_define_method(rb_cARGF, "read_nonblock", argf_read_nonblock, -1);
11827 rb_define_method(rb_cARGF, "readlines", argf_readlines, -1);
11828 rb_define_method(rb_cARGF, "to_a", argf_readlines, -1);
11829 rb_define_method(rb_cARGF, "gets", argf_gets, -1);
11830 rb_define_method(rb_cARGF, "readline", argf_readline, -1);
11831 rb_define_method(rb_cARGF, "getc", argf_getc, 0);
11832 rb_define_method(rb_cARGF, "getbyte", argf_getbyte, 0);
11833 rb_define_method(rb_cARGF, "readchar", argf_readchar, 0);
11834 rb_define_method(rb_cARGF, "readbyte", argf_readbyte, 0);
11835 rb_define_method(rb_cARGF, "tell", argf_tell, 0);
11836 rb_define_method(rb_cARGF, "seek", argf_seek_m, -1);
11837 rb_define_method(rb_cARGF, "rewind", argf_rewind, 0);
11838 rb_define_method(rb_cARGF, "pos", argf_tell, 0);
11839 rb_define_method(rb_cARGF, "pos=", argf_set_pos, 1);
11840 rb_define_method(rb_cARGF, "eof", argf_eof, 0);
11841 rb_define_method(rb_cARGF, "eof?", argf_eof, 0);
11842 rb_define_method(rb_cARGF, "binmode", argf_binmode_m, 0);
11843 rb_define_method(rb_cARGF, "binmode?", argf_binmode_p, 0);
11844
11845 rb_define_method(rb_cARGF, "write", argf_write, 1);
11846 rb_define_method(rb_cARGF, "print", rb_io_print, -1);
11847 rb_define_method(rb_cARGF, "putc", rb_io_putc, 1);
11848 rb_define_method(rb_cARGF, "puts", rb_io_puts, -1);
11849 rb_define_method(rb_cARGF, "printf", rb_io_printf, -1);
11850
11851 rb_define_method(rb_cARGF, "filename", argf_filename, 0);
11852 rb_define_method(rb_cARGF, "path", argf_filename, 0);
11853 rb_define_method(rb_cARGF, "file", argf_file, 0);
11854 rb_define_method(rb_cARGF, "skip", argf_skip, 0);
11855 rb_define_method(rb_cARGF, "close", argf_close_m, 0);
11856 rb_define_method(rb_cARGF, "closed?", argf_closed, 0);
11857
11858 rb_define_method(rb_cARGF, "lineno", argf_lineno, 0);
11859 rb_define_method(rb_cARGF, "lineno=", argf_set_lineno, 1);
11860
11861 rb_define_method(rb_cARGF, "inplace_mode", argf_inplace_mode_get, 0);
11862 rb_define_method(rb_cARGF, "inplace_mode=", argf_inplace_mode_set, 1);
11863
11864 rb_define_method(rb_cARGF, "external_encoding", argf_external_encoding, 0);
11865 rb_define_method(rb_cARGF, "internal_encoding", argf_internal_encoding, 0);
11866 rb_define_method(rb_cARGF, "set_encoding", argf_set_encoding, -1);
11867
11868 argf = rb_class_new_instance(0, 0, rb_cARGF);
11869
11870 rb_define_readonly_variable("$<", &argf);
11871 /*
11872 * ARGF is a stream designed for use in scripts that process files given
11873 * as command-line arguments or passed in via STDIN.
11874 *
11875 * See ARGF (the class) for more details.
11876 */
11877 rb_define_global_const("ARGF", argf);
11878
11879 rb_define_hooked_variable("$.", &argf, argf_lineno_getter, argf_lineno_setter);
11880 rb_define_hooked_variable("$FILENAME", &argf, argf_filename_getter, rb_gvar_readonly_setter);
11881 ARGF.filename = rb_str_new2("-");
11882
11883 rb_define_hooked_variable("$-i", &argf, opt_i_get, opt_i_set);
11884 rb_define_hooked_variable("$*", &argf, argf_argv_getter, rb_gvar_readonly_setter);
11885
11886 #if defined (_WIN32) || defined(__CYGWIN__)
11887 atexit(pipe_atexit);
11888 #endif
11889
11890 Init_File();
11891
11892 rb_define_method(rb_cFile, "initialize", rb_file_initialize, -1);
11893
11894 sym_mode = ID2SYM(rb_intern("mode"));
11895 sym_perm = ID2SYM(rb_intern("perm"));
11896 sym_extenc = ID2SYM(rb_intern("external_encoding"));
11897 sym_intenc = ID2SYM(rb_intern("internal_encoding"));
11898 sym_encoding = ID2SYM(rb_intern("encoding"));
11899 sym_open_args = ID2SYM(rb_intern("open_args"));
11900 sym_textmode = ID2SYM(rb_intern("textmode"));
11901 sym_binmode = ID2SYM(rb_intern("binmode"));
11902 sym_autoclose = ID2SYM(rb_intern("autoclose"));
11903 sym_normal = ID2SYM(rb_intern("normal"));
11904 sym_sequential = ID2SYM(rb_intern("sequential"));
11905 sym_random = ID2SYM(rb_intern("random"));
11906 sym_willneed = ID2SYM(rb_intern("willneed"));
11907 sym_dontneed = ID2SYM(rb_intern("dontneed"));
11908 sym_noreuse = ID2SYM(rb_intern("noreuse"));
11909 }
11910