00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "ruby/ruby.h"
00015 #include "ruby/io.h"
00016 #include "dln.h"
00017 #include "internal.h"
00018 #include <ctype.h>
00019 #include <errno.h>
00020
00021 #define free(x) xfree(x)
00022
00023 #if defined(DOSISH) || defined(__CYGWIN__)
00024 #include <io.h>
00025 #endif
00026
00027 #include <sys/types.h>
00028 #if defined HAVE_NET_SOCKET_H
00029 # include <net/socket.h>
00030 #elif defined HAVE_SYS_SOCKET_H
00031 # include <sys/socket.h>
00032 #endif
00033
00034 #if defined(__BOW__) || defined(__CYGWIN__) || defined(_WIN32) || defined(__EMX__) || defined(__BEOS__) || defined(__HAIKU__)
00035 # define NO_SAFE_RENAME
00036 #endif
00037
00038 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(sun) || defined(_nec_ews)
00039 # define USE_SETVBUF
00040 #endif
00041
00042 #ifdef __QNXNTO__
00043 #include "unix.h"
00044 #endif
00045
00046 #include <sys/types.h>
00047 #if defined(HAVE_SYS_IOCTL_H) && !defined(_WIN32)
00048 #include <sys/ioctl.h>
00049 #endif
00050 #if defined(HAVE_FCNTL_H) || defined(_WIN32)
00051 #include <fcntl.h>
00052 #elif defined(HAVE_SYS_FCNTL_H)
00053 #include <sys/fcntl.h>
00054 #endif
00055
00056 #if !HAVE_OFF_T && !defined(off_t)
00057 # define off_t long
00058 #endif
00059
00060 #include <sys/stat.h>
00061
00062
00063 #if defined(HAVE_SYS_PARAM_H) && !(defined(__EMX__) || defined(__HIUX_MPP__))
00064 # include <sys/param.h>
00065 #endif
00066
00067 #if !defined NOFILE
00068 # define NOFILE 64
00069 #endif
00070
00071 #ifdef HAVE_UNISTD_H
00072 #include <unistd.h>
00073 #endif
00074
00075 #ifdef HAVE_SYSCALL_H
00076 #include <syscall.h>
00077 #elif defined HAVE_SYS_SYSCALL_H
00078 #include <sys/syscall.h>
00079 #endif
00080
00081 #if defined(__BEOS__) || defined(__HAIKU__)
00082 # ifndef NOFILE
00083 # define NOFILE (OPEN_MAX)
00084 # endif
00085 #endif
00086
00087 #include "ruby/util.h"
00088
00089 #ifndef O_ACCMODE
00090 #define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR)
00091 #endif
00092
00093 #if SIZEOF_OFF_T > SIZEOF_LONG && !defined(HAVE_LONG_LONG)
00094 # error off_t is bigger than long, but you have no long long...
00095 #endif
00096
00097 #ifndef PIPE_BUF
00098 # ifdef _POSIX_PIPE_BUF
00099 # define PIPE_BUF _POSIX_PIPE_BUF
00100 # else
00101 # define PIPE_BUF 512
00102 # endif
00103 #endif
00104
00105 #define numberof(array) (int)(sizeof(array) / sizeof((array)[0]))
00106
00107 #define IO_RBUF_CAPA_MIN 8192
00108 #define IO_CBUF_CAPA_MIN (128*1024)
00109 #define IO_RBUF_CAPA_FOR(fptr) (NEED_READCONV(fptr) ? IO_CBUF_CAPA_MIN : IO_RBUF_CAPA_MIN)
00110 #define IO_WBUF_CAPA_MIN 8192
00111
00112
00113 #ifdef _WIN32
00114 #undef open
00115 #define open rb_w32_uopen
00116 #endif
00117
00118 VALUE rb_cIO;
00119 VALUE rb_eEOFError;
00120 VALUE rb_eIOError;
00121 VALUE rb_mWaitReadable;
00122 VALUE rb_mWaitWritable;
00123
00124 VALUE rb_stdin, rb_stdout, rb_stderr;
00125 VALUE rb_deferr;
00126 static VALUE orig_stdout, orig_stderr;
00127
00128 VALUE rb_output_fs;
00129 VALUE rb_rs;
00130 VALUE rb_output_rs;
00131 VALUE rb_default_rs;
00132
00133 static VALUE argf;
00134
00135 static ID id_write, id_read, id_getc, id_flush, id_readpartial, id_set_encoding;
00136 static VALUE sym_mode, sym_perm, sym_extenc, sym_intenc, sym_encoding, sym_open_args;
00137 static VALUE sym_textmode, sym_binmode, sym_autoclose;
00138
00139 struct argf {
00140 VALUE filename, current_file;
00141 long last_lineno;
00142 long lineno;
00143 VALUE argv;
00144 char *inplace;
00145 struct rb_io_enc_t encs;
00146 int8_t init_p, next_p, binmode;
00147 };
00148
00149 static int max_file_descriptor = NOFILE;
00150 void
00151 rb_update_max_fd(int fd)
00152 {
00153 struct stat buf;
00154 if (fstat(fd, &buf) != 0 && errno == EBADF) {
00155 rb_bug("rb_update_max_fd: invalid fd (%d) given.", fd);
00156 }
00157 if (max_file_descriptor < fd) max_file_descriptor = fd;
00158 }
00159
00160 void
00161 rb_maygvl_fd_fix_cloexec(int fd)
00162 {
00163
00164 #ifdef F_GETFD
00165 int flags, flags2, ret;
00166 flags = fcntl(fd, F_GETFD);
00167 if (flags == -1) {
00168 rb_bug("rb_maygvl_fd_fix_cloexec: fcntl(%d, F_GETFD) failed: %s", fd, strerror(errno));
00169 }
00170 if (fd <= 2)
00171 flags2 = flags & ~FD_CLOEXEC;
00172 else
00173 flags2 = flags | FD_CLOEXEC;
00174 if (flags != flags2) {
00175 ret = fcntl(fd, F_SETFD, flags2);
00176 if (ret == -1) {
00177 rb_bug("rb_maygvl_fd_fix_cloexec: fcntl(%d, F_SETFD, %d) failed: %s", fd, flags2, strerror(errno));
00178 }
00179 }
00180 #endif
00181 }
00182
00183 int
00184 rb_cloexec_fcntl_dupfd(int fd, int minfd)
00185 {
00186 int ret;
00187
00188 #if defined(HAVE_FCNTL) && defined(F_DUPFD_CLOEXEC)
00189 static int try_dupfd_cloexec = 1;
00190 if (try_dupfd_cloexec) {
00191 ret = fcntl(fd, F_DUPFD_CLOEXEC, minfd);
00192 if (ret != -1) {
00193 if (ret <= 2)
00194 rb_maygvl_fd_fix_cloexec(ret);
00195 return ret;
00196 }
00197
00198 if (errno == EINVAL) {
00199 ret = fcntl(fd, F_DUPFD, minfd);
00200 if (ret != -1) {
00201 try_dupfd_cloexec = 0;
00202 }
00203 }
00204 }
00205 else {
00206 ret = fcntl(fd, F_DUPFD, minfd);
00207 }
00208 #elif defined(F_DUPFD)
00209 ret = fcntl(fd, F_DUPFD, minfd);
00210 #else
00211 ret = -1;
00212 errno = EINVAL;
00213 #endif
00214 if (ret == -1) return -1;
00215 rb_maygvl_fd_fix_cloexec(ret);
00216 return ret;
00217 }
00218
00219 #define argf_of(obj) (*(struct argf *)DATA_PTR(obj))
00220 #define ARGF argf_of(argf)
00221
00222 #ifdef _STDIO_USES_IOSTREAM
00223 # ifdef _IO_fpos_t
00224 # define STDIO_READ_DATA_PENDING(fp) ((fp)->_IO_read_ptr != (fp)->_IO_read_end)
00225 # else
00226 # define STDIO_READ_DATA_PENDING(fp) ((fp)->_gptr < (fp)->_egptr)
00227 # endif
00228 #elif defined(FILE_COUNT)
00229 # define STDIO_READ_DATA_PENDING(fp) ((fp)->FILE_COUNT > 0)
00230 #elif defined(FILE_READEND)
00231 # define STDIO_READ_DATA_PENDING(fp) ((fp)->FILE_READPTR < (fp)->FILE_READEND)
00232 #elif defined(__BEOS__) || defined(__HAIKU__)
00233 # define STDIO_READ_DATA_PENDING(fp) ((fp)->_state._eof == 0)
00234 #else
00235 # define STDIO_READ_DATA_PENDING(fp) (!feof(fp))
00236 #endif
00237
00238 #define GetWriteIO(io) rb_io_get_write_io(io)
00239
00240 #define READ_DATA_PENDING(fptr) ((fptr)->rbuf.len)
00241 #define READ_DATA_PENDING_COUNT(fptr) ((fptr)->rbuf.len)
00242 #define READ_DATA_PENDING_PTR(fptr) ((fptr)->rbuf.ptr+(fptr)->rbuf.off)
00243 #define READ_DATA_BUFFERED(fptr) READ_DATA_PENDING(fptr)
00244
00245 #define READ_CHAR_PENDING(fptr) ((fptr)->cbuf.len)
00246 #define READ_CHAR_PENDING_COUNT(fptr) ((fptr)->cbuf.len)
00247 #define READ_CHAR_PENDING_PTR(fptr) ((fptr)->cbuf.ptr+(fptr)->cbuf.off)
00248
00249 #if defined(_WIN32)
00250 #define WAIT_FD_IN_WIN32(fptr) \
00251 (rb_w32_io_cancelable_p((fptr)->fd) ? 0 : rb_thread_wait_fd((fptr)->fd))
00252 #else
00253 #define WAIT_FD_IN_WIN32(fptr)
00254 #endif
00255
00256 #define READ_CHECK(fptr) do {\
00257 if (!READ_DATA_PENDING(fptr)) {\
00258 WAIT_FD_IN_WIN32(fptr);\
00259 rb_io_check_closed(fptr);\
00260 }\
00261 } while(0)
00262
00263 #ifndef S_ISSOCK
00264 # ifdef _S_ISSOCK
00265 # define S_ISSOCK(m) _S_ISSOCK(m)
00266 # else
00267 # ifdef _S_IFSOCK
00268 # define S_ISSOCK(m) (((m) & S_IFMT) == _S_IFSOCK)
00269 # else
00270 # ifdef S_IFSOCK
00271 # define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
00272 # endif
00273 # endif
00274 # endif
00275 #endif
00276
00277 #define rb_sys_fail_path(path) rb_sys_fail_str(path)
00278
00279 static int io_fflush(rb_io_t *);
00280 static rb_io_t *flush_before_seek(rb_io_t *fptr);
00281
00282 #define NEED_NEWLINE_DECORATOR_ON_READ(fptr) ((fptr)->mode & FMODE_TEXTMODE)
00283 #define NEED_NEWLINE_DECORATOR_ON_WRITE(fptr) ((fptr)->mode & FMODE_TEXTMODE)
00284 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
00285
00286 # define DEFAULT_TEXTMODE FMODE_TEXTMODE
00287 # define TEXTMODE_NEWLINE_DECORATOR_ON_WRITE ECONV_CRLF_NEWLINE_DECORATOR
00288
00289
00290
00291
00292
00293
00294
00295 #define NEED_READCONV(fptr) ((fptr)->encs.enc2 != NULL || (fptr)->encs.ecflags & ~ECONV_CRLF_NEWLINE_DECORATOR)
00296 #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)))
00297 #define SET_BINARY_MODE(fptr) setmode((fptr)->fd, O_BINARY)
00298
00299 #define NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr) do {\
00300 if (NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {\
00301 if (((fptr)->mode & FMODE_READABLE) &&\
00302 !((fptr)->encs.ecflags & ECONV_NEWLINE_DECORATOR_MASK)) {\
00303 setmode((fptr)->fd, O_BINARY);\
00304 }\
00305 else {\
00306 setmode((fptr)->fd, O_TEXT);\
00307 }\
00308 }\
00309 } while(0)
00310
00311 #define SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags) do {\
00312 if ((enc2) && ((ecflags) & ECONV_DEFAULT_NEWLINE_DECORATOR)) {\
00313 (ecflags) |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;\
00314 }\
00315 } while(0)
00316
00317
00318
00319
00320 static void
00321 io_unread(rb_io_t *fptr)
00322 {
00323 off_t r, pos;
00324 ssize_t read_size;
00325 long i;
00326 long newlines = 0;
00327 long extra_max;
00328 char *p;
00329 char *buf;
00330
00331 rb_io_check_closed(fptr);
00332 if (fptr->rbuf.len == 0 || fptr->mode & FMODE_DUPLEX) {
00333 return;
00334 }
00335
00336 errno = 0;
00337 if (!rb_w32_fd_is_text(fptr->fd)) {
00338 r = lseek(fptr->fd, -fptr->rbuf.len, SEEK_CUR);
00339 if (r < 0 && errno) {
00340 if (errno == ESPIPE)
00341 fptr->mode |= FMODE_DUPLEX;
00342 return;
00343 }
00344
00345 fptr->rbuf.off = 0;
00346 fptr->rbuf.len = 0;
00347 return;
00348 }
00349
00350 pos = lseek(fptr->fd, 0, SEEK_CUR);
00351 if (pos < 0 && errno) {
00352 if (errno == ESPIPE)
00353 fptr->mode |= FMODE_DUPLEX;
00354 return;
00355 }
00356
00357
00358 extra_max = (long)(pos - fptr->rbuf.len);
00359 p = fptr->rbuf.ptr + fptr->rbuf.off;
00360
00361
00362 if (*(fptr->rbuf.ptr + fptr->rbuf.capa - 1) == '\r') {
00363 newlines++;
00364 }
00365
00366 for (i = 0; i < fptr->rbuf.len; i++) {
00367 if (*p == '\n') newlines++;
00368 if (extra_max == newlines) break;
00369 p++;
00370 }
00371
00372 buf = ALLOC_N(char, fptr->rbuf.len + newlines);
00373 while (newlines >= 0) {
00374 r = lseek(fptr->fd, pos - fptr->rbuf.len - newlines, SEEK_SET);
00375 if (newlines == 0) break;
00376 if (r < 0) {
00377 newlines--;
00378 continue;
00379 }
00380 read_size = _read(fptr->fd, buf, fptr->rbuf.len + newlines);
00381 if (read_size < 0) {
00382 free(buf);
00383 rb_sys_fail_path(fptr->pathv);
00384 }
00385 if (read_size == fptr->rbuf.len) {
00386 lseek(fptr->fd, r, SEEK_SET);
00387 break;
00388 }
00389 else {
00390 newlines--;
00391 }
00392 }
00393 free(buf);
00394 fptr->rbuf.off = 0;
00395 fptr->rbuf.len = 0;
00396 return;
00397 }
00398
00399
00400
00401
00402
00403
00404
00405
00406 static inline int
00407 set_binary_mode_with_seek_cur(rb_io_t *fptr)
00408 {
00409 if (!rb_w32_fd_is_text(fptr->fd)) return O_BINARY;
00410
00411 if (fptr->rbuf.len == 0 || fptr->mode & FMODE_DUPLEX) {
00412 return setmode(fptr->fd, O_BINARY);
00413 }
00414 flush_before_seek(fptr);
00415 return setmode(fptr->fd, O_BINARY);
00416 }
00417 #define SET_BINARY_MODE_WITH_SEEK_CUR(fptr) set_binary_mode_with_seek_cur(fptr)
00418
00419 #else
00420
00421 # define DEFAULT_TEXTMODE 0
00422 #define NEED_READCONV(fptr) ((fptr)->encs.enc2 != NULL || NEED_NEWLINE_DECORATOR_ON_READ(fptr))
00423 #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)))
00424 #define SET_BINARY_MODE(fptr) (void)(fptr)
00425 #define NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr) (void)(fptr)
00426 #define SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags) ((void)(enc2), (void)(ecflags))
00427 #define SET_BINARY_MODE_WITH_SEEK_CUR(fptr) (void)(fptr)
00428 #endif
00429
00430 #if !defined HAVE_SHUTDOWN && !defined shutdown
00431 #define shutdown(a,b) 0
00432 #endif
00433
00434 #if defined(_WIN32)
00435 #define is_socket(fd, path) rb_w32_is_socket(fd)
00436 #elif !defined(S_ISSOCK)
00437 #define is_socket(fd, path) 0
00438 #else
00439 static int
00440 is_socket(int fd, VALUE path)
00441 {
00442 struct stat sbuf;
00443 if (fstat(fd, &sbuf) < 0)
00444 rb_sys_fail_path(path);
00445 return S_ISSOCK(sbuf.st_mode);
00446 }
00447 #endif
00448
00449 void
00450 rb_eof_error(void)
00451 {
00452 rb_raise(rb_eEOFError, "end of file reached");
00453 }
00454
00455 VALUE
00456 rb_io_taint_check(VALUE io)
00457 {
00458 if (!OBJ_UNTRUSTED(io) && rb_safe_level() >= 4)
00459 rb_raise(rb_eSecurityError, "Insecure: operation on trusted IO");
00460 rb_check_frozen(io);
00461 return io;
00462 }
00463
00464 void
00465 rb_io_check_initialized(rb_io_t *fptr)
00466 {
00467 if (!fptr) {
00468 rb_raise(rb_eIOError, "uninitialized stream");
00469 }
00470 }
00471
00472 void
00473 rb_io_check_closed(rb_io_t *fptr)
00474 {
00475 rb_io_check_initialized(fptr);
00476 if (fptr->fd < 0) {
00477 rb_raise(rb_eIOError, "closed stream");
00478 }
00479 }
00480
00481
00482 VALUE
00483 rb_io_get_io(VALUE io)
00484 {
00485 return rb_convert_type(io, T_FILE, "IO", "to_io");
00486 }
00487
00488 static VALUE
00489 rb_io_check_io(VALUE io)
00490 {
00491 return rb_check_convert_type(io, T_FILE, "IO", "to_io");
00492 }
00493
00494 VALUE
00495 rb_io_get_write_io(VALUE io)
00496 {
00497 VALUE write_io;
00498 rb_io_check_initialized(RFILE(io)->fptr);
00499 write_io = RFILE(io)->fptr->tied_io_for_writing;
00500 if (write_io) {
00501 return write_io;
00502 }
00503 return io;
00504 }
00505
00506 VALUE
00507 rb_io_set_write_io(VALUE io, VALUE w)
00508 {
00509 VALUE write_io;
00510 rb_io_check_initialized(RFILE(io)->fptr);
00511 if (!RTEST(w)) {
00512 w = 0;
00513 }
00514 else {
00515 GetWriteIO(w);
00516 }
00517 write_io = RFILE(io)->fptr->tied_io_for_writing;
00518 RFILE(io)->fptr->tied_io_for_writing = w;
00519 return write_io ? write_io : Qnil;
00520 }
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539 static VALUE
00540 rb_io_s_try_convert(VALUE dummy, VALUE io)
00541 {
00542 return rb_io_check_io(io);
00543 }
00544
00545 #if !(defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32))
00546 static void
00547 io_unread(rb_io_t *fptr)
00548 {
00549 off_t r;
00550 rb_io_check_closed(fptr);
00551 if (fptr->rbuf.len == 0 || fptr->mode & FMODE_DUPLEX)
00552 return;
00553
00554 errno = 0;
00555 r = lseek(fptr->fd, -fptr->rbuf.len, SEEK_CUR);
00556 if (r < 0 && errno) {
00557 if (errno == ESPIPE)
00558 fptr->mode |= FMODE_DUPLEX;
00559 return;
00560 }
00561 fptr->rbuf.off = 0;
00562 fptr->rbuf.len = 0;
00563 return;
00564 }
00565 #endif
00566
00567 static rb_encoding *io_input_encoding(rb_io_t *fptr);
00568
00569 static void
00570 io_ungetbyte(VALUE str, rb_io_t *fptr)
00571 {
00572 long len = RSTRING_LEN(str);
00573
00574 if (fptr->rbuf.ptr == NULL) {
00575 const int min_capa = IO_RBUF_CAPA_FOR(fptr);
00576 fptr->rbuf.off = 0;
00577 fptr->rbuf.len = 0;
00578 #if SIZEOF_LONG > SIZEOF_INT
00579 if (len > INT_MAX)
00580 rb_raise(rb_eIOError, "ungetbyte failed");
00581 #endif
00582 if (len > min_capa)
00583 fptr->rbuf.capa = (int)len;
00584 else
00585 fptr->rbuf.capa = min_capa;
00586 fptr->rbuf.ptr = ALLOC_N(char, fptr->rbuf.capa);
00587 }
00588 if (fptr->rbuf.capa < len + fptr->rbuf.len) {
00589 rb_raise(rb_eIOError, "ungetbyte failed");
00590 }
00591 if (fptr->rbuf.off < len) {
00592 MEMMOVE(fptr->rbuf.ptr+fptr->rbuf.capa-fptr->rbuf.len,
00593 fptr->rbuf.ptr+fptr->rbuf.off,
00594 char, fptr->rbuf.len);
00595 fptr->rbuf.off = fptr->rbuf.capa-fptr->rbuf.len;
00596 }
00597 fptr->rbuf.off-=(int)len;
00598 fptr->rbuf.len+=(int)len;
00599 MEMMOVE(fptr->rbuf.ptr+fptr->rbuf.off, RSTRING_PTR(str), char, len);
00600 }
00601
00602 static rb_io_t *
00603 flush_before_seek(rb_io_t *fptr)
00604 {
00605 if (io_fflush(fptr) < 0)
00606 rb_sys_fail(0);
00607 io_unread(fptr);
00608 errno = 0;
00609 return fptr;
00610 }
00611
00612 #define io_seek(fptr, ofs, whence) (errno = 0, lseek(flush_before_seek(fptr)->fd, (ofs), (whence)))
00613 #define io_tell(fptr) lseek(flush_before_seek(fptr)->fd, 0, SEEK_CUR)
00614
00615 #ifndef SEEK_CUR
00616 # define SEEK_SET 0
00617 # define SEEK_CUR 1
00618 # define SEEK_END 2
00619 #endif
00620
00621 #define FMODE_SYNCWRITE (FMODE_SYNC|FMODE_WRITABLE)
00622
00623 void
00624 rb_io_check_char_readable(rb_io_t *fptr)
00625 {
00626 rb_io_check_closed(fptr);
00627 if (!(fptr->mode & FMODE_READABLE)) {
00628 rb_raise(rb_eIOError, "not opened for reading");
00629 }
00630 if (fptr->wbuf.len) {
00631 if (io_fflush(fptr) < 0)
00632 rb_sys_fail(0);
00633 }
00634 if (fptr->tied_io_for_writing) {
00635 rb_io_t *wfptr;
00636 GetOpenFile(fptr->tied_io_for_writing, wfptr);
00637 if (io_fflush(wfptr) < 0)
00638 rb_sys_fail(0);
00639 }
00640 }
00641
00642 void
00643 rb_io_check_byte_readable(rb_io_t *fptr)
00644 {
00645 rb_io_check_char_readable(fptr);
00646 if (READ_CHAR_PENDING(fptr)) {
00647 rb_raise(rb_eIOError, "byte oriented read for character buffered IO");
00648 }
00649 }
00650
00651 void
00652 rb_io_check_readable(rb_io_t *fptr)
00653 {
00654 rb_io_check_byte_readable(fptr);
00655 }
00656
00657 static rb_encoding*
00658 io_read_encoding(rb_io_t *fptr)
00659 {
00660 if (fptr->encs.enc) {
00661 return fptr->encs.enc;
00662 }
00663 return rb_default_external_encoding();
00664 }
00665
00666 static rb_encoding*
00667 io_input_encoding(rb_io_t *fptr)
00668 {
00669 if (fptr->encs.enc2) {
00670 return fptr->encs.enc2;
00671 }
00672 return io_read_encoding(fptr);
00673 }
00674
00675 void
00676 rb_io_check_writable(rb_io_t *fptr)
00677 {
00678 rb_io_check_closed(fptr);
00679 if (!(fptr->mode & FMODE_WRITABLE)) {
00680 rb_raise(rb_eIOError, "not opened for writing");
00681 }
00682 if (fptr->rbuf.len) {
00683 io_unread(fptr);
00684 }
00685 }
00686
00687 int
00688 rb_io_read_pending(rb_io_t *fptr)
00689 {
00690
00691 if (READ_CHAR_PENDING(fptr))
00692 return 1;
00693 return READ_DATA_PENDING(fptr);
00694 }
00695
00696 void
00697 rb_read_check(FILE *fp)
00698 {
00699 if (!STDIO_READ_DATA_PENDING(fp)) {
00700 rb_thread_wait_fd(fileno(fp));
00701 }
00702 }
00703
00704 void
00705 rb_io_read_check(rb_io_t *fptr)
00706 {
00707 if (!READ_DATA_PENDING(fptr)) {
00708 rb_thread_wait_fd(fptr->fd);
00709 }
00710 return;
00711 }
00712
00713 static int
00714 ruby_dup(int orig)
00715 {
00716 int fd;
00717
00718 fd = dup(orig);
00719 if (fd < 0) {
00720 if (errno == EMFILE || errno == ENFILE || errno == ENOMEM) {
00721 rb_gc();
00722 fd = dup(orig);
00723 }
00724 if (fd < 0) {
00725 rb_sys_fail(0);
00726 }
00727 }
00728 rb_update_max_fd(fd);
00729 return fd;
00730 }
00731
00732 static VALUE
00733 io_alloc(VALUE klass)
00734 {
00735 NEWOBJ(io, struct RFile);
00736 OBJSETUP(io, klass, T_FILE);
00737
00738 io->fptr = 0;
00739
00740 return (VALUE)io;
00741 }
00742
00743 #ifndef S_ISREG
00744 # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
00745 #endif
00746
00747 static int
00748 wsplit_p(rb_io_t *fptr)
00749 {
00750 #if defined(HAVE_FCNTL) && defined(F_GETFL) && defined(O_NONBLOCK)
00751 int r;
00752 #endif
00753
00754 if (!(fptr->mode & FMODE_WSPLIT_INITIALIZED)) {
00755 struct stat buf;
00756 if (fstat(fptr->fd, &buf) == 0 &&
00757 !S_ISREG(buf.st_mode)
00758 #if defined(HAVE_FCNTL) && defined(F_GETFL) && defined(O_NONBLOCK)
00759 && (r = fcntl(fptr->fd, F_GETFL)) != -1 &&
00760 !(r & O_NONBLOCK)
00761 #endif
00762 ) {
00763 fptr->mode |= FMODE_WSPLIT;
00764 }
00765 fptr->mode |= FMODE_WSPLIT_INITIALIZED;
00766 }
00767 return fptr->mode & FMODE_WSPLIT;
00768 }
00769
00770 struct io_internal_read_struct {
00771 int fd;
00772 void *buf;
00773 size_t capa;
00774 };
00775
00776 struct io_internal_write_struct {
00777 int fd;
00778 const void *buf;
00779 size_t capa;
00780 };
00781
00782 static VALUE
00783 internal_read_func(void *ptr)
00784 {
00785 struct io_internal_read_struct *iis = ptr;
00786 return read(iis->fd, iis->buf, iis->capa);
00787 }
00788
00789 static VALUE
00790 internal_write_func(void *ptr)
00791 {
00792 struct io_internal_write_struct *iis = ptr;
00793 return write(iis->fd, iis->buf, iis->capa);
00794 }
00795
00796 static ssize_t
00797 rb_read_internal(int fd, void *buf, size_t count)
00798 {
00799 struct io_internal_read_struct iis;
00800 iis.fd = fd;
00801 iis.buf = buf;
00802 iis.capa = count;
00803
00804 return (ssize_t)rb_thread_io_blocking_region(internal_read_func, &iis, fd);
00805 }
00806
00807 static ssize_t
00808 rb_write_internal(int fd, const void *buf, size_t count)
00809 {
00810 struct io_internal_write_struct iis;
00811 iis.fd = fd;
00812 iis.buf = buf;
00813 iis.capa = count;
00814
00815 return (ssize_t)rb_thread_io_blocking_region(internal_write_func, &iis, fd);
00816 }
00817
00818 static long
00819 io_writable_length(rb_io_t *fptr, long l)
00820 {
00821 if (PIPE_BUF < l &&
00822 !rb_thread_alone() &&
00823 wsplit_p(fptr)) {
00824 l = PIPE_BUF;
00825 }
00826 return l;
00827 }
00828
00829 static VALUE
00830 io_flush_buffer_sync(void *arg)
00831 {
00832 rb_io_t *fptr = arg;
00833 long l = io_writable_length(fptr, fptr->wbuf.len);
00834 ssize_t r = write(fptr->fd, fptr->wbuf.ptr+fptr->wbuf.off, (size_t)l);
00835
00836 if (fptr->wbuf.len <= r) {
00837 fptr->wbuf.off = 0;
00838 fptr->wbuf.len = 0;
00839 return 0;
00840 }
00841 if (0 <= r) {
00842 fptr->wbuf.off += (int)r;
00843 fptr->wbuf.len -= (int)r;
00844 errno = EAGAIN;
00845 }
00846 return (VALUE)-1;
00847 }
00848
00849 static VALUE
00850 io_flush_buffer_async(VALUE arg)
00851 {
00852 rb_io_t *fptr = (rb_io_t *)arg;
00853 return rb_thread_io_blocking_region(io_flush_buffer_sync, fptr, fptr->fd);
00854 }
00855
00856 static inline int
00857 io_flush_buffer(rb_io_t *fptr)
00858 {
00859 if (fptr->write_lock) {
00860 return (int)rb_mutex_synchronize(fptr->write_lock, io_flush_buffer_async, (VALUE)fptr);
00861 }
00862 else {
00863 return (int)io_flush_buffer_async((VALUE)fptr);
00864 }
00865 }
00866
00867 static int
00868 io_fflush(rb_io_t *fptr)
00869 {
00870 rb_io_check_closed(fptr);
00871 if (fptr->wbuf.len == 0)
00872 return 0;
00873 if (!rb_thread_fd_writable(fptr->fd)) {
00874 rb_io_check_closed(fptr);
00875 }
00876 while (fptr->wbuf.len > 0 && io_flush_buffer(fptr) != 0) {
00877 if (!rb_io_wait_writable(fptr->fd))
00878 return -1;
00879 rb_io_check_closed(fptr);
00880 }
00881 return 0;
00882 }
00883
00884 int
00885 rb_io_wait_readable(int f)
00886 {
00887 if (f < 0) {
00888 rb_raise(rb_eIOError, "closed stream");
00889 }
00890 switch (errno) {
00891 case EINTR:
00892 #if defined(ERESTART)
00893 case ERESTART:
00894 #endif
00895 rb_thread_wait_fd(f);
00896 return TRUE;
00897
00898 case EAGAIN:
00899 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
00900 case EWOULDBLOCK:
00901 #endif
00902 rb_wait_for_single_fd(f, RB_WAITFD_IN, NULL);
00903 return TRUE;
00904
00905 default:
00906 return FALSE;
00907 }
00908 }
00909
00910 int
00911 rb_io_wait_writable(int f)
00912 {
00913 if (f < 0) {
00914 rb_raise(rb_eIOError, "closed stream");
00915 }
00916 switch (errno) {
00917 case EINTR:
00918 #if defined(ERESTART)
00919 case ERESTART:
00920 #endif
00921 rb_thread_fd_writable(f);
00922 return TRUE;
00923
00924 case EAGAIN:
00925 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
00926 case EWOULDBLOCK:
00927 #endif
00928 rb_wait_for_single_fd(f, RB_WAITFD_OUT, NULL);
00929 return TRUE;
00930
00931 default:
00932 return FALSE;
00933 }
00934 }
00935
00936 static void
00937 make_writeconv(rb_io_t *fptr)
00938 {
00939 if (!fptr->writeconv_initialized) {
00940 const char *senc, *denc;
00941 rb_encoding *enc;
00942 int ecflags;
00943 VALUE ecopts;
00944
00945 fptr->writeconv_initialized = 1;
00946
00947 ecflags = fptr->encs.ecflags & ~ECONV_NEWLINE_DECORATOR_READ_MASK;
00948 ecopts = fptr->encs.ecopts;
00949
00950 if (!fptr->encs.enc || (fptr->encs.enc == rb_ascii8bit_encoding() && !fptr->encs.enc2)) {
00951
00952 fptr->writeconv_pre_ecflags = 0;
00953 fptr->writeconv_pre_ecopts = Qnil;
00954 fptr->writeconv = rb_econv_open_opts("", "", ecflags, ecopts);
00955 if (!fptr->writeconv)
00956 rb_exc_raise(rb_econv_open_exc("", "", ecflags));
00957 fptr->writeconv_asciicompat = Qnil;
00958 }
00959 else {
00960 enc = fptr->encs.enc2 ? fptr->encs.enc2 : fptr->encs.enc;
00961 senc = rb_econv_asciicompat_encoding(rb_enc_name(enc));
00962 if (!senc && !(fptr->encs.ecflags & ECONV_STATEFUL_DECORATOR_MASK)) {
00963
00964 fptr->writeconv_pre_ecflags = ecflags;
00965 fptr->writeconv_pre_ecopts = ecopts;
00966 fptr->writeconv = NULL;
00967 fptr->writeconv_asciicompat = Qnil;
00968 }
00969 else {
00970
00971 fptr->writeconv_pre_ecflags = ecflags & ~ECONV_STATEFUL_DECORATOR_MASK;
00972 fptr->writeconv_pre_ecopts = ecopts;
00973 if (senc) {
00974 denc = rb_enc_name(enc);
00975 fptr->writeconv_asciicompat = rb_str_new2(senc);
00976 }
00977 else {
00978 senc = denc = "";
00979 fptr->writeconv_asciicompat = rb_str_new2(rb_enc_name(enc));
00980 }
00981 ecflags = fptr->encs.ecflags & (ECONV_ERROR_HANDLER_MASK|ECONV_STATEFUL_DECORATOR_MASK);
00982 ecopts = fptr->encs.ecopts;
00983 fptr->writeconv = rb_econv_open_opts(senc, denc, ecflags, ecopts);
00984 if (!fptr->writeconv)
00985 rb_exc_raise(rb_econv_open_exc(senc, denc, ecflags));
00986 }
00987 }
00988 }
00989 }
00990
00991
00992 struct binwrite_arg {
00993 rb_io_t *fptr;
00994 VALUE str;
00995 const char *ptr;
00996 long length;
00997 };
00998
00999 struct write_arg {
01000 VALUE io;
01001 VALUE str;
01002 int nosync;
01003 };
01004
01005 static VALUE
01006 io_binwrite_string(VALUE arg)
01007 {
01008 struct binwrite_arg *p = (struct binwrite_arg *)arg;
01009 long l = io_writable_length(p->fptr, p->length);
01010 return rb_write_internal(p->fptr->fd, p->ptr, l);
01011 }
01012
01013 static long
01014 io_binwrite(VALUE str, const char *ptr, long len, rb_io_t *fptr, int nosync)
01015 {
01016 long n, r, offset = 0;
01017
01018 if ((n = len) <= 0) return n;
01019 if (fptr->wbuf.ptr == NULL && !(!nosync && (fptr->mode & FMODE_SYNC))) {
01020 fptr->wbuf.off = 0;
01021 fptr->wbuf.len = 0;
01022 fptr->wbuf.capa = IO_WBUF_CAPA_MIN;
01023 fptr->wbuf.ptr = ALLOC_N(char, fptr->wbuf.capa);
01024 fptr->write_lock = rb_mutex_new();
01025 }
01026 if ((!nosync && (fptr->mode & (FMODE_SYNC|FMODE_TTY))) ||
01027 (fptr->wbuf.ptr && fptr->wbuf.capa <= fptr->wbuf.len + len)) {
01028 struct binwrite_arg arg;
01029
01030
01031 if (fptr->wbuf.len && fptr->wbuf.len+len <= fptr->wbuf.capa) {
01032 if (fptr->wbuf.capa < fptr->wbuf.off+fptr->wbuf.len+len) {
01033 MEMMOVE(fptr->wbuf.ptr, fptr->wbuf.ptr+fptr->wbuf.off, char, fptr->wbuf.len);
01034 fptr->wbuf.off = 0;
01035 }
01036 MEMMOVE(fptr->wbuf.ptr+fptr->wbuf.off+fptr->wbuf.len, ptr+offset, char, len);
01037 fptr->wbuf.len += (int)len;
01038 n = 0;
01039 }
01040 if (io_fflush(fptr) < 0)
01041 return -1L;
01042 if (n == 0)
01043 return len;
01044
01045
01046 if (fptr->stdio_file != stderr && !rb_thread_fd_writable(fptr->fd)) {
01047 rb_io_check_closed(fptr);
01048 }
01049 arg.fptr = fptr;
01050 arg.str = str;
01051 retry:
01052 arg.ptr = ptr + offset;
01053 arg.length = n;
01054 if (fptr->write_lock) {
01055 r = rb_mutex_synchronize(fptr->write_lock, io_binwrite_string, (VALUE)&arg);
01056 }
01057 else {
01058 long l = io_writable_length(fptr, n);
01059 r = rb_write_internal(fptr->fd, ptr+offset, l);
01060 }
01061
01062 if (r == n) return len;
01063 if (0 <= r) {
01064 offset += r;
01065 n -= r;
01066 errno = EAGAIN;
01067 }
01068 if (rb_io_wait_writable(fptr->fd)) {
01069 rb_io_check_closed(fptr);
01070 if (offset < len)
01071 goto retry;
01072 }
01073 return -1L;
01074 }
01075
01076 if (fptr->wbuf.off) {
01077 if (fptr->wbuf.len)
01078 MEMMOVE(fptr->wbuf.ptr, fptr->wbuf.ptr+fptr->wbuf.off, char, fptr->wbuf.len);
01079 fptr->wbuf.off = 0;
01080 }
01081 MEMMOVE(fptr->wbuf.ptr+fptr->wbuf.off+fptr->wbuf.len, ptr+offset, char, len);
01082 fptr->wbuf.len += (int)len;
01083 return len;
01084 }
01085
01086 # define MODE_BTMODE(a,b,c) ((fmode & FMODE_BINMODE) ? (b) : \
01087 (fmode & FMODE_TEXTMODE) ? (c) : (a))
01088 static VALUE
01089 do_writeconv(VALUE str, rb_io_t *fptr)
01090 {
01091 if (NEED_WRITECONV(fptr)) {
01092 VALUE common_encoding = Qnil;
01093 SET_BINARY_MODE(fptr);
01094
01095 make_writeconv(fptr);
01096
01097 if (fptr->writeconv) {
01098 #define fmode (fptr->mode)
01099 if (!NIL_P(fptr->writeconv_asciicompat))
01100 common_encoding = fptr->writeconv_asciicompat;
01101 else if (MODE_BTMODE(DEFAULT_TEXTMODE,0,1) && !rb_enc_asciicompat(rb_enc_get(str))) {
01102 rb_raise(rb_eArgError, "ASCII incompatible string written for text mode IO without encoding conversion: %s",
01103 rb_enc_name(rb_enc_get(str)));
01104 }
01105 #undef fmode
01106 }
01107 else {
01108 if (fptr->encs.enc2)
01109 common_encoding = rb_enc_from_encoding(fptr->encs.enc2);
01110 else if (fptr->encs.enc != rb_ascii8bit_encoding())
01111 common_encoding = rb_enc_from_encoding(fptr->encs.enc);
01112 }
01113
01114 if (!NIL_P(common_encoding)) {
01115 str = rb_str_encode(str, common_encoding,
01116 fptr->writeconv_pre_ecflags, fptr->writeconv_pre_ecopts);
01117 }
01118
01119 if (fptr->writeconv) {
01120 str = rb_econv_str_convert(fptr->writeconv, str, ECONV_PARTIAL_INPUT);
01121 }
01122 }
01123 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
01124 #define fmode (fptr->mode)
01125 else if (MODE_BTMODE(DEFAULT_TEXTMODE,0,1)) {
01126 if ((fptr->mode & FMODE_READABLE) &&
01127 !(fptr->encs.ecflags & ECONV_NEWLINE_DECORATOR_MASK)) {
01128 setmode(fptr->fd, O_BINARY);
01129 }
01130 else {
01131 setmode(fptr->fd, O_TEXT);
01132 }
01133 if (!rb_enc_asciicompat(rb_enc_get(str))) {
01134 rb_raise(rb_eArgError, "ASCII incompatible string written for text mode IO without encoding conversion: %s",
01135 rb_enc_name(rb_enc_get(str)));
01136 }
01137 }
01138 #undef fmode
01139 #endif
01140 return str;
01141 }
01142
01143 static long
01144 io_fwrite(VALUE str, rb_io_t *fptr, int nosync)
01145 {
01146 #ifdef _WIN32
01147 if (fptr->mode & FMODE_TTY) {
01148 long len = rb_w32_write_console(str, fptr->fd);
01149 if (len > 0) return len;
01150 }
01151 #endif
01152 str = do_writeconv(str, fptr);
01153 return io_binwrite(str, RSTRING_PTR(str), RSTRING_LEN(str),
01154 fptr, nosync);
01155 }
01156
01157 ssize_t
01158 rb_io_bufwrite(VALUE io, const void *buf, size_t size)
01159 {
01160 rb_io_t *fptr;
01161
01162 GetOpenFile(io, fptr);
01163 rb_io_check_writable(fptr);
01164 return (ssize_t)io_binwrite(0, buf, (long)size, fptr, 0);
01165 }
01166
01167 static VALUE
01168 io_write(VALUE io, VALUE str, int nosync)
01169 {
01170 rb_io_t *fptr;
01171 long n;
01172 VALUE tmp;
01173
01174 rb_secure(4);
01175 io = GetWriteIO(io);
01176 str = rb_obj_as_string(str);
01177 tmp = rb_io_check_io(io);
01178 if (NIL_P(tmp)) {
01179
01180 return rb_funcall(io, id_write, 1, str);
01181 }
01182 io = tmp;
01183 if (RSTRING_LEN(str) == 0) return INT2FIX(0);
01184
01185 GetOpenFile(io, fptr);
01186 rb_io_check_writable(fptr);
01187
01188 n = io_fwrite(str, fptr, nosync);
01189 if (n == -1L) rb_sys_fail_path(fptr->pathv);
01190
01191 return LONG2FIX(n);
01192 }
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212 static VALUE
01213 io_write_m(VALUE io, VALUE str)
01214 {
01215 return io_write(io, str, 0);
01216 }
01217
01218 VALUE
01219 rb_io_write(VALUE io, VALUE str)
01220 {
01221 return rb_funcall(io, id_write, 1, str);
01222 }
01223
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240 VALUE
01241 rb_io_addstr(VALUE io, VALUE str)
01242 {
01243 rb_io_write(io, str);
01244 return io;
01245 }
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260
01261
01262
01263 VALUE
01264 rb_io_flush(VALUE io)
01265 {
01266 rb_io_t *fptr;
01267
01268 if (TYPE(io) != T_FILE) {
01269 return rb_funcall(io, id_flush, 0);
01270 }
01271
01272 io = GetWriteIO(io);
01273 GetOpenFile(io, fptr);
01274
01275 if (fptr->mode & FMODE_WRITABLE) {
01276 if (io_fflush(fptr) < 0)
01277 rb_sys_fail(0);
01278 #ifdef _WIN32
01279 if (GetFileType((HANDLE)rb_w32_get_osfhandle(fptr->fd)) == FILE_TYPE_DISK) {
01280 fsync(fptr->fd);
01281 }
01282 #endif
01283 }
01284 if (fptr->mode & FMODE_READABLE) {
01285 io_unread(fptr);
01286 }
01287
01288 return io;
01289 }
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304 static VALUE
01305 rb_io_tell(VALUE io)
01306 {
01307 rb_io_t *fptr;
01308 off_t pos;
01309
01310 GetOpenFile(io, fptr);
01311 pos = io_tell(fptr);
01312 if (pos < 0 && errno) rb_sys_fail_path(fptr->pathv);
01313 pos -= fptr->rbuf.len;
01314 return OFFT2NUM(pos);
01315 }
01316
01317 static VALUE
01318 rb_io_seek(VALUE io, VALUE offset, int whence)
01319 {
01320 rb_io_t *fptr;
01321 off_t pos;
01322
01323 pos = NUM2OFFT(offset);
01324 GetOpenFile(io, fptr);
01325 pos = io_seek(fptr, pos, whence);
01326 if (pos < 0 && errno) rb_sys_fail_path(fptr->pathv);
01327
01328 return INT2FIX(0);
01329 }
01330
01331
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352 static VALUE
01353 rb_io_seek_m(int argc, VALUE *argv, VALUE io)
01354 {
01355 VALUE offset, ptrname;
01356 int whence = SEEK_SET;
01357
01358 if (rb_scan_args(argc, argv, "11", &offset, &ptrname) == 2) {
01359 whence = NUM2INT(ptrname);
01360 }
01361
01362 return rb_io_seek(io, offset, whence);
01363 }
01364
01365
01366
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376 static VALUE
01377 rb_io_set_pos(VALUE io, VALUE offset)
01378 {
01379 rb_io_t *fptr;
01380 off_t pos;
01381
01382 pos = NUM2OFFT(offset);
01383 GetOpenFile(io, fptr);
01384 pos = io_seek(fptr, pos, SEEK_SET);
01385 if (pos < 0 && errno) rb_sys_fail_path(fptr->pathv);
01386
01387 return OFFT2NUM(pos);
01388 }
01389
01390 static void clear_readconv(rb_io_t *fptr);
01391
01392
01393
01394
01395
01396
01397
01398
01399
01400
01401
01402
01403
01404
01405
01406
01407
01408 static VALUE
01409 rb_io_rewind(VALUE io)
01410 {
01411 rb_io_t *fptr;
01412
01413 GetOpenFile(io, fptr);
01414 if (io_seek(fptr, 0L, 0) < 0 && errno) rb_sys_fail_path(fptr->pathv);
01415 #ifdef _WIN32
01416 if (GetFileType((HANDLE)rb_w32_get_osfhandle(fptr->fd)) == FILE_TYPE_DISK) {
01417 fsync(fptr->fd);
01418 }
01419 #endif
01420 if (io == ARGF.current_file) {
01421 ARGF.lineno -= fptr->lineno;
01422 }
01423 fptr->lineno = 0;
01424 if (fptr->readconv) {
01425 clear_readconv(fptr);
01426 }
01427
01428 return INT2FIX(0);
01429 }
01430
01431 static int
01432 io_fillbuf(rb_io_t *fptr)
01433 {
01434 ssize_t r;
01435
01436 if (fptr->rbuf.ptr == NULL) {
01437 fptr->rbuf.off = 0;
01438 fptr->rbuf.len = 0;
01439 fptr->rbuf.capa = IO_RBUF_CAPA_FOR(fptr);
01440 fptr->rbuf.ptr = ALLOC_N(char, fptr->rbuf.capa);
01441 #ifdef _WIN32
01442 fptr->rbuf.capa--;
01443 #endif
01444 }
01445 if (fptr->rbuf.len == 0) {
01446 retry:
01447 {
01448 r = rb_read_internal(fptr->fd, fptr->rbuf.ptr, fptr->rbuf.capa);
01449 }
01450 if (r < 0) {
01451 if (rb_io_wait_readable(fptr->fd))
01452 goto retry;
01453 rb_sys_fail_path(fptr->pathv);
01454 }
01455 fptr->rbuf.off = 0;
01456 fptr->rbuf.len = (int)r;
01457 if (r == 0)
01458 return -1;
01459 }
01460 return 0;
01461 }
01462
01463
01464
01465
01466
01467
01468
01469
01470
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481
01482
01483
01484
01485
01486
01487
01488
01489
01490
01491
01492
01493
01494
01495
01496
01497 VALUE
01498 rb_io_eof(VALUE io)
01499 {
01500 rb_io_t *fptr;
01501
01502 GetOpenFile(io, fptr);
01503 rb_io_check_char_readable(fptr);
01504
01505 if (READ_CHAR_PENDING(fptr)) return Qfalse;
01506 if (READ_DATA_PENDING(fptr)) return Qfalse;
01507 READ_CHECK(fptr);
01508 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
01509 if (!NEED_READCONV(fptr) && NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {
01510 return eof(fptr->fd) ? Qtrue : Qfalse;
01511 }
01512 #endif
01513 if (io_fillbuf(fptr) < 0) {
01514 return Qtrue;
01515 }
01516 return Qfalse;
01517 }
01518
01519
01520
01521
01522
01523
01524
01525
01526
01527
01528
01529
01530
01531
01532 static VALUE
01533 rb_io_sync(VALUE io)
01534 {
01535 rb_io_t *fptr;
01536
01537 io = GetWriteIO(io);
01538 GetOpenFile(io, fptr);
01539 return (fptr->mode & FMODE_SYNC) ? Qtrue : Qfalse;
01540 }
01541
01542
01543
01544
01545
01546
01547
01548
01549
01550
01551
01552
01553
01554
01555
01556
01557 static VALUE
01558 rb_io_set_sync(VALUE io, VALUE sync)
01559 {
01560 rb_io_t *fptr;
01561
01562 io = GetWriteIO(io);
01563 GetOpenFile(io, fptr);
01564 if (RTEST(sync)) {
01565 fptr->mode |= FMODE_SYNC;
01566 }
01567 else {
01568 fptr->mode &= ~FMODE_SYNC;
01569 }
01570 return sync;
01571 }
01572
01573 #ifdef HAVE_FSYNC
01574 static VALUE nogvl_fsync(void *ptr)
01575 {
01576 rb_io_t *fptr = ptr;
01577
01578 return (VALUE)fsync(fptr->fd);
01579 }
01580
01581
01582
01583
01584
01585
01586
01587
01588
01589
01590
01591
01592
01593
01594
01595 static VALUE
01596 rb_io_fsync(VALUE io)
01597 {
01598 rb_io_t *fptr;
01599
01600 io = GetWriteIO(io);
01601 GetOpenFile(io, fptr);
01602
01603 if (io_fflush(fptr) < 0)
01604 rb_sys_fail(0);
01605 #ifndef _WIN32
01606 if ((int)rb_thread_io_blocking_region(nogvl_fsync, fptr, fptr->fd) < 0)
01607 rb_sys_fail_path(fptr->pathv);
01608 #endif
01609 return INT2FIX(0);
01610 }
01611 #else
01612 #define rb_io_fsync rb_f_notimplement
01613 #endif
01614
01615 #ifdef HAVE_FDATASYNC
01616 static VALUE nogvl_fdatasync(void *ptr)
01617 {
01618 rb_io_t *fptr = ptr;
01619
01620 return (VALUE)fdatasync(fptr->fd);
01621 }
01622
01623
01624
01625
01626
01627
01628
01629
01630
01631
01632
01633
01634 static VALUE
01635 rb_io_fdatasync(VALUE io)
01636 {
01637 rb_io_t *fptr;
01638
01639 io = GetWriteIO(io);
01640 GetOpenFile(io, fptr);
01641
01642 if (io_fflush(fptr) < 0)
01643 rb_sys_fail(0);
01644
01645 if ((int)rb_thread_io_blocking_region(nogvl_fdatasync, fptr, fptr->fd) == 0)
01646 return INT2FIX(0);
01647
01648
01649 return rb_io_fsync(io);
01650 }
01651 #else
01652 #define rb_io_fdatasync rb_io_fsync
01653 #endif
01654
01655
01656
01657
01658
01659
01660
01661
01662
01663
01664
01665
01666
01667 static VALUE
01668 rb_io_fileno(VALUE io)
01669 {
01670 rb_io_t *fptr;
01671 int fd;
01672
01673 GetOpenFile(io, fptr);
01674 fd = fptr->fd;
01675 return INT2FIX(fd);
01676 }
01677
01678
01679
01680
01681
01682
01683
01684
01685
01686
01687
01688
01689
01690
01691
01692
01693
01694
01695
01696
01697
01698
01699 static VALUE
01700 rb_io_pid(VALUE io)
01701 {
01702 rb_io_t *fptr;
01703
01704 GetOpenFile(io, fptr);
01705 if (!fptr->pid)
01706 return Qnil;
01707 return PIDT2NUM(fptr->pid);
01708 }
01709
01710
01711
01712
01713
01714
01715
01716
01717
01718 static VALUE
01719 rb_io_inspect(VALUE obj)
01720 {
01721 rb_io_t *fptr;
01722 VALUE result;
01723 static const char closed[] = " (closed)";
01724
01725 fptr = RFILE(rb_io_taint_check(obj))->fptr;
01726 if (!fptr) return rb_any_to_s(obj);
01727 result = rb_str_new_cstr("#<");
01728 rb_str_append(result, rb_class_name(CLASS_OF(obj)));
01729 rb_str_cat2(result, ":");
01730 if (NIL_P(fptr->pathv)) {
01731 if (fptr->fd < 0) {
01732 rb_str_cat(result, closed+1, strlen(closed)-1);
01733 }
01734 else {
01735 rb_str_catf(result, "fd %d", fptr->fd);
01736 }
01737 }
01738 else {
01739 rb_str_append(result, fptr->pathv);
01740 if (fptr->fd < 0) {
01741 rb_str_cat(result, closed, strlen(closed));
01742 }
01743 }
01744 return rb_str_cat2(result, ">");
01745 }
01746
01747
01748
01749
01750
01751
01752
01753
01754 static VALUE
01755 rb_io_to_io(VALUE io)
01756 {
01757 return io;
01758 }
01759
01760
01761 static long
01762 read_buffered_data(char *ptr, long len, rb_io_t *fptr)
01763 {
01764 int n;
01765
01766 n = READ_DATA_PENDING_COUNT(fptr);
01767 if (n <= 0) return 0;
01768 if (n > len) n = (int)len;
01769 MEMMOVE(ptr, fptr->rbuf.ptr+fptr->rbuf.off, char, n);
01770 fptr->rbuf.off += n;
01771 fptr->rbuf.len -= n;
01772 return n;
01773 }
01774
01775 static long
01776 io_bufread(char *ptr, long len, rb_io_t *fptr)
01777 {
01778 long offset = 0;
01779 long n = len;
01780 long c;
01781
01782 if (READ_DATA_PENDING(fptr) == 0) {
01783 while (n > 0) {
01784 again:
01785 c = rb_read_internal(fptr->fd, ptr+offset, n);
01786 if (c == 0) break;
01787 if (c < 0) {
01788 if (rb_io_wait_readable(fptr->fd))
01789 goto again;
01790 return -1;
01791 }
01792 offset += c;
01793 if ((n -= c) <= 0) break;
01794 rb_thread_wait_fd(fptr->fd);
01795 }
01796 return len - n;
01797 }
01798
01799 while (n > 0) {
01800 c = read_buffered_data(ptr+offset, n, fptr);
01801 if (c > 0) {
01802 offset += c;
01803 if ((n -= c) <= 0) break;
01804 }
01805 rb_thread_wait_fd(fptr->fd);
01806 rb_io_check_closed(fptr);
01807 if (io_fillbuf(fptr) < 0) {
01808 break;
01809 }
01810 }
01811 return len - n;
01812 }
01813
01814 static long
01815 io_fread(VALUE str, long offset, rb_io_t *fptr)
01816 {
01817 long len;
01818
01819 rb_str_locktmp(str);
01820 len = io_bufread(RSTRING_PTR(str) + offset, RSTRING_LEN(str) - offset,
01821 fptr);
01822 rb_str_unlocktmp(str);
01823 if (len < 0) rb_sys_fail_path(fptr->pathv);
01824 return len;
01825 }
01826
01827 ssize_t
01828 rb_io_bufread(VALUE io, void *buf, size_t size)
01829 {
01830 rb_io_t *fptr;
01831
01832 GetOpenFile(io, fptr);
01833 rb_io_check_readable(fptr);
01834 return (ssize_t)io_bufread(buf, (long)size, fptr);
01835 }
01836
01837 #define SMALLBUF 100
01838
01839 static long
01840 remain_size(rb_io_t *fptr)
01841 {
01842 struct stat st;
01843 off_t siz = READ_DATA_PENDING_COUNT(fptr);
01844 off_t pos;
01845
01846 if (fstat(fptr->fd, &st) == 0 && S_ISREG(st.st_mode)
01847 #if defined(__BEOS__) || defined(__HAIKU__)
01848 && (st.st_dev > 3)
01849 #endif
01850 )
01851 {
01852 if (io_fflush(fptr) < 0)
01853 rb_sys_fail(0);
01854 pos = lseek(fptr->fd, 0, SEEK_CUR);
01855 if (st.st_size >= pos && pos >= 0) {
01856 siz += st.st_size - pos;
01857 if (siz > LONG_MAX) {
01858 rb_raise(rb_eIOError, "file too big for single read");
01859 }
01860 }
01861 }
01862 else {
01863 siz += BUFSIZ;
01864 }
01865 return (long)siz;
01866 }
01867
01868 static VALUE
01869 io_enc_str(VALUE str, rb_io_t *fptr)
01870 {
01871 OBJ_TAINT(str);
01872 rb_enc_associate(str, io_read_encoding(fptr));
01873 return str;
01874 }
01875
01876 static void
01877 make_readconv(rb_io_t *fptr, int size)
01878 {
01879 if (!fptr->readconv) {
01880 int ecflags;
01881 VALUE ecopts;
01882 const char *sname, *dname;
01883 ecflags = fptr->encs.ecflags & ~ECONV_NEWLINE_DECORATOR_WRITE_MASK;
01884 ecopts = fptr->encs.ecopts;
01885 if (fptr->encs.enc2) {
01886 sname = rb_enc_name(fptr->encs.enc2);
01887 dname = rb_enc_name(fptr->encs.enc);
01888 }
01889 else {
01890 sname = dname = "";
01891 }
01892 fptr->readconv = rb_econv_open_opts(sname, dname, ecflags, ecopts);
01893 if (!fptr->readconv)
01894 rb_exc_raise(rb_econv_open_exc(sname, dname, ecflags));
01895 fptr->cbuf.off = 0;
01896 fptr->cbuf.len = 0;
01897 if (size < IO_CBUF_CAPA_MIN) size = IO_CBUF_CAPA_MIN;
01898 fptr->cbuf.capa = size;
01899 fptr->cbuf.ptr = ALLOC_N(char, fptr->cbuf.capa);
01900 }
01901 }
01902
01903 #define MORE_CHAR_SUSPENDED Qtrue
01904 #define MORE_CHAR_FINISHED Qnil
01905 static VALUE
01906 fill_cbuf(rb_io_t *fptr, int ec_flags)
01907 {
01908 const unsigned char *ss, *sp, *se;
01909 unsigned char *ds, *dp, *de;
01910 rb_econv_result_t res;
01911 int putbackable;
01912 int cbuf_len0;
01913 VALUE exc;
01914
01915 ec_flags |= ECONV_PARTIAL_INPUT;
01916
01917 if (fptr->cbuf.len == fptr->cbuf.capa)
01918 return MORE_CHAR_SUSPENDED;
01919 if (fptr->cbuf.len == 0)
01920 fptr->cbuf.off = 0;
01921 else if (fptr->cbuf.off + fptr->cbuf.len == fptr->cbuf.capa) {
01922 memmove(fptr->cbuf.ptr, fptr->cbuf.ptr+fptr->cbuf.off, fptr->cbuf.len);
01923 fptr->cbuf.off = 0;
01924 }
01925
01926 cbuf_len0 = fptr->cbuf.len;
01927
01928 while (1) {
01929 ss = sp = (const unsigned char *)fptr->rbuf.ptr + fptr->rbuf.off;
01930 se = sp + fptr->rbuf.len;
01931 ds = dp = (unsigned char *)fptr->cbuf.ptr + fptr->cbuf.off + fptr->cbuf.len;
01932 de = (unsigned char *)fptr->cbuf.ptr + fptr->cbuf.capa;
01933 res = rb_econv_convert(fptr->readconv, &sp, se, &dp, de, ec_flags);
01934 fptr->rbuf.off += (int)(sp - ss);
01935 fptr->rbuf.len -= (int)(sp - ss);
01936 fptr->cbuf.len += (int)(dp - ds);
01937
01938 putbackable = rb_econv_putbackable(fptr->readconv);
01939 if (putbackable) {
01940 rb_econv_putback(fptr->readconv, (unsigned char *)fptr->rbuf.ptr + fptr->rbuf.off - putbackable, putbackable);
01941 fptr->rbuf.off -= putbackable;
01942 fptr->rbuf.len += putbackable;
01943 }
01944
01945 exc = rb_econv_make_exception(fptr->readconv);
01946 if (!NIL_P(exc))
01947 return exc;
01948
01949 if (cbuf_len0 != fptr->cbuf.len)
01950 return MORE_CHAR_SUSPENDED;
01951
01952 if (res == econv_finished) {
01953 return MORE_CHAR_FINISHED;
01954 }
01955
01956 if (res == econv_source_buffer_empty) {
01957 if (fptr->rbuf.len == 0) {
01958 READ_CHECK(fptr);
01959 if (io_fillbuf(fptr) == -1) {
01960 if (!fptr->readconv) {
01961 return MORE_CHAR_FINISHED;
01962 }
01963 ds = dp = (unsigned char *)fptr->cbuf.ptr + fptr->cbuf.off + fptr->cbuf.len;
01964 de = (unsigned char *)fptr->cbuf.ptr + fptr->cbuf.capa;
01965 res = rb_econv_convert(fptr->readconv, NULL, NULL, &dp, de, 0);
01966 fptr->cbuf.len += (int)(dp - ds);
01967 rb_econv_check_error(fptr->readconv);
01968 break;
01969 }
01970 }
01971 }
01972 }
01973 if (cbuf_len0 != fptr->cbuf.len)
01974 return MORE_CHAR_SUSPENDED;
01975
01976 return MORE_CHAR_FINISHED;
01977 }
01978
01979 static VALUE
01980 more_char(rb_io_t *fptr)
01981 {
01982 VALUE v;
01983 v = fill_cbuf(fptr, ECONV_AFTER_OUTPUT);
01984 if (v != MORE_CHAR_SUSPENDED && v != MORE_CHAR_FINISHED)
01985 rb_exc_raise(v);
01986 return v;
01987 }
01988
01989 static VALUE
01990 io_shift_cbuf(rb_io_t *fptr, int len, VALUE *strp)
01991 {
01992 VALUE str = Qnil;
01993 if (strp) {
01994 str = *strp;
01995 if (NIL_P(str)) {
01996 *strp = str = rb_str_new(fptr->cbuf.ptr+fptr->cbuf.off, len);
01997 }
01998 else {
01999 rb_str_cat(str, fptr->cbuf.ptr+fptr->cbuf.off, len);
02000 }
02001 OBJ_TAINT(str);
02002 rb_enc_associate(str, fptr->encs.enc);
02003 }
02004 fptr->cbuf.off += len;
02005 fptr->cbuf.len -= len;
02006
02007 if (fptr->cbuf.len == 0)
02008 fptr->cbuf.off = 0;
02009 else if (fptr->cbuf.capa/2 < fptr->cbuf.off) {
02010 memmove(fptr->cbuf.ptr, fptr->cbuf.ptr+fptr->cbuf.off, fptr->cbuf.len);
02011 fptr->cbuf.off = 0;
02012 }
02013 return str;
02014 }
02015
02016 static void
02017 io_setstrbuf(VALUE *str,long len)
02018 {
02019 #ifdef _WIN32
02020 if (NIL_P(*str)) {
02021 *str = rb_str_new(0, len+1);
02022 rb_str_set_len(*str,len);
02023 }
02024 else {
02025 StringValue(*str);
02026 rb_str_modify(*str);
02027 rb_str_resize(*str, len+1);
02028 rb_str_set_len(*str,len);
02029 }
02030 #else
02031 if (NIL_P(*str)) {
02032 *str = rb_str_new(0, len);
02033 }
02034 else {
02035 StringValue(*str);
02036 rb_str_modify(*str);
02037 rb_str_resize(*str, len);
02038 }
02039 #endif
02040 }
02041
02042 static VALUE
02043 read_all(rb_io_t *fptr, long siz, VALUE str)
02044 {
02045 long bytes;
02046 long n;
02047 long pos;
02048 rb_encoding *enc;
02049 int cr;
02050
02051 if (NEED_READCONV(fptr)) {
02052 SET_BINARY_MODE(fptr);
02053 io_setstrbuf(&str,0);
02054 make_readconv(fptr, 0);
02055 while (1) {
02056 VALUE v;
02057 if (fptr->cbuf.len) {
02058 io_shift_cbuf(fptr, fptr->cbuf.len, &str);
02059 }
02060 v = fill_cbuf(fptr, 0);
02061 if (v != MORE_CHAR_SUSPENDED && v != MORE_CHAR_FINISHED) {
02062 if (fptr->cbuf.len) {
02063 io_shift_cbuf(fptr, fptr->cbuf.len, &str);
02064 }
02065 rb_exc_raise(v);
02066 }
02067 if (v == MORE_CHAR_FINISHED) {
02068 clear_readconv(fptr);
02069 return io_enc_str(str, fptr);
02070 }
02071 }
02072 }
02073
02074 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
02075 bytes = 0;
02076 pos = 0;
02077
02078 enc = io_read_encoding(fptr);
02079 cr = 0;
02080
02081 if (siz == 0) siz = BUFSIZ;
02082 io_setstrbuf(&str,siz);
02083 for (;;) {
02084 READ_CHECK(fptr);
02085 n = io_fread(str, bytes, fptr);
02086 if (n == 0 && bytes == 0) {
02087 break;
02088 }
02089 bytes += n;
02090 if (cr != ENC_CODERANGE_BROKEN)
02091 pos += rb_str_coderange_scan_restartable(RSTRING_PTR(str) + pos, RSTRING_PTR(str) + bytes, enc, &cr);
02092 if (bytes < siz) break;
02093 siz += BUFSIZ;
02094 rb_str_resize(str, siz);
02095 }
02096 if (bytes != siz) rb_str_resize(str, bytes);
02097 str = io_enc_str(str, fptr);
02098 ENC_CODERANGE_SET(str, cr);
02099 return str;
02100 }
02101
02102 void
02103 rb_io_set_nonblock(rb_io_t *fptr)
02104 {
02105 int oflags;
02106 #ifdef F_GETFL
02107 oflags = fcntl(fptr->fd, F_GETFL);
02108 if (oflags == -1) {
02109 rb_sys_fail_path(fptr->pathv);
02110 }
02111 #else
02112 oflags = 0;
02113 #endif
02114 if ((oflags & O_NONBLOCK) == 0) {
02115 oflags |= O_NONBLOCK;
02116 if (fcntl(fptr->fd, F_SETFL, oflags) == -1) {
02117 rb_sys_fail_path(fptr->pathv);
02118 }
02119 }
02120 }
02121
02122 static VALUE
02123 io_getpartial(int argc, VALUE *argv, VALUE io, int nonblock)
02124 {
02125 rb_io_t *fptr;
02126 VALUE length, str;
02127 long n, len;
02128
02129 rb_scan_args(argc, argv, "11", &length, &str);
02130
02131 if ((len = NUM2LONG(length)) < 0) {
02132 rb_raise(rb_eArgError, "negative length %ld given", len);
02133 }
02134
02135 io_setstrbuf(&str,len);
02136 OBJ_TAINT(str);
02137
02138 GetOpenFile(io, fptr);
02139 rb_io_check_byte_readable(fptr);
02140
02141 if (len == 0)
02142 return str;
02143
02144 if (!nonblock)
02145 READ_CHECK(fptr);
02146 n = read_buffered_data(RSTRING_PTR(str), len, fptr);
02147 if (n <= 0) {
02148 again:
02149 if (nonblock) {
02150 rb_io_set_nonblock(fptr);
02151 }
02152 rb_str_locktmp(str);
02153 n = rb_read_internal(fptr->fd, RSTRING_PTR(str), len);
02154 rb_str_unlocktmp(str);
02155 if (n < 0) {
02156 if (!nonblock && rb_io_wait_readable(fptr->fd))
02157 goto again;
02158 if (nonblock && (errno == EWOULDBLOCK || errno == EAGAIN))
02159 rb_mod_sys_fail(rb_mWaitReadable, "read would block");
02160 rb_sys_fail_path(fptr->pathv);
02161 }
02162 }
02163 rb_str_resize(str, n);
02164
02165 if (n == 0)
02166 return Qnil;
02167 else
02168 return str;
02169 }
02170
02171
02172
02173
02174
02175
02176
02177
02178
02179
02180
02181
02182
02183
02184
02185
02186
02187
02188
02189
02190
02191
02192
02193
02194
02195
02196
02197
02198
02199
02200
02201
02202
02203
02204
02205
02206
02207
02208
02209
02210
02211
02212
02213
02214
02215
02216
02217
02218
02219
02220
02221
02222
02223
02224
02225
02226
02227
02228 static VALUE
02229 io_readpartial(int argc, VALUE *argv, VALUE io)
02230 {
02231 VALUE ret;
02232
02233 ret = io_getpartial(argc, argv, io, 0);
02234 if (NIL_P(ret))
02235 rb_eof_error();
02236 else
02237 return ret;
02238 }
02239
02240
02241
02242
02243
02244
02245
02246
02247
02248
02249
02250
02251
02252
02253
02254
02255
02256
02257
02258
02259
02260
02261
02262
02263
02264
02265
02266
02267
02268
02269
02270
02271
02272
02273
02274
02275
02276
02277
02278
02279
02280
02281
02282
02283
02284
02285
02286
02287
02288
02289 static VALUE
02290 io_read_nonblock(int argc, VALUE *argv, VALUE io)
02291 {
02292 VALUE ret;
02293
02294 ret = io_getpartial(argc, argv, io, 1);
02295 if (NIL_P(ret))
02296 rb_eof_error();
02297 else
02298 return ret;
02299 }
02300
02301
02302
02303
02304
02305
02306
02307
02308
02309
02310
02311
02312
02313
02314
02315
02316
02317
02318
02319
02320
02321
02322
02323
02324
02325
02326
02327
02328
02329
02330
02331
02332
02333
02334
02335
02336
02337
02338
02339
02340
02341
02342
02343
02344
02345
02346
02347
02348
02349
02350
02351
02352
02353
02354 static VALUE
02355 rb_io_write_nonblock(VALUE io, VALUE str)
02356 {
02357 rb_io_t *fptr;
02358 long n;
02359
02360 rb_secure(4);
02361 if (TYPE(str) != T_STRING)
02362 str = rb_obj_as_string(str);
02363
02364 io = GetWriteIO(io);
02365 GetOpenFile(io, fptr);
02366 rb_io_check_writable(fptr);
02367
02368 if (io_fflush(fptr) < 0)
02369 rb_sys_fail(0);
02370
02371 rb_io_set_nonblock(fptr);
02372 n = write(fptr->fd, RSTRING_PTR(str), RSTRING_LEN(str));
02373
02374 if (n == -1) {
02375 if (errno == EWOULDBLOCK || errno == EAGAIN)
02376 rb_mod_sys_fail(rb_mWaitWritable, "write would block");
02377 rb_sys_fail_path(fptr->pathv);
02378 }
02379
02380 return LONG2FIX(n);
02381 }
02382
02383
02384
02385
02386
02387
02388
02389
02390
02391
02392
02393
02394
02395
02396
02397
02398
02399
02400
02401
02402
02403
02404
02405
02406
02407
02408
02409
02410
02411
02412
02413
02414
02415
02416
02417
02418
02419
02420
02421
02422
02423
02424
02425
02426
02427
02428
02429
02430
02431
02432
02433
02434
02435
02436
02437
02438
02439
02440
02441
02442
02443
02444 static VALUE
02445 io_read(int argc, VALUE *argv, VALUE io)
02446 {
02447 rb_io_t *fptr;
02448 long n, len;
02449 VALUE length, str;
02450 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
02451 int previous_mode;
02452 #endif
02453
02454 rb_scan_args(argc, argv, "02", &length, &str);
02455
02456 if (NIL_P(length)) {
02457 GetOpenFile(io, fptr);
02458 rb_io_check_char_readable(fptr);
02459 return read_all(fptr, remain_size(fptr), str);
02460 }
02461 len = NUM2LONG(length);
02462 if (len < 0) {
02463 rb_raise(rb_eArgError, "negative length %ld given", len);
02464 }
02465
02466 io_setstrbuf(&str,len);
02467
02468 GetOpenFile(io, fptr);
02469 rb_io_check_byte_readable(fptr);
02470 if (len == 0) return str;
02471
02472 READ_CHECK(fptr);
02473 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
02474 previous_mode = set_binary_mode_with_seek_cur(fptr);
02475 #endif
02476 n = io_fread(str, 0, fptr);
02477 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
02478 if (previous_mode == O_TEXT) {
02479 setmode(fptr->fd, O_TEXT);
02480 }
02481 #endif
02482 if (n == 0) {
02483 if (fptr->fd < 0) return Qnil;
02484 rb_str_resize(str, 0);
02485 return Qnil;
02486 }
02487 rb_str_resize(str, n);
02488 OBJ_TAINT(str);
02489
02490 return str;
02491 }
02492
02493 static void
02494 rscheck(const char *rsptr, long rslen, VALUE rs)
02495 {
02496 if (!rs) return;
02497 if (RSTRING_PTR(rs) != rsptr && RSTRING_LEN(rs) != rslen)
02498 rb_raise(rb_eRuntimeError, "rs modified");
02499 }
02500
02501 static int
02502 appendline(rb_io_t *fptr, int delim, VALUE *strp, long *lp)
02503 {
02504 VALUE str = *strp;
02505 long limit = *lp;
02506
02507 if (NEED_READCONV(fptr)) {
02508 SET_BINARY_MODE(fptr);
02509 make_readconv(fptr, 0);
02510 do {
02511 const char *p, *e;
02512 int searchlen;
02513 if (fptr->cbuf.len) {
02514 p = fptr->cbuf.ptr+fptr->cbuf.off;
02515 searchlen = fptr->cbuf.len;
02516 if (0 < limit && limit < searchlen)
02517 searchlen = (int)limit;
02518 e = memchr(p, delim, searchlen);
02519 if (e) {
02520 int len = (int)(e-p+1);
02521 if (NIL_P(str))
02522 *strp = str = rb_str_new(p, len);
02523 else
02524 rb_str_buf_cat(str, p, len);
02525 fptr->cbuf.off += len;
02526 fptr->cbuf.len -= len;
02527 limit -= len;
02528 *lp = limit;
02529 return delim;
02530 }
02531
02532 if (NIL_P(str))
02533 *strp = str = rb_str_new(p, searchlen);
02534 else
02535 rb_str_buf_cat(str, p, searchlen);
02536 fptr->cbuf.off += searchlen;
02537 fptr->cbuf.len -= searchlen;
02538 limit -= searchlen;
02539
02540 if (limit == 0) {
02541 *lp = limit;
02542 return (unsigned char)RSTRING_PTR(str)[RSTRING_LEN(str)-1];
02543 }
02544 }
02545 } while (more_char(fptr) != MORE_CHAR_FINISHED);
02546 clear_readconv(fptr);
02547 *lp = limit;
02548 return EOF;
02549 }
02550
02551 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
02552 do {
02553 long pending = READ_DATA_PENDING_COUNT(fptr);
02554 if (pending > 0) {
02555 const char *p = READ_DATA_PENDING_PTR(fptr);
02556 const char *e;
02557 long last;
02558
02559 if (limit > 0 && pending > limit) pending = limit;
02560 e = memchr(p, delim, pending);
02561 if (e) pending = e - p + 1;
02562 if (!NIL_P(str)) {
02563 last = RSTRING_LEN(str);
02564 rb_str_resize(str, last + pending);
02565 }
02566 else {
02567 last = 0;
02568 *strp = str = rb_str_buf_new(pending);
02569 rb_str_set_len(str, pending);
02570 }
02571 read_buffered_data(RSTRING_PTR(str) + last, pending, fptr);
02572 limit -= pending;
02573 *lp = limit;
02574 if (e) return delim;
02575 if (limit == 0)
02576 return (unsigned char)RSTRING_PTR(str)[RSTRING_LEN(str)-1];
02577 }
02578 READ_CHECK(fptr);
02579 } while (io_fillbuf(fptr) >= 0);
02580 *lp = limit;
02581 return EOF;
02582 }
02583
02584 static inline int
02585 swallow(rb_io_t *fptr, int term)
02586 {
02587 if (NEED_READCONV(fptr)) {
02588 rb_encoding *enc = io_read_encoding(fptr);
02589 int needconv = rb_enc_mbminlen(enc) != 1;
02590 SET_BINARY_MODE(fptr);
02591 make_readconv(fptr, 0);
02592 do {
02593 size_t cnt;
02594 while ((cnt = READ_CHAR_PENDING_COUNT(fptr)) > 0) {
02595 const char *p = READ_CHAR_PENDING_PTR(fptr);
02596 int i;
02597 if (!needconv) {
02598 if (*p != term) return TRUE;
02599 i = (int)cnt;
02600 while (--i && *++p == term);
02601 }
02602 else {
02603 const char *e = p + cnt;
02604 if (rb_enc_ascget(p, e, &i, enc) != term) return TRUE;
02605 while ((p += i) < e && rb_enc_ascget(p, e, &i, enc) == term);
02606 i = (int)(e - p);
02607 }
02608 io_shift_cbuf(fptr, (int)cnt - i, NULL);
02609 }
02610 } while (more_char(fptr) != MORE_CHAR_FINISHED);
02611 return FALSE;
02612 }
02613
02614 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
02615 do {
02616 size_t cnt;
02617 while ((cnt = READ_DATA_PENDING_COUNT(fptr)) > 0) {
02618 char buf[1024];
02619 const char *p = READ_DATA_PENDING_PTR(fptr);
02620 int i;
02621 if (cnt > sizeof buf) cnt = sizeof buf;
02622 if (*p != term) return TRUE;
02623 i = (int)cnt;
02624 while (--i && *++p == term);
02625 if (!read_buffered_data(buf, cnt - i, fptr))
02626 rb_sys_fail_path(fptr->pathv);
02627 }
02628 READ_CHECK(fptr);
02629 } while (io_fillbuf(fptr) == 0);
02630 return FALSE;
02631 }
02632
02633 static VALUE
02634 rb_io_getline_fast(rb_io_t *fptr, rb_encoding *enc, VALUE io)
02635 {
02636 VALUE str = Qnil;
02637 int len = 0;
02638 long pos = 0;
02639 int cr = 0;
02640
02641 for (;;) {
02642 int pending = READ_DATA_PENDING_COUNT(fptr);
02643
02644 if (pending > 0) {
02645 const char *p = READ_DATA_PENDING_PTR(fptr);
02646 const char *e;
02647
02648 e = memchr(p, '\n', pending);
02649 if (e) {
02650 pending = (int)(e - p + 1);
02651 }
02652 if (NIL_P(str)) {
02653 str = rb_str_new(p, pending);
02654 fptr->rbuf.off += pending;
02655 fptr->rbuf.len -= pending;
02656 }
02657 else {
02658 rb_str_resize(str, len + pending);
02659 read_buffered_data(RSTRING_PTR(str)+len, pending, fptr);
02660 }
02661 len += pending;
02662 if (cr != ENC_CODERANGE_BROKEN)
02663 pos += rb_str_coderange_scan_restartable(RSTRING_PTR(str) + pos, RSTRING_PTR(str) + len, enc, &cr);
02664 if (e) break;
02665 }
02666 READ_CHECK(fptr);
02667 if (io_fillbuf(fptr) < 0) {
02668 if (NIL_P(str)) return Qnil;
02669 break;
02670 }
02671 }
02672
02673 str = io_enc_str(str, fptr);
02674 ENC_CODERANGE_SET(str, cr);
02675 fptr->lineno++;
02676 if (io == ARGF.current_file) {
02677 ARGF.lineno++;
02678 ARGF.last_lineno = ARGF.lineno;
02679 }
02680 else {
02681 ARGF.last_lineno = fptr->lineno;
02682 }
02683
02684 return str;
02685 }
02686
02687 static void
02688 prepare_getline_args(int argc, VALUE *argv, VALUE *rsp, long *limit, VALUE io)
02689 {
02690 VALUE rs = rb_rs, lim = Qnil;
02691 rb_io_t *fptr;
02692
02693 if (argc == 1) {
02694 VALUE tmp = Qnil;
02695
02696 if (NIL_P(argv[0]) || !NIL_P(tmp = rb_check_string_type(argv[0]))) {
02697 rs = tmp;
02698 }
02699 else {
02700 lim = argv[0];
02701 }
02702 }
02703 else if (2 <= argc) {
02704 rb_scan_args(argc, argv, "2", &rs, &lim);
02705 if (!NIL_P(rs))
02706 StringValue(rs);
02707 }
02708 if (!NIL_P(rs)) {
02709 rb_encoding *enc_rs, *enc_io;
02710
02711 GetOpenFile(io, fptr);
02712 enc_rs = rb_enc_get(rs);
02713 enc_io = io_read_encoding(fptr);
02714 if (enc_io != enc_rs &&
02715 (rb_enc_str_coderange(rs) != ENC_CODERANGE_7BIT ||
02716 (RSTRING_LEN(rs) > 0 && !rb_enc_asciicompat(enc_io)))) {
02717 if (rs == rb_default_rs) {
02718 rs = rb_enc_str_new(0, 0, enc_io);
02719 rb_str_buf_cat_ascii(rs, "\n");
02720 }
02721 else {
02722 rb_raise(rb_eArgError, "encoding mismatch: %s IO with %s RS",
02723 rb_enc_name(enc_io),
02724 rb_enc_name(enc_rs));
02725 }
02726 }
02727 }
02728 *rsp = rs;
02729 *limit = NIL_P(lim) ? -1L : NUM2LONG(lim);
02730 }
02731
02732 static VALUE
02733 rb_io_getline_1(VALUE rs, long limit, VALUE io)
02734 {
02735 VALUE str = Qnil;
02736 rb_io_t *fptr;
02737 int nolimit = 0;
02738 rb_encoding *enc;
02739
02740 GetOpenFile(io, fptr);
02741 rb_io_check_char_readable(fptr);
02742 if (NIL_P(rs) && limit < 0) {
02743 str = read_all(fptr, 0, Qnil);
02744 if (RSTRING_LEN(str) == 0) return Qnil;
02745 }
02746 else if (limit == 0) {
02747 return rb_enc_str_new(0, 0, io_read_encoding(fptr));
02748 }
02749 else if (rs == rb_default_rs && limit < 0 && !NEED_READCONV(fptr) &&
02750 rb_enc_asciicompat(enc = io_read_encoding(fptr))) {
02751 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
02752 return rb_io_getline_fast(fptr, enc, io);
02753 }
02754 else {
02755 int c, newline = -1;
02756 const char *rsptr = 0;
02757 long rslen = 0;
02758 int rspara = 0;
02759 int extra_limit = 16;
02760
02761 SET_BINARY_MODE(fptr);
02762 enc = io_read_encoding(fptr);
02763
02764 if (!NIL_P(rs)) {
02765 rslen = RSTRING_LEN(rs);
02766 if (rslen == 0) {
02767 rsptr = "\n\n";
02768 rslen = 2;
02769 rspara = 1;
02770 swallow(fptr, '\n');
02771 rs = 0;
02772 if (!rb_enc_asciicompat(enc)) {
02773 rs = rb_usascii_str_new(rsptr, rslen);
02774 rs = rb_str_encode(rs, rb_enc_from_encoding(enc), 0, Qnil);
02775 OBJ_FREEZE(rs);
02776 rsptr = RSTRING_PTR(rs);
02777 rslen = RSTRING_LEN(rs);
02778 }
02779 }
02780 else {
02781 rsptr = RSTRING_PTR(rs);
02782 }
02783 newline = (unsigned char)rsptr[rslen - 1];
02784 }
02785
02786
02787 while ((c = appendline(fptr, newline, &str, &limit)) != EOF) {
02788 const char *s, *p, *pp, *e;
02789
02790 if (c == newline) {
02791 if (RSTRING_LEN(str) < rslen) continue;
02792 s = RSTRING_PTR(str);
02793 e = s + RSTRING_LEN(str);
02794 p = e - rslen;
02795 pp = rb_enc_left_char_head(s, p, e, enc);
02796 if (pp != p) continue;
02797 if (!rspara) rscheck(rsptr, rslen, rs);
02798 if (memcmp(p, rsptr, rslen) == 0) break;
02799 }
02800 if (limit == 0) {
02801 s = RSTRING_PTR(str);
02802 p = s + RSTRING_LEN(str);
02803 pp = rb_enc_left_char_head(s, p-1, p, enc);
02804 if (extra_limit &&
02805 MBCLEN_NEEDMORE_P(rb_enc_precise_mbclen(pp, p, enc))) {
02806
02807
02808 limit = 1;
02809 extra_limit--;
02810 }
02811 else {
02812 nolimit = 1;
02813 break;
02814 }
02815 }
02816 }
02817
02818 if (rspara) {
02819 if (c != EOF) {
02820 swallow(fptr, '\n');
02821 }
02822 }
02823 if (!NIL_P(str))
02824 str = io_enc_str(str, fptr);
02825 }
02826
02827 if (!NIL_P(str)) {
02828 if (!nolimit) {
02829 fptr->lineno++;
02830 if (io == ARGF.current_file) {
02831 ARGF.lineno++;
02832 ARGF.last_lineno = ARGF.lineno;
02833 }
02834 else {
02835 ARGF.last_lineno = fptr->lineno;
02836 }
02837 }
02838 }
02839
02840 return str;
02841 }
02842
02843 static VALUE
02844 rb_io_getline(int argc, VALUE *argv, VALUE io)
02845 {
02846 VALUE rs;
02847 long limit;
02848
02849 prepare_getline_args(argc, argv, &rs, &limit, io);
02850 return rb_io_getline_1(rs, limit, io);
02851 }
02852
02853 VALUE
02854 rb_io_gets(VALUE io)
02855 {
02856 return rb_io_getline_1(rb_default_rs, -1, io);
02857 }
02858
02859
02860
02861
02862
02863
02864
02865
02866
02867
02868
02869
02870
02871
02872
02873
02874
02875
02876
02877
02878
02879
02880 static VALUE
02881 rb_io_gets_m(int argc, VALUE *argv, VALUE io)
02882 {
02883 VALUE str;
02884
02885 str = rb_io_getline(argc, argv, io);
02886 rb_lastline_set(str);
02887
02888 return str;
02889 }
02890
02891
02892
02893
02894
02895
02896
02897
02898
02899
02900
02901
02902
02903
02904
02905
02906
02907
02908
02909
02910
02911
02912
02913 static VALUE
02914 rb_io_lineno(VALUE io)
02915 {
02916 rb_io_t *fptr;
02917
02918 GetOpenFile(io, fptr);
02919 rb_io_check_char_readable(fptr);
02920 return INT2NUM(fptr->lineno);
02921 }
02922
02923
02924
02925
02926
02927
02928
02929
02930
02931
02932
02933
02934
02935
02936
02937
02938
02939
02940 static VALUE
02941 rb_io_set_lineno(VALUE io, VALUE lineno)
02942 {
02943 rb_io_t *fptr;
02944
02945 GetOpenFile(io, fptr);
02946 rb_io_check_char_readable(fptr);
02947 fptr->lineno = NUM2INT(lineno);
02948 return lineno;
02949 }
02950
02951
02952
02953
02954
02955
02956
02957
02958
02959
02960
02961 static VALUE
02962 rb_io_readline(int argc, VALUE *argv, VALUE io)
02963 {
02964 VALUE line = rb_io_gets_m(argc, argv, io);
02965
02966 if (NIL_P(line)) {
02967 rb_eof_error();
02968 }
02969 return line;
02970 }
02971
02972
02973
02974
02975
02976
02977
02978
02979
02980
02981
02982
02983
02984
02985
02986
02987
02988
02989
02990 static VALUE
02991 rb_io_readlines(int argc, VALUE *argv, VALUE io)
02992 {
02993 VALUE line, ary, rs;
02994 long limit;
02995
02996 prepare_getline_args(argc, argv, &rs, &limit, io);
02997 if (limit == 0)
02998 rb_raise(rb_eArgError, "invalid limit: 0 for readlines");
02999 ary = rb_ary_new();
03000 while (!NIL_P(line = rb_io_getline_1(rs, limit, io))) {
03001 rb_ary_push(ary, line);
03002 }
03003 return ary;
03004 }
03005
03006
03007
03008
03009
03010
03011
03012
03013
03014
03015
03016
03017
03018
03019
03020
03021
03022
03023
03024
03025
03026
03027
03028
03029
03030
03031
03032
03033
03034
03035
03036
03037
03038
03039
03040 static VALUE
03041 rb_io_each_line(int argc, VALUE *argv, VALUE io)
03042 {
03043 VALUE str, rs;
03044 long limit;
03045
03046 RETURN_ENUMERATOR(io, argc, argv);
03047 prepare_getline_args(argc, argv, &rs, &limit, io);
03048 if (limit == 0)
03049 rb_raise(rb_eArgError, "invalid limit: 0 for each_line");
03050 while (!NIL_P(str = rb_io_getline_1(rs, limit, io))) {
03051 rb_yield(str);
03052 }
03053 return io;
03054 }
03055
03056
03057
03058
03059
03060
03061
03062
03063
03064
03065
03066
03067
03068
03069
03070
03071
03072
03073
03074
03075
03076 static VALUE
03077 rb_io_each_byte(VALUE io)
03078 {
03079 rb_io_t *fptr;
03080 char *p, *e;
03081
03082 RETURN_ENUMERATOR(io, 0, 0);
03083 GetOpenFile(io, fptr);
03084
03085 for (;;) {
03086 while (fptr->rbuf.len > 0) {
03087 p = fptr->rbuf.ptr + fptr->rbuf.off++;
03088 e = p + fptr->rbuf.len--;
03089 rb_yield(INT2FIX(*p & 0xff));
03090 errno = 0;
03091 }
03092 rb_io_check_byte_readable(fptr);
03093 READ_CHECK(fptr);
03094 if (io_fillbuf(fptr) < 0) {
03095 break;
03096 }
03097 }
03098 return io;
03099 }
03100
03101 static VALUE
03102 io_getc(rb_io_t *fptr, rb_encoding *enc)
03103 {
03104 int r, n, cr = 0;
03105 VALUE str;
03106
03107 if (NEED_READCONV(fptr)) {
03108 VALUE str = Qnil;
03109 rb_encoding *read_enc = io_read_encoding(fptr);
03110
03111 SET_BINARY_MODE(fptr);
03112 make_readconv(fptr, 0);
03113
03114 while (1) {
03115 if (fptr->cbuf.len) {
03116 r = rb_enc_precise_mbclen(fptr->cbuf.ptr+fptr->cbuf.off,
03117 fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
03118 read_enc);
03119 if (!MBCLEN_NEEDMORE_P(r))
03120 break;
03121 if (fptr->cbuf.len == fptr->cbuf.capa) {
03122 rb_raise(rb_eIOError, "too long character");
03123 }
03124 }
03125
03126 if (more_char(fptr) == MORE_CHAR_FINISHED) {
03127 if (fptr->cbuf.len == 0) {
03128 clear_readconv(fptr);
03129 return Qnil;
03130 }
03131
03132 str = rb_enc_str_new(fptr->cbuf.ptr+fptr->cbuf.off, 1, read_enc);
03133 fptr->cbuf.off += 1;
03134 fptr->cbuf.len -= 1;
03135 if (fptr->cbuf.len == 0) clear_readconv(fptr);
03136 ENC_CODERANGE_SET(str, ENC_CODERANGE_BROKEN);
03137 return str;
03138 }
03139 }
03140 if (MBCLEN_INVALID_P(r)) {
03141 r = rb_enc_mbclen(fptr->cbuf.ptr+fptr->cbuf.off,
03142 fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
03143 read_enc);
03144 io_shift_cbuf(fptr, r, &str);
03145 cr = ENC_CODERANGE_BROKEN;
03146 }
03147 else {
03148 io_shift_cbuf(fptr, MBCLEN_CHARFOUND_LEN(r), &str);
03149 cr = ISASCII(r) ? ENC_CODERANGE_7BIT : ENC_CODERANGE_VALID;
03150 }
03151 str = io_enc_str(str, fptr);
03152 ENC_CODERANGE_SET(str, cr);
03153 return str;
03154 }
03155
03156 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
03157 if (io_fillbuf(fptr) < 0) {
03158 return Qnil;
03159 }
03160 if (rb_enc_asciicompat(enc) && ISASCII(fptr->rbuf.ptr[fptr->rbuf.off])) {
03161 str = rb_str_new(fptr->rbuf.ptr+fptr->rbuf.off, 1);
03162 fptr->rbuf.off += 1;
03163 fptr->rbuf.len -= 1;
03164 cr = ENC_CODERANGE_7BIT;
03165 }
03166 else {
03167 r = rb_enc_precise_mbclen(fptr->rbuf.ptr+fptr->rbuf.off, fptr->rbuf.ptr+fptr->rbuf.off+fptr->rbuf.len, enc);
03168 if (MBCLEN_CHARFOUND_P(r) &&
03169 (n = MBCLEN_CHARFOUND_LEN(r)) <= fptr->rbuf.len) {
03170 str = rb_str_new(fptr->rbuf.ptr+fptr->rbuf.off, n);
03171 fptr->rbuf.off += n;
03172 fptr->rbuf.len -= n;
03173 cr = ENC_CODERANGE_VALID;
03174 }
03175 else if (MBCLEN_NEEDMORE_P(r)) {
03176 str = rb_str_new(fptr->rbuf.ptr+fptr->rbuf.off, fptr->rbuf.len);
03177 fptr->rbuf.len = 0;
03178 getc_needmore:
03179 if (io_fillbuf(fptr) != -1) {
03180 rb_str_cat(str, fptr->rbuf.ptr+fptr->rbuf.off, 1);
03181 fptr->rbuf.off++;
03182 fptr->rbuf.len--;
03183 r = rb_enc_precise_mbclen(RSTRING_PTR(str), RSTRING_PTR(str)+RSTRING_LEN(str), enc);
03184 if (MBCLEN_NEEDMORE_P(r)) {
03185 goto getc_needmore;
03186 }
03187 else if (MBCLEN_CHARFOUND_P(r)) {
03188 cr = ENC_CODERANGE_VALID;
03189 }
03190 }
03191 }
03192 else {
03193 str = rb_str_new(fptr->rbuf.ptr+fptr->rbuf.off, 1);
03194 fptr->rbuf.off++;
03195 fptr->rbuf.len--;
03196 }
03197 }
03198 if (!cr) cr = ENC_CODERANGE_BROKEN;
03199 str = io_enc_str(str, fptr);
03200 ENC_CODERANGE_SET(str, cr);
03201 return str;
03202 }
03203
03204
03205
03206
03207
03208
03209
03210
03211
03212
03213
03214
03215
03216
03217
03218
03219
03220
03221
03222 static VALUE
03223 rb_io_each_char(VALUE io)
03224 {
03225 rb_io_t *fptr;
03226 rb_encoding *enc;
03227 VALUE c;
03228
03229 RETURN_ENUMERATOR(io, 0, 0);
03230 GetOpenFile(io, fptr);
03231 rb_io_check_char_readable(fptr);
03232
03233 enc = io_input_encoding(fptr);
03234 READ_CHECK(fptr);
03235 while (!NIL_P(c = io_getc(fptr, enc))) {
03236 rb_yield(c);
03237 }
03238 return io;
03239 }
03240
03241
03242
03243
03244
03245
03246
03247
03248
03249
03250
03251
03252
03253
03254
03255
03256
03257 static VALUE
03258 rb_io_each_codepoint(VALUE io)
03259 {
03260 rb_io_t *fptr;
03261 rb_encoding *enc;
03262 unsigned int c;
03263 int r, n;
03264
03265 RETURN_ENUMERATOR(io, 0, 0);
03266 GetOpenFile(io, fptr);
03267 rb_io_check_char_readable(fptr);
03268
03269 READ_CHECK(fptr);
03270 if (NEED_READCONV(fptr)) {
03271 SET_BINARY_MODE(fptr);
03272 for (;;) {
03273 make_readconv(fptr, 0);
03274 for (;;) {
03275 if (fptr->cbuf.len) {
03276 if (fptr->encs.enc)
03277 r = rb_enc_precise_mbclen(fptr->cbuf.ptr+fptr->cbuf.off,
03278 fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
03279 fptr->encs.enc);
03280 else
03281 r = ONIGENC_CONSTRUCT_MBCLEN_CHARFOUND(1);
03282 if (!MBCLEN_NEEDMORE_P(r))
03283 break;
03284 if (fptr->cbuf.len == fptr->cbuf.capa) {
03285 rb_raise(rb_eIOError, "too long character");
03286 }
03287 }
03288 if (more_char(fptr) == MORE_CHAR_FINISHED) {
03289 clear_readconv(fptr);
03290
03291 return io;
03292 }
03293 }
03294 if (MBCLEN_INVALID_P(r)) {
03295 rb_raise(rb_eArgError, "invalid byte sequence in %s",
03296 rb_enc_name(fptr->encs.enc));
03297 }
03298 n = MBCLEN_CHARFOUND_LEN(r);
03299 if (fptr->encs.enc) {
03300 c = rb_enc_codepoint(fptr->cbuf.ptr+fptr->cbuf.off,
03301 fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
03302 fptr->encs.enc);
03303 }
03304 else {
03305 c = (unsigned char)fptr->cbuf.ptr[fptr->cbuf.off];
03306 }
03307 fptr->cbuf.off += n;
03308 fptr->cbuf.len -= n;
03309 rb_yield(UINT2NUM(c));
03310 }
03311 }
03312 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
03313 enc = io_input_encoding(fptr);
03314 for (;;) {
03315 if (io_fillbuf(fptr) < 0) {
03316 return io;
03317 }
03318 r = rb_enc_precise_mbclen(fptr->rbuf.ptr+fptr->rbuf.off,
03319 fptr->rbuf.ptr+fptr->rbuf.off+fptr->rbuf.len, enc);
03320 if (MBCLEN_CHARFOUND_P(r) &&
03321 (n = MBCLEN_CHARFOUND_LEN(r)) <= fptr->rbuf.len) {
03322 c = rb_enc_codepoint(fptr->rbuf.ptr+fptr->rbuf.off,
03323 fptr->rbuf.ptr+fptr->rbuf.off+fptr->rbuf.len, enc);
03324 fptr->rbuf.off += n;
03325 fptr->rbuf.len -= n;
03326 rb_yield(UINT2NUM(c));
03327 }
03328 else if (MBCLEN_INVALID_P(r)) {
03329 rb_raise(rb_eArgError, "invalid byte sequence in %s", rb_enc_name(enc));
03330 }
03331 else {
03332 continue;
03333 }
03334 }
03335 return io;
03336 }
03337
03338
03339
03340
03341
03342
03343
03344
03345
03346
03347
03348
03349
03350
03351
03352 static VALUE
03353 rb_io_getc(VALUE io)
03354 {
03355 rb_io_t *fptr;
03356 rb_encoding *enc;
03357
03358 GetOpenFile(io, fptr);
03359 rb_io_check_char_readable(fptr);
03360
03361 enc = io_input_encoding(fptr);
03362 READ_CHECK(fptr);
03363 return io_getc(fptr, enc);
03364 }
03365
03366
03367
03368
03369
03370
03371
03372
03373
03374
03375
03376
03377
03378 static VALUE
03379 rb_io_readchar(VALUE io)
03380 {
03381 VALUE c = rb_io_getc(io);
03382
03383 if (NIL_P(c)) {
03384 rb_eof_error();
03385 }
03386 return c;
03387 }
03388
03389
03390
03391
03392
03393
03394
03395
03396
03397
03398
03399
03400
03401 VALUE
03402 rb_io_getbyte(VALUE io)
03403 {
03404 rb_io_t *fptr;
03405 int c;
03406
03407 GetOpenFile(io, fptr);
03408 rb_io_check_byte_readable(fptr);
03409 READ_CHECK(fptr);
03410 if (fptr->fd == 0 && (fptr->mode & FMODE_TTY) && TYPE(rb_stdout) == T_FILE) {
03411 rb_io_t *ofp;
03412 GetOpenFile(rb_stdout, ofp);
03413 if (ofp->mode & FMODE_TTY) {
03414 rb_io_flush(rb_stdout);
03415 }
03416 }
03417 if (io_fillbuf(fptr) < 0) {
03418 return Qnil;
03419 }
03420 fptr->rbuf.off++;
03421 fptr->rbuf.len--;
03422 c = (unsigned char)fptr->rbuf.ptr[fptr->rbuf.off-1];
03423 return INT2FIX(c & 0xff);
03424 }
03425
03426
03427
03428
03429
03430
03431
03432
03433
03434 static VALUE
03435 rb_io_readbyte(VALUE io)
03436 {
03437 VALUE c = rb_io_getbyte(io);
03438
03439 if (NIL_P(c)) {
03440 rb_eof_error();
03441 }
03442 return c;
03443 }
03444
03445
03446
03447
03448
03449
03450
03451
03452
03453
03454
03455
03456
03457
03458
03459
03460
03461
03462 VALUE
03463 rb_io_ungetbyte(VALUE io, VALUE b)
03464 {
03465 rb_io_t *fptr;
03466
03467 GetOpenFile(io, fptr);
03468 rb_io_check_byte_readable(fptr);
03469 if (NIL_P(b)) return Qnil;
03470 if (FIXNUM_P(b)) {
03471 char cc = FIX2INT(b);
03472 b = rb_str_new(&cc, 1);
03473 }
03474 else {
03475 SafeStringValue(b);
03476 }
03477 io_ungetbyte(b, fptr);
03478 return Qnil;
03479 }
03480
03481
03482
03483
03484
03485
03486
03487
03488
03489
03490
03491
03492
03493
03494
03495
03496
03497 VALUE
03498 rb_io_ungetc(VALUE io, VALUE c)
03499 {
03500 rb_io_t *fptr;
03501 long len;
03502
03503 GetOpenFile(io, fptr);
03504 rb_io_check_char_readable(fptr);
03505 if (NIL_P(c)) return Qnil;
03506 if (FIXNUM_P(c)) {
03507 c = rb_enc_uint_chr(FIX2UINT(c), io_read_encoding(fptr));
03508 }
03509 else if (TYPE(c) == T_BIGNUM) {
03510 c = rb_enc_uint_chr(NUM2UINT(c), io_read_encoding(fptr));
03511 }
03512 else {
03513 SafeStringValue(c);
03514 }
03515 if (NEED_READCONV(fptr)) {
03516 SET_BINARY_MODE(fptr);
03517 len = RSTRING_LEN(c);
03518 #if SIZEOF_LONG > SIZEOF_INT
03519 if (len > INT_MAX)
03520 rb_raise(rb_eIOError, "ungetc failed");
03521 #endif
03522 make_readconv(fptr, (int)len);
03523 if (fptr->cbuf.capa - fptr->cbuf.len < len)
03524 rb_raise(rb_eIOError, "ungetc failed");
03525 if (fptr->cbuf.off < len) {
03526 MEMMOVE(fptr->cbuf.ptr+fptr->cbuf.capa-fptr->cbuf.len,
03527 fptr->cbuf.ptr+fptr->cbuf.off,
03528 char, fptr->cbuf.len);
03529 fptr->cbuf.off = fptr->cbuf.capa-fptr->cbuf.len;
03530 }
03531 fptr->cbuf.off -= (int)len;
03532 fptr->cbuf.len += (int)len;
03533 MEMMOVE(fptr->cbuf.ptr+fptr->cbuf.off, RSTRING_PTR(c), char, len);
03534 }
03535 else {
03536 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
03537 io_ungetbyte(c, fptr);
03538 }
03539 return Qnil;
03540 }
03541
03542
03543
03544
03545
03546
03547
03548
03549
03550
03551
03552
03553
03554 static VALUE
03555 rb_io_isatty(VALUE io)
03556 {
03557 rb_io_t *fptr;
03558
03559 GetOpenFile(io, fptr);
03560 if (isatty(fptr->fd) == 0)
03561 return Qfalse;
03562 return Qtrue;
03563 }
03564
03565 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
03566
03567
03568
03569
03570
03571
03572
03573
03574
03575
03576
03577
03578
03579
03580 static VALUE
03581 rb_io_close_on_exec_p(VALUE io)
03582 {
03583 rb_io_t *fptr;
03584 VALUE write_io;
03585 int fd, ret;
03586
03587 write_io = GetWriteIO(io);
03588 if (io != write_io) {
03589 GetOpenFile(write_io, fptr);
03590 if (fptr && 0 <= (fd = fptr->fd)) {
03591 if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
03592 if (!(ret & FD_CLOEXEC)) return Qfalse;
03593 }
03594 }
03595
03596 GetOpenFile(io, fptr);
03597 if (fptr && 0 <= (fd = fptr->fd)) {
03598 if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
03599 if (!(ret & FD_CLOEXEC)) return Qfalse;
03600 }
03601 return Qtrue;
03602 }
03603 #else
03604 #define rb_io_close_on_exec_p rb_f_notimplement
03605 #endif
03606
03607 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
03608
03609
03610
03611
03612
03613
03614
03615
03616
03617
03618
03619
03620 static VALUE
03621 rb_io_set_close_on_exec(VALUE io, VALUE arg)
03622 {
03623 int flag = RTEST(arg) ? FD_CLOEXEC : 0;
03624 rb_io_t *fptr;
03625 VALUE write_io;
03626 int fd, ret;
03627
03628 write_io = GetWriteIO(io);
03629 if (io != write_io) {
03630 GetOpenFile(write_io, fptr);
03631 if (fptr && 0 <= (fd = fptr->fd)) {
03632 if ((ret = fcntl(fptr->fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
03633 if ((ret & FD_CLOEXEC) != flag) {
03634 ret = (ret & ~FD_CLOEXEC) | flag;
03635 ret = fcntl(fd, F_SETFD, ret);
03636 if (ret == -1) rb_sys_fail_path(fptr->pathv);
03637 }
03638 }
03639
03640 }
03641
03642 GetOpenFile(io, fptr);
03643 if (fptr && 0 <= (fd = fptr->fd)) {
03644 if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
03645 if ((ret & FD_CLOEXEC) != flag) {
03646 ret = (ret & ~FD_CLOEXEC) | flag;
03647 ret = fcntl(fd, F_SETFD, ret);
03648 if (ret == -1) rb_sys_fail_path(fptr->pathv);
03649 }
03650 }
03651 return Qnil;
03652 }
03653 #else
03654 #define rb_io_set_close_on_exec rb_f_notimplement
03655 #endif
03656
03657 #define FMODE_PREP (1<<16)
03658 #define IS_PREP_STDIO(f) ((f)->mode & FMODE_PREP)
03659 #define PREP_STDIO_NAME(f) (RSTRING_PTR((f)->pathv))
03660
03661 static VALUE
03662 finish_writeconv(rb_io_t *fptr, int noalloc)
03663 {
03664 unsigned char *ds, *dp, *de;
03665 rb_econv_result_t res;
03666
03667 if (!fptr->wbuf.ptr) {
03668 unsigned char buf[1024];
03669 long r;
03670
03671 res = econv_destination_buffer_full;
03672 while (res == econv_destination_buffer_full) {
03673 ds = dp = buf;
03674 de = buf + sizeof(buf);
03675 res = rb_econv_convert(fptr->writeconv, NULL, NULL, &dp, de, 0);
03676 while (dp-ds) {
03677 retry:
03678 r = rb_write_internal(fptr->fd, ds, dp-ds);
03679 if (r == dp-ds)
03680 break;
03681 if (0 <= r) {
03682 ds += r;
03683 }
03684 if (rb_io_wait_writable(fptr->fd)) {
03685 if (fptr->fd < 0)
03686 return noalloc ? Qtrue : rb_exc_new3(rb_eIOError, rb_str_new_cstr("closed stream"));
03687 goto retry;
03688 }
03689 return noalloc ? Qtrue : INT2NUM(errno);
03690 }
03691 if (res == econv_invalid_byte_sequence ||
03692 res == econv_incomplete_input ||
03693 res == econv_undefined_conversion) {
03694 return noalloc ? Qtrue : rb_econv_make_exception(fptr->writeconv);
03695 }
03696 }
03697
03698 return Qnil;
03699 }
03700
03701 res = econv_destination_buffer_full;
03702 while (res == econv_destination_buffer_full) {
03703 if (fptr->wbuf.len == fptr->wbuf.capa) {
03704 if (io_fflush(fptr) < 0)
03705 return noalloc ? Qtrue : INT2NUM(errno);
03706 }
03707
03708 ds = dp = (unsigned char *)fptr->wbuf.ptr + fptr->wbuf.off + fptr->wbuf.len;
03709 de = (unsigned char *)fptr->wbuf.ptr + fptr->wbuf.capa;
03710 res = rb_econv_convert(fptr->writeconv, NULL, NULL, &dp, de, 0);
03711 fptr->wbuf.len += (int)(dp - ds);
03712 if (res == econv_invalid_byte_sequence ||
03713 res == econv_incomplete_input ||
03714 res == econv_undefined_conversion) {
03715 return noalloc ? Qtrue : rb_econv_make_exception(fptr->writeconv);
03716 }
03717 }
03718 return Qnil;
03719 }
03720
03721 struct finish_writeconv_arg {
03722 rb_io_t *fptr;
03723 int noalloc;
03724 };
03725
03726 static VALUE
03727 finish_writeconv_sync(VALUE arg)
03728 {
03729 struct finish_writeconv_arg *p = (struct finish_writeconv_arg *)arg;
03730 return finish_writeconv(p->fptr, p->noalloc);
03731 }
03732
03733 static void
03734 fptr_finalize(rb_io_t *fptr, int noraise)
03735 {
03736 VALUE err = Qnil;
03737 if (fptr->writeconv) {
03738 if (fptr->write_lock && !noraise) {
03739 struct finish_writeconv_arg arg;
03740 arg.fptr = fptr;
03741 arg.noalloc = noraise;
03742 err = rb_mutex_synchronize(fptr->write_lock, finish_writeconv_sync, (VALUE)&arg);
03743 }
03744 else {
03745 err = finish_writeconv(fptr, noraise);
03746 }
03747 }
03748 if (fptr->wbuf.len) {
03749 if (noraise) {
03750 if ((int)io_flush_buffer_sync(fptr) < 0 && NIL_P(err))
03751 err = Qtrue;
03752 }
03753 else {
03754 if (io_fflush(fptr) < 0 && NIL_P(err))
03755 err = INT2NUM(errno);
03756 }
03757 }
03758 if (IS_PREP_STDIO(fptr) || fptr->fd <= 2) {
03759 goto skip_fd_close;
03760 }
03761 if (fptr->stdio_file) {
03762
03763
03764 if (fclose(fptr->stdio_file) < 0 && NIL_P(err))
03765 err = noraise ? Qtrue : INT2NUM(errno);
03766 }
03767 else if (0 <= fptr->fd) {
03768
03769
03770
03771 if (close(fptr->fd) < 0 && NIL_P(err))
03772 err = noraise ? Qtrue : INT2NUM(errno);
03773 }
03774 skip_fd_close:
03775 fptr->fd = -1;
03776 fptr->stdio_file = 0;
03777 fptr->mode &= ~(FMODE_READABLE|FMODE_WRITABLE);
03778
03779 if (!NIL_P(err) && !noraise) {
03780 switch(TYPE(err)) {
03781 case T_FIXNUM:
03782 case T_BIGNUM:
03783 errno = NUM2INT(err);
03784 rb_sys_fail_path(fptr->pathv);
03785
03786 default:
03787 rb_exc_raise(err);
03788 }
03789 }
03790 }
03791
03792 static void
03793 rb_io_fptr_cleanup(rb_io_t *fptr, int noraise)
03794 {
03795 if (fptr->finalize) {
03796 (*fptr->finalize)(fptr, noraise);
03797 }
03798 else {
03799 fptr_finalize(fptr, noraise);
03800 }
03801 }
03802
03803 static void
03804 clear_readconv(rb_io_t *fptr)
03805 {
03806 if (fptr->readconv) {
03807 rb_econv_close(fptr->readconv);
03808 fptr->readconv = NULL;
03809 }
03810 if (fptr->cbuf.ptr) {
03811 free(fptr->cbuf.ptr);
03812 fptr->cbuf.ptr = NULL;
03813 }
03814 }
03815
03816 static void
03817 clear_writeconv(rb_io_t *fptr)
03818 {
03819 if (fptr->writeconv) {
03820 rb_econv_close(fptr->writeconv);
03821 fptr->writeconv = NULL;
03822 }
03823 fptr->writeconv_initialized = 0;
03824 }
03825
03826 static void
03827 clear_codeconv(rb_io_t *fptr)
03828 {
03829 clear_readconv(fptr);
03830 clear_writeconv(fptr);
03831 }
03832
03833 int
03834 rb_io_fptr_finalize(rb_io_t *fptr)
03835 {
03836 if (!fptr) return 0;
03837 fptr->pathv = Qnil;
03838 if (0 <= fptr->fd)
03839 rb_io_fptr_cleanup(fptr, TRUE);
03840 fptr->write_lock = 0;
03841 if (fptr->rbuf.ptr) {
03842 free(fptr->rbuf.ptr);
03843 fptr->rbuf.ptr = 0;
03844 }
03845 if (fptr->wbuf.ptr) {
03846 free(fptr->wbuf.ptr);
03847 fptr->wbuf.ptr = 0;
03848 }
03849 clear_codeconv(fptr);
03850 free(fptr);
03851 return 1;
03852 }
03853
03854 size_t rb_econv_memsize(rb_econv_t *);
03855
03856 RUBY_FUNC_EXPORTED size_t
03857 rb_io_memsize(const rb_io_t *fptr)
03858 {
03859 size_t size = sizeof(rb_io_t);
03860 size += fptr->rbuf.capa;
03861 size += fptr->wbuf.capa;
03862 size += fptr->cbuf.capa;
03863 if (fptr->readconv) size += rb_econv_memsize(fptr->readconv);
03864 if (fptr->writeconv) size += rb_econv_memsize(fptr->writeconv);
03865 return size;
03866 }
03867
03868 VALUE
03869 rb_io_close(VALUE io)
03870 {
03871 rb_io_t *fptr;
03872 int fd;
03873 VALUE write_io;
03874 rb_io_t *write_fptr;
03875
03876 write_io = GetWriteIO(io);
03877 if (io != write_io) {
03878 write_fptr = RFILE(write_io)->fptr;
03879 if (write_fptr && 0 <= write_fptr->fd) {
03880 rb_io_fptr_cleanup(write_fptr, TRUE);
03881 }
03882 }
03883
03884 fptr = RFILE(io)->fptr;
03885 if (!fptr) return Qnil;
03886 if (fptr->fd < 0) return Qnil;
03887
03888 fd = fptr->fd;
03889 #if defined __APPLE__ && defined(__MACH__) && \
03890 (!defined(MAC_OS_X_VERSION_MIN_ALLOWED) || MAC_OS_X_VERSION_MIN_ALLOWED <= 1050)
03891
03892
03893 rb_thread_fd_close(fd);
03894 #endif
03895 rb_io_fptr_cleanup(fptr, FALSE);
03896 rb_thread_fd_close(fd);
03897
03898 if (fptr->pid) {
03899 rb_syswait(fptr->pid);
03900 fptr->pid = 0;
03901 }
03902
03903 return Qnil;
03904 }
03905
03906
03907
03908
03909
03910
03911
03912
03913
03914
03915
03916
03917
03918
03919
03920 static VALUE
03921 rb_io_close_m(VALUE io)
03922 {
03923 if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(io)) {
03924 rb_raise(rb_eSecurityError, "Insecure: can't close");
03925 }
03926 rb_io_check_closed(RFILE(io)->fptr);
03927 rb_io_close(io);
03928 return Qnil;
03929 }
03930
03931 static VALUE
03932 io_call_close(VALUE io)
03933 {
03934 return rb_funcall(io, rb_intern("close"), 0, 0);
03935 }
03936
03937 static VALUE
03938 io_close(VALUE io)
03939 {
03940 return rb_rescue(io_call_close, io, 0, 0);
03941 }
03942
03943
03944
03945
03946
03947
03948
03949
03950
03951
03952
03953
03954
03955
03956
03957
03958
03959
03960
03961
03962 static VALUE
03963 rb_io_closed(VALUE io)
03964 {
03965 rb_io_t *fptr;
03966 VALUE write_io;
03967 rb_io_t *write_fptr;
03968
03969 write_io = GetWriteIO(io);
03970 if (io != write_io) {
03971 write_fptr = RFILE(write_io)->fptr;
03972 if (write_fptr && 0 <= write_fptr->fd) {
03973 return Qfalse;
03974 }
03975 }
03976
03977 fptr = RFILE(io)->fptr;
03978 rb_io_check_initialized(fptr);
03979 return 0 <= fptr->fd ? Qfalse : Qtrue;
03980 }
03981
03982
03983
03984
03985
03986
03987
03988
03989
03990
03991
03992
03993
03994
03995
03996
03997
03998
03999
04000 static VALUE
04001 rb_io_close_read(VALUE io)
04002 {
04003 rb_io_t *fptr;
04004 VALUE write_io;
04005
04006 if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(io)) {
04007 rb_raise(rb_eSecurityError, "Insecure: can't close");
04008 }
04009 GetOpenFile(io, fptr);
04010 if (is_socket(fptr->fd, fptr->pathv)) {
04011 #ifndef SHUT_RD
04012 # define SHUT_RD 0
04013 #endif
04014 if (shutdown(fptr->fd, SHUT_RD) < 0)
04015 rb_sys_fail_path(fptr->pathv);
04016 fptr->mode &= ~FMODE_READABLE;
04017 if (!(fptr->mode & FMODE_WRITABLE))
04018 return rb_io_close(io);
04019 return Qnil;
04020 }
04021
04022 write_io = GetWriteIO(io);
04023 if (io != write_io) {
04024 rb_io_t *wfptr;
04025 rb_io_fptr_cleanup(fptr, FALSE);
04026 GetOpenFile(write_io, wfptr);
04027 RFILE(io)->fptr = wfptr;
04028 RFILE(write_io)->fptr = NULL;
04029 rb_io_fptr_finalize(fptr);
04030 return Qnil;
04031 }
04032
04033 if (fptr->mode & FMODE_WRITABLE) {
04034 rb_raise(rb_eIOError, "closing non-duplex IO for reading");
04035 }
04036 return rb_io_close(io);
04037 }
04038
04039
04040
04041
04042
04043
04044
04045
04046
04047
04048
04049
04050
04051
04052
04053
04054
04055
04056
04057
04058 static VALUE
04059 rb_io_close_write(VALUE io)
04060 {
04061 rb_io_t *fptr;
04062 VALUE write_io;
04063
04064 if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(io)) {
04065 rb_raise(rb_eSecurityError, "Insecure: can't close");
04066 }
04067 write_io = GetWriteIO(io);
04068 GetOpenFile(write_io, fptr);
04069 if (is_socket(fptr->fd, fptr->pathv)) {
04070 #ifndef SHUT_WR
04071 # define SHUT_WR 1
04072 #endif
04073 if (shutdown(fptr->fd, SHUT_WR) < 0)
04074 rb_sys_fail_path(fptr->pathv);
04075 fptr->mode &= ~FMODE_WRITABLE;
04076 if (!(fptr->mode & FMODE_READABLE))
04077 return rb_io_close(write_io);
04078 return Qnil;
04079 }
04080
04081 if (fptr->mode & FMODE_READABLE) {
04082 rb_raise(rb_eIOError, "closing non-duplex IO for writing");
04083 }
04084
04085 rb_io_close(write_io);
04086 if (io != write_io) {
04087 GetOpenFile(io, fptr);
04088 fptr->tied_io_for_writing = 0;
04089 fptr->mode &= ~FMODE_DUPLEX;
04090 }
04091 return Qnil;
04092 }
04093
04094
04095
04096
04097
04098
04099
04100
04101
04102
04103
04104
04105
04106
04107 static VALUE
04108 rb_io_sysseek(int argc, VALUE *argv, VALUE io)
04109 {
04110 VALUE offset, ptrname;
04111 int whence = SEEK_SET;
04112 rb_io_t *fptr;
04113 off_t pos;
04114
04115 if (rb_scan_args(argc, argv, "11", &offset, &ptrname) == 2) {
04116 whence = NUM2INT(ptrname);
04117 }
04118 pos = NUM2OFFT(offset);
04119 GetOpenFile(io, fptr);
04120 if ((fptr->mode & FMODE_READABLE) &&
04121 (READ_DATA_BUFFERED(fptr) || READ_CHAR_PENDING(fptr))) {
04122 rb_raise(rb_eIOError, "sysseek for buffered IO");
04123 }
04124 if ((fptr->mode & FMODE_WRITABLE) && fptr->wbuf.len) {
04125 rb_warn("sysseek for buffered IO");
04126 }
04127 errno = 0;
04128 pos = lseek(fptr->fd, pos, whence);
04129 if (pos == -1 && errno) rb_sys_fail_path(fptr->pathv);
04130
04131 return OFFT2NUM(pos);
04132 }
04133
04134
04135
04136
04137
04138
04139
04140
04141
04142
04143
04144
04145
04146
04147 static VALUE
04148 rb_io_syswrite(VALUE io, VALUE str)
04149 {
04150 rb_io_t *fptr;
04151 long n;
04152
04153 rb_secure(4);
04154 if (TYPE(str) != T_STRING)
04155 str = rb_obj_as_string(str);
04156
04157 io = GetWriteIO(io);
04158 GetOpenFile(io, fptr);
04159 rb_io_check_writable(fptr);
04160
04161 if (fptr->wbuf.len) {
04162 rb_warn("syswrite for buffered IO");
04163 }
04164 if (!rb_thread_fd_writable(fptr->fd)) {
04165 rb_io_check_closed(fptr);
04166 }
04167
04168 n = rb_write_internal(fptr->fd, RSTRING_PTR(str), RSTRING_LEN(str));
04169
04170 if (n == -1) rb_sys_fail_path(fptr->pathv);
04171
04172 return LONG2FIX(n);
04173 }
04174
04175
04176
04177
04178
04179
04180
04181
04182
04183
04184
04185
04186
04187
04188
04189
04190
04191 static VALUE
04192 rb_io_sysread(int argc, VALUE *argv, VALUE io)
04193 {
04194 VALUE len, str;
04195 rb_io_t *fptr;
04196 long n, ilen;
04197
04198 rb_scan_args(argc, argv, "11", &len, &str);
04199 ilen = NUM2LONG(len);
04200
04201 io_setstrbuf(&str,ilen);
04202 if (ilen == 0) return str;
04203
04204 GetOpenFile(io, fptr);
04205 rb_io_check_byte_readable(fptr);
04206
04207 if (READ_DATA_BUFFERED(fptr)) {
04208 rb_raise(rb_eIOError, "sysread for buffered IO");
04209 }
04210
04211 n = fptr->fd;
04212 rb_thread_wait_fd(fptr->fd);
04213 rb_io_check_closed(fptr);
04214
04215 rb_str_locktmp(str);
04216 n = rb_read_internal(fptr->fd, RSTRING_PTR(str), ilen);
04217 rb_str_unlocktmp(str);
04218
04219 if (n == -1) {
04220 rb_sys_fail_path(fptr->pathv);
04221 }
04222 rb_str_set_len(str, n);
04223 if (n == 0 && ilen > 0) {
04224 rb_eof_error();
04225 }
04226 rb_str_resize(str, n);
04227 OBJ_TAINT(str);
04228
04229 return str;
04230 }
04231
04232 VALUE
04233 rb_io_binmode(VALUE io)
04234 {
04235 rb_io_t *fptr;
04236
04237 GetOpenFile(io, fptr);
04238 if (fptr->readconv)
04239 rb_econv_binmode(fptr->readconv);
04240 if (fptr->writeconv)
04241 rb_econv_binmode(fptr->writeconv);
04242 fptr->mode |= FMODE_BINMODE;
04243 fptr->mode &= ~FMODE_TEXTMODE;
04244 fptr->writeconv_pre_ecflags &= ~ECONV_NEWLINE_DECORATOR_MASK;
04245 #ifdef O_BINARY
04246 if (!fptr->readconv) {
04247 SET_BINARY_MODE_WITH_SEEK_CUR(fptr);
04248 }
04249 else {
04250 setmode(fptr->fd, O_BINARY);
04251 }
04252 #endif
04253 return io;
04254 }
04255
04256 VALUE
04257 rb_io_ascii8bit_binmode(VALUE io)
04258 {
04259 rb_io_t *fptr;
04260
04261 GetOpenFile(io, fptr);
04262 if (fptr->readconv) {
04263 rb_econv_close(fptr->readconv);
04264 fptr->readconv = NULL;
04265 }
04266 if (fptr->writeconv) {
04267 rb_econv_close(fptr->writeconv);
04268 fptr->writeconv = NULL;
04269 }
04270 fptr->mode |= FMODE_BINMODE;
04271 fptr->mode &= ~FMODE_TEXTMODE;
04272 SET_BINARY_MODE_WITH_SEEK_CUR(fptr);
04273
04274 fptr->encs.enc = rb_ascii8bit_encoding();
04275 fptr->encs.enc2 = NULL;
04276 fptr->encs.ecflags = 0;
04277 fptr->encs.ecopts = Qnil;
04278 clear_codeconv(fptr);
04279
04280 return io;
04281 }
04282
04283
04284
04285
04286
04287
04288
04289
04290
04291
04292
04293
04294
04295
04296 static VALUE
04297 rb_io_binmode_m(VALUE io)
04298 {
04299 VALUE write_io;
04300
04301 rb_io_ascii8bit_binmode(io);
04302
04303 write_io = GetWriteIO(io);
04304 if (write_io != io)
04305 rb_io_ascii8bit_binmode(write_io);
04306 return io;
04307 }
04308
04309
04310
04311
04312
04313
04314
04315 static VALUE
04316 rb_io_binmode_p(VALUE io)
04317 {
04318 rb_io_t *fptr;
04319 GetOpenFile(io, fptr);
04320 return fptr->mode & FMODE_BINMODE ? Qtrue : Qfalse;
04321 }
04322
04323 static const char*
04324 rb_io_fmode_modestr(int fmode)
04325 {
04326 if (fmode & FMODE_APPEND) {
04327 if ((fmode & FMODE_READWRITE) == FMODE_READWRITE) {
04328 return MODE_BTMODE("a+", "ab+", "at+");
04329 }
04330 return MODE_BTMODE("a", "ab", "at");
04331 }
04332 switch (fmode & FMODE_READWRITE) {
04333 case FMODE_READABLE:
04334 return MODE_BTMODE("r", "rb", "rt");
04335 case FMODE_WRITABLE:
04336 return MODE_BTMODE("w", "wb", "wt");
04337 case FMODE_READWRITE:
04338 if (fmode & FMODE_CREATE) {
04339 return MODE_BTMODE("w+", "wb+", "wt+");
04340 }
04341 return MODE_BTMODE("r+", "rb+", "rt+");
04342 }
04343 rb_raise(rb_eArgError, "invalid access fmode 0x%x", fmode);
04344 return NULL;
04345 }
04346
04347 static int
04348 io_encname_bom_p(const char *name, long len)
04349 {
04350 static const char bom_prefix[] = "bom|utf-";
04351 enum {bom_prefix_len = (int)sizeof(bom_prefix) - 1};
04352 if (!len) {
04353 const char *p = strchr(name, ':');
04354 len = p ? (long)(p - name) : (long)strlen(name);
04355 }
04356 return len > bom_prefix_len && STRNCASECMP(name, bom_prefix, bom_prefix_len) == 0;
04357 }
04358
04359 int
04360 rb_io_modestr_fmode(const char *modestr)
04361 {
04362 int fmode = 0;
04363 const char *m = modestr, *p = NULL;
04364
04365 switch (*m++) {
04366 case 'r':
04367 fmode |= FMODE_READABLE;
04368 break;
04369 case 'w':
04370 fmode |= FMODE_WRITABLE | FMODE_TRUNC | FMODE_CREATE;
04371 break;
04372 case 'a':
04373 fmode |= FMODE_WRITABLE | FMODE_APPEND | FMODE_CREATE;
04374 break;
04375 default:
04376 error:
04377 rb_raise(rb_eArgError, "invalid access mode %s", modestr);
04378 }
04379
04380 while (*m) {
04381 switch (*m++) {
04382 case 'b':
04383 fmode |= FMODE_BINMODE;
04384 break;
04385 case 't':
04386 fmode |= FMODE_TEXTMODE;
04387 break;
04388 case '+':
04389 fmode |= FMODE_READWRITE;
04390 break;
04391 default:
04392 goto error;
04393 case ':':
04394 p = m;
04395 goto finished;
04396 }
04397 }
04398
04399 finished:
04400 if ((fmode & FMODE_BINMODE) && (fmode & FMODE_TEXTMODE))
04401 goto error;
04402 if (p && io_encname_bom_p(p, 0))
04403 fmode |= FMODE_SETENC_BY_BOM;
04404
04405 return fmode;
04406 }
04407
04408 int
04409 rb_io_oflags_fmode(int oflags)
04410 {
04411 int fmode = 0;
04412
04413 switch (oflags & (O_RDONLY|O_WRONLY|O_RDWR)) {
04414 case O_RDONLY:
04415 fmode = FMODE_READABLE;
04416 break;
04417 case O_WRONLY:
04418 fmode = FMODE_WRITABLE;
04419 break;
04420 case O_RDWR:
04421 fmode = FMODE_READWRITE;
04422 break;
04423 }
04424
04425 if (oflags & O_APPEND) {
04426 fmode |= FMODE_APPEND;
04427 }
04428 if (oflags & O_TRUNC) {
04429 fmode |= FMODE_TRUNC;
04430 }
04431 if (oflags & O_CREAT) {
04432 fmode |= FMODE_CREATE;
04433 }
04434 #ifdef O_BINARY
04435 if (oflags & O_BINARY) {
04436 fmode |= FMODE_BINMODE;
04437 }
04438 #endif
04439
04440 return fmode;
04441 }
04442
04443 static int
04444 rb_io_fmode_oflags(int fmode)
04445 {
04446 int oflags = 0;
04447
04448 switch (fmode & FMODE_READWRITE) {
04449 case FMODE_READABLE:
04450 oflags |= O_RDONLY;
04451 break;
04452 case FMODE_WRITABLE:
04453 oflags |= O_WRONLY;
04454 break;
04455 case FMODE_READWRITE:
04456 oflags |= O_RDWR;
04457 break;
04458 }
04459
04460 if (fmode & FMODE_APPEND) {
04461 oflags |= O_APPEND;
04462 }
04463 if (fmode & FMODE_TRUNC) {
04464 oflags |= O_TRUNC;
04465 }
04466 if (fmode & FMODE_CREATE) {
04467 oflags |= O_CREAT;
04468 }
04469 #ifdef O_BINARY
04470 if (fmode & FMODE_BINMODE) {
04471 oflags |= O_BINARY;
04472 }
04473 #endif
04474
04475 return oflags;
04476 }
04477
04478 int
04479 rb_io_modestr_oflags(const char *modestr)
04480 {
04481 return rb_io_fmode_oflags(rb_io_modestr_fmode(modestr));
04482 }
04483
04484 static const char*
04485 rb_io_oflags_modestr(int oflags)
04486 {
04487 #ifdef O_BINARY
04488 # define MODE_BINARY(a,b) ((oflags & O_BINARY) ? (b) : (a))
04489 #else
04490 # define MODE_BINARY(a,b) (a)
04491 #endif
04492 int accmode = oflags & (O_RDONLY|O_WRONLY|O_RDWR);
04493 if (oflags & O_APPEND) {
04494 if (accmode == O_WRONLY) {
04495 return MODE_BINARY("a", "ab");
04496 }
04497 if (accmode == O_RDWR) {
04498 return MODE_BINARY("a+", "ab+");
04499 }
04500 }
04501 switch (oflags & (O_RDONLY|O_WRONLY|O_RDWR)) {
04502 case O_RDONLY:
04503 return MODE_BINARY("r", "rb");
04504 case O_WRONLY:
04505 return MODE_BINARY("w", "wb");
04506 case O_RDWR:
04507 return MODE_BINARY("r+", "rb+");
04508 }
04509 rb_raise(rb_eArgError, "invalid access oflags 0x%x", oflags);
04510 return NULL;
04511 }
04512
04513
04514
04515
04516
04517
04518 static void
04519 rb_io_ext_int_to_encs(rb_encoding *ext, rb_encoding *intern, rb_encoding **enc, rb_encoding **enc2)
04520 {
04521 int default_ext = 0;
04522
04523 if (ext == NULL) {
04524 ext = rb_default_external_encoding();
04525 default_ext = 1;
04526 }
04527 if (intern == NULL && ext != rb_ascii8bit_encoding())
04528
04529 intern = rb_default_internal_encoding();
04530 if (intern == NULL || intern == (rb_encoding *)Qnil || intern == ext) {
04531
04532 *enc = (default_ext && intern != ext) ? NULL : ext;
04533 *enc2 = NULL;
04534 }
04535 else {
04536 *enc = intern;
04537 *enc2 = ext;
04538 }
04539 }
04540
04541 static void
04542 parse_mode_enc(const char *estr, rb_encoding **enc_p, rb_encoding **enc2_p, int *fmode_p)
04543 {
04544 const char *p;
04545 char encname[ENCODING_MAXNAMELEN+1];
04546 int idx, idx2;
04547 rb_encoding *ext_enc, *int_enc;
04548
04549
04550
04551 p = strrchr(estr, ':');
04552 if (p) {
04553 long len = (p++) - estr;
04554 if (len == 0 || len > ENCODING_MAXNAMELEN)
04555 idx = -1;
04556 else {
04557 if (io_encname_bom_p(estr, len)) {
04558 if (fmode_p) *fmode_p |= FMODE_SETENC_BY_BOM;
04559 estr += 4;
04560 len -= 4;
04561 }
04562 memcpy(encname, estr, len);
04563 encname[len] = '\0';
04564 estr = encname;
04565 idx = rb_enc_find_index(encname);
04566 }
04567 }
04568 else {
04569 long len = strlen(estr);
04570 if (io_encname_bom_p(estr, len)) {
04571 if (fmode_p) *fmode_p |= FMODE_SETENC_BY_BOM;
04572 estr += 4;
04573 len -= 4;
04574 memcpy(encname, estr, len);
04575 encname[len] = '\0';
04576 estr = encname;
04577 }
04578 idx = rb_enc_find_index(estr);
04579 }
04580
04581 if (idx >= 0)
04582 ext_enc = rb_enc_from_index(idx);
04583 else {
04584 if (idx != -2)
04585 rb_warn("Unsupported encoding %s ignored", estr);
04586 ext_enc = NULL;
04587 }
04588
04589 int_enc = NULL;
04590 if (p) {
04591 if (*p == '-' && *(p+1) == '\0') {
04592
04593 int_enc = (rb_encoding *)Qnil;
04594 }
04595 else {
04596 idx2 = rb_enc_find_index(p);
04597 if (idx2 < 0)
04598 rb_warn("Unsupported encoding %s ignored", p);
04599 else if (idx2 == idx) {
04600 rb_warn("Ignoring internal encoding %s: it is identical to external encoding %s", p, estr);
04601 int_enc = (rb_encoding *)Qnil;
04602 }
04603 else
04604 int_enc = rb_enc_from_index(idx2);
04605 }
04606 }
04607
04608 rb_io_ext_int_to_encs(ext_enc, int_enc, enc_p, enc2_p);
04609 }
04610
04611 static void
04612 mode_enc(rb_io_t *fptr, const char *estr)
04613 {
04614 clear_codeconv(fptr);
04615
04616 parse_mode_enc(estr, &fptr->encs.enc, &fptr->encs.enc2, NULL);
04617 }
04618
04619 static void
04620 rb_io_mode_enc(rb_io_t *fptr, const char *modestr)
04621 {
04622 const char *p = strchr(modestr, ':');
04623 if (p) {
04624 mode_enc(fptr, p+1);
04625 }
04626 }
04627
04628 int
04629 rb_io_extract_encoding_option(VALUE opt, rb_encoding **enc_p, rb_encoding **enc2_p, int *fmode_p)
04630 {
04631 VALUE encoding=Qnil, extenc=Qundef, intenc=Qundef, tmp;
04632 int extracted = 0;
04633 rb_encoding *extencoding = NULL;
04634 rb_encoding *intencoding = NULL;
04635
04636 if (!NIL_P(opt)) {
04637 VALUE v;
04638 v = rb_hash_lookup2(opt, sym_encoding, Qnil);
04639 if (v != Qnil) encoding = v;
04640 v = rb_hash_lookup2(opt, sym_extenc, Qundef);
04641 if (v != Qnil) extenc = v;
04642 v = rb_hash_lookup2(opt, sym_intenc, Qundef);
04643 if (v != Qundef) intenc = v;
04644 }
04645 if ((extenc != Qundef || intenc != Qundef) && !NIL_P(encoding)) {
04646 if (!NIL_P(ruby_verbose)) {
04647 int idx = rb_to_encoding_index(encoding);
04648 rb_warn("Ignoring encoding parameter '%s': %s_encoding is used",
04649 idx < 0 ? StringValueCStr(encoding) : rb_enc_name(rb_enc_from_index(idx)),
04650 extenc == Qundef ? "internal" : "external");
04651 }
04652 encoding = Qnil;
04653 }
04654 if (extenc != Qundef && !NIL_P(extenc)) {
04655 extencoding = rb_to_encoding(extenc);
04656 }
04657 if (intenc != Qundef) {
04658 if (NIL_P(intenc)) {
04659
04660 intencoding = (rb_encoding *)Qnil;
04661 }
04662 else if (!NIL_P(tmp = rb_check_string_type(intenc))) {
04663 char *p = StringValueCStr(tmp);
04664
04665 if (*p == '-' && *(p+1) == '\0') {
04666
04667 intencoding = (rb_encoding *)Qnil;
04668 }
04669 else {
04670 intencoding = rb_to_encoding(intenc);
04671 }
04672 }
04673 else {
04674 intencoding = rb_to_encoding(intenc);
04675 }
04676 if (extencoding == intencoding) {
04677 intencoding = (rb_encoding *)Qnil;
04678 }
04679 }
04680 if (!NIL_P(encoding)) {
04681 extracted = 1;
04682 if (!NIL_P(tmp = rb_check_string_type(encoding))) {
04683 parse_mode_enc(StringValueCStr(tmp), enc_p, enc2_p, fmode_p);
04684 }
04685 else {
04686 rb_io_ext_int_to_encs(rb_to_encoding(encoding), NULL, enc_p, enc2_p);
04687 }
04688 }
04689 else if (extenc != Qundef || intenc != Qundef) {
04690 extracted = 1;
04691 rb_io_ext_int_to_encs(extencoding, intencoding, enc_p, enc2_p);
04692 }
04693 return extracted;
04694 }
04695
04696 typedef struct rb_io_enc_t convconfig_t;
04697
04698 static void
04699 validate_enc_binmode(int *fmode_p, int ecflags, rb_encoding *enc, rb_encoding *enc2)
04700 {
04701 int fmode = *fmode_p;
04702
04703 if ((fmode & FMODE_READABLE) &&
04704 !enc2 &&
04705 !(fmode & FMODE_BINMODE) &&
04706 !rb_enc_asciicompat(enc ? enc : rb_default_external_encoding()))
04707 rb_raise(rb_eArgError, "ASCII incompatible encoding needs binmode");
04708
04709 if (!(fmode & FMODE_BINMODE) &&
04710 (DEFAULT_TEXTMODE || (ecflags & ECONV_NEWLINE_DECORATOR_MASK))) {
04711 fmode |= DEFAULT_TEXTMODE;
04712 *fmode_p = fmode;
04713 }
04714 #if !DEFAULT_TEXTMODE
04715 else if (!(ecflags & ECONV_NEWLINE_DECORATOR_MASK)) {
04716 fmode &= ~FMODE_TEXTMODE;
04717 *fmode_p = fmode;
04718 }
04719 #endif
04720 }
04721
04722 static void
04723 extract_binmode(VALUE opthash, int *fmode)
04724 {
04725 if (!NIL_P(opthash)) {
04726 VALUE v;
04727 v = rb_hash_aref(opthash, sym_textmode);
04728 if (!NIL_P(v) && RTEST(v))
04729 *fmode |= FMODE_TEXTMODE;
04730 v = rb_hash_aref(opthash, sym_binmode);
04731 if (!NIL_P(v) && RTEST(v))
04732 *fmode |= FMODE_BINMODE;
04733
04734 if ((*fmode & FMODE_BINMODE) && (*fmode & FMODE_TEXTMODE))
04735 rb_raise(rb_eArgError, "both textmode and binmode specified");
04736 }
04737 }
04738
04739 static void
04740 rb_io_extract_modeenc(VALUE *vmode_p, VALUE *vperm_p, VALUE opthash,
04741 int *oflags_p, int *fmode_p, convconfig_t *convconfig_p)
04742 {
04743 VALUE vmode;
04744 int oflags, fmode;
04745 rb_encoding *enc, *enc2;
04746 int ecflags;
04747 VALUE ecopts;
04748 int has_enc = 0, has_vmode = 0;
04749 VALUE intmode;
04750
04751 vmode = *vmode_p;
04752
04753
04754 rb_io_ext_int_to_encs(NULL, NULL, &enc, &enc2);
04755
04756 vmode_handle:
04757 if (NIL_P(vmode)) {
04758 fmode = FMODE_READABLE;
04759 oflags = O_RDONLY;
04760 }
04761 else if (!NIL_P(intmode = rb_check_to_integer(vmode, "to_int"))) {
04762 vmode = intmode;
04763 oflags = NUM2INT(intmode);
04764 fmode = rb_io_oflags_fmode(oflags);
04765 }
04766 else {
04767 const char *p;
04768
04769 SafeStringValue(vmode);
04770 p = StringValueCStr(vmode);
04771 fmode = rb_io_modestr_fmode(p);
04772 oflags = rb_io_fmode_oflags(fmode);
04773 p = strchr(p, ':');
04774 if (p) {
04775 has_enc = 1;
04776 parse_mode_enc(p+1, &enc, &enc2, &fmode);
04777 }
04778 else {
04779 rb_encoding *e;
04780
04781 e = (fmode & FMODE_BINMODE) ? rb_ascii8bit_encoding() : NULL;
04782 rb_io_ext_int_to_encs(e, NULL, &enc, &enc2);
04783 }
04784 }
04785
04786 if (NIL_P(opthash)) {
04787 ecflags = (fmode & FMODE_READABLE) ?
04788 MODE_BTMODE(ECONV_DEFAULT_NEWLINE_DECORATOR,
04789 0, ECONV_UNIVERSAL_NEWLINE_DECORATOR) : 0;
04790 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
04791 ecflags |= (fmode & FMODE_WRITABLE) ?
04792 MODE_BTMODE(TEXTMODE_NEWLINE_DECORATOR_ON_WRITE,
04793 0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE) : 0;
04794 #endif
04795 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
04796 ecopts = Qnil;
04797 }
04798 else {
04799 VALUE v;
04800 extract_binmode(opthash, &fmode);
04801 #ifdef O_BINARY
04802 if (fmode & FMODE_BINMODE)
04803 oflags |= O_BINARY;
04804 #endif
04805 #if DEFAULT_TEXTMODE
04806 else if (NIL_P(vmode)) {
04807 fmode |= DEFAULT_TEXTMODE;
04808 }
04809 #endif
04810 if (!has_vmode) {
04811 v = rb_hash_aref(opthash, sym_mode);
04812 if (!NIL_P(v)) {
04813 if (!NIL_P(vmode)) {
04814 rb_raise(rb_eArgError, "mode specified twice");
04815 }
04816 has_vmode = 1;
04817 vmode = v;
04818 goto vmode_handle;
04819 }
04820 }
04821 v = rb_hash_aref(opthash, sym_perm);
04822 if (!NIL_P(v)) {
04823 if (vperm_p) {
04824 if (!NIL_P(*vperm_p)) {
04825 rb_raise(rb_eArgError, "perm specified twice");
04826 }
04827 *vperm_p = v;
04828 }
04829 else {
04830
04831 }
04832 }
04833 ecflags = (fmode & FMODE_READABLE) ?
04834 MODE_BTMODE(ECONV_DEFAULT_NEWLINE_DECORATOR,
04835 0, ECONV_UNIVERSAL_NEWLINE_DECORATOR) : 0;
04836 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
04837 ecflags |= (fmode & FMODE_WRITABLE) ?
04838 MODE_BTMODE(TEXTMODE_NEWLINE_DECORATOR_ON_WRITE,
04839 0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE) : 0;
04840 #endif
04841
04842 if (rb_io_extract_encoding_option(opthash, &enc, &enc2, &fmode)) {
04843 if (has_enc) {
04844 rb_raise(rb_eArgError, "encoding specified twice");
04845 }
04846 }
04847 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
04848 ecflags = rb_econv_prepare_options(opthash, &ecopts, ecflags);
04849 }
04850
04851 validate_enc_binmode(&fmode, ecflags, enc, enc2);
04852
04853 *vmode_p = vmode;
04854
04855 *oflags_p = oflags;
04856 *fmode_p = fmode;
04857 convconfig_p->enc = enc;
04858 convconfig_p->enc2 = enc2;
04859 convconfig_p->ecflags = ecflags;
04860 convconfig_p->ecopts = ecopts;
04861 }
04862
04863 struct sysopen_struct {
04864 VALUE fname;
04865 int oflags;
04866 mode_t perm;
04867 };
04868
04869 static VALUE
04870 sysopen_func(void *ptr)
04871 {
04872 const struct sysopen_struct *data = ptr;
04873 const char *fname = RSTRING_PTR(data->fname);
04874 return (VALUE)open(fname, data->oflags, data->perm);
04875 }
04876
04877 static inline int
04878 rb_sysopen_internal(struct sysopen_struct *data)
04879 {
04880 int fd;
04881 fd = (int)rb_thread_blocking_region(sysopen_func, data, RUBY_UBF_IO, 0);
04882 if (0 <= fd)
04883 rb_update_max_fd(fd);
04884 return fd;
04885 }
04886
04887 static int
04888 rb_sysopen(VALUE fname, int oflags, mode_t perm)
04889 {
04890 int fd;
04891 struct sysopen_struct data;
04892
04893 data.fname = rb_str_encode_ospath(fname);
04894 data.oflags = oflags;
04895 data.perm = perm;
04896
04897 fd = rb_sysopen_internal(&data);
04898 if (fd < 0) {
04899 if (errno == EMFILE || errno == ENFILE) {
04900 rb_gc();
04901 fd = rb_sysopen_internal(&data);
04902 }
04903 if (fd < 0) {
04904 rb_sys_fail_path(fname);
04905 }
04906 }
04907 rb_update_max_fd(fd);
04908 return fd;
04909 }
04910
04911 FILE *
04912 rb_fdopen(int fd, const char *modestr)
04913 {
04914 FILE *file;
04915
04916 #if defined(sun)
04917 errno = 0;
04918 #endif
04919 file = fdopen(fd, modestr);
04920 if (!file) {
04921 if (
04922 #if defined(sun)
04923 errno == 0 ||
04924 #endif
04925 errno == EMFILE || errno == ENFILE) {
04926 rb_gc();
04927 #if defined(sun)
04928 errno = 0;
04929 #endif
04930 file = fdopen(fd, modestr);
04931 }
04932 if (!file) {
04933 #ifdef _WIN32
04934 if (errno == 0) errno = EINVAL;
04935 #elif defined(sun)
04936 if (errno == 0) errno = EMFILE;
04937 #endif
04938 rb_sys_fail(0);
04939 }
04940 }
04941
04942
04943 #ifdef USE_SETVBUF
04944 if (setvbuf(file, NULL, _IOFBF, 0) != 0)
04945 rb_warn("setvbuf() can't be honoured (fd=%d)", fd);
04946 #endif
04947 return file;
04948 }
04949
04950 static void
04951 io_check_tty(rb_io_t *fptr)
04952 {
04953 if (isatty(fptr->fd))
04954 fptr->mode |= FMODE_TTY|FMODE_DUPLEX;
04955 }
04956
04957 static VALUE rb_io_internal_encoding(VALUE);
04958 static void io_encoding_set(rb_io_t *, VALUE, VALUE, VALUE);
04959
04960 static int
04961 io_strip_bom(VALUE io)
04962 {
04963 VALUE b1, b2, b3, b4;
04964
04965 if (NIL_P(b1 = rb_io_getbyte(io))) return 0;
04966 switch (b1) {
04967 case INT2FIX(0xEF):
04968 if (NIL_P(b2 = rb_io_getbyte(io))) break;
04969 if (b2 == INT2FIX(0xBB) && !NIL_P(b3 = rb_io_getbyte(io))) {
04970 if (b3 == INT2FIX(0xBF)) {
04971 return rb_utf8_encindex();
04972 }
04973 rb_io_ungetbyte(io, b3);
04974 }
04975 rb_io_ungetbyte(io, b2);
04976 break;
04977
04978 case INT2FIX(0xFE):
04979 if (NIL_P(b2 = rb_io_getbyte(io))) break;
04980 if (b2 == INT2FIX(0xFF)) {
04981 return rb_enc_find_index("UTF-16BE");
04982 }
04983 rb_io_ungetbyte(io, b2);
04984 break;
04985
04986 case INT2FIX(0xFF):
04987 if (NIL_P(b2 = rb_io_getbyte(io))) break;
04988 if (b2 == INT2FIX(0xFE)) {
04989 b3 = rb_io_getbyte(io);
04990 if (b3 == INT2FIX(0) && !NIL_P(b4 = rb_io_getbyte(io))) {
04991 if (b4 == INT2FIX(0)) {
04992 return rb_enc_find_index("UTF-32LE");
04993 }
04994 rb_io_ungetbyte(io, b4);
04995 rb_io_ungetbyte(io, b3);
04996 }
04997 else {
04998 rb_io_ungetbyte(io, b3);
04999 return rb_enc_find_index("UTF-16LE");
05000 }
05001 }
05002 rb_io_ungetbyte(io, b2);
05003 break;
05004
05005 case INT2FIX(0):
05006 if (NIL_P(b2 = rb_io_getbyte(io))) break;
05007 if (b2 == INT2FIX(0) && !NIL_P(b3 = rb_io_getbyte(io))) {
05008 if (b3 == INT2FIX(0xFE) && !NIL_P(b4 = rb_io_getbyte(io))) {
05009 if (b4 == INT2FIX(0xFF)) {
05010 return rb_enc_find_index("UTF-32BE");
05011 }
05012 rb_io_ungetbyte(io, b4);
05013 }
05014 rb_io_ungetbyte(io, b3);
05015 }
05016 rb_io_ungetbyte(io, b2);
05017 break;
05018 }
05019 rb_io_ungetbyte(io, b1);
05020 return 0;
05021 }
05022
05023 static void
05024 io_set_encoding_by_bom(VALUE io)
05025 {
05026 int idx = io_strip_bom(io);
05027
05028 if (idx) {
05029 rb_io_t *fptr;
05030 GetOpenFile(io, fptr);
05031 io_encoding_set(fptr, rb_enc_from_encoding(rb_enc_from_index(idx)),
05032 rb_io_internal_encoding(io), Qnil);
05033 }
05034 }
05035
05036 static VALUE
05037 rb_file_open_generic(VALUE io, VALUE filename, int oflags, int fmode, convconfig_t *convconfig, mode_t perm)
05038 {
05039 rb_io_t *fptr;
05040 convconfig_t cc;
05041 if (!convconfig) {
05042
05043 rb_io_ext_int_to_encs(NULL, NULL, &cc.enc, &cc.enc2);
05044 cc.ecflags = 0;
05045 cc.ecopts = Qnil;
05046 convconfig = &cc;
05047 }
05048 validate_enc_binmode(&fmode, convconfig->ecflags,
05049 convconfig->enc, convconfig->enc2);
05050
05051 MakeOpenFile(io, fptr);
05052 fptr->mode = fmode;
05053 fptr->encs = *convconfig;
05054 fptr->pathv = rb_str_new_frozen(filename);
05055 fptr->fd = rb_sysopen(fptr->pathv, oflags, perm);
05056 io_check_tty(fptr);
05057 if (fmode & FMODE_SETENC_BY_BOM) io_set_encoding_by_bom(io);
05058
05059 return io;
05060 }
05061
05062 static VALUE
05063 rb_file_open_internal(VALUE io, VALUE filename, const char *modestr)
05064 {
05065 int fmode = rb_io_modestr_fmode(modestr);
05066 const char *p = strchr(modestr, ':');
05067 convconfig_t convconfig;
05068
05069 if (p) {
05070 parse_mode_enc(p+1, &convconfig.enc, &convconfig.enc2, &fmode);
05071 }
05072 else {
05073 rb_encoding *e;
05074
05075
05076 e = (fmode & FMODE_BINMODE) ? rb_ascii8bit_encoding() : NULL;
05077 rb_io_ext_int_to_encs(e, NULL, &convconfig.enc, &convconfig.enc2);
05078 convconfig.ecflags = 0;
05079 convconfig.ecopts = Qnil;
05080 }
05081
05082 return rb_file_open_generic(io, filename,
05083 rb_io_fmode_oflags(fmode),
05084 fmode,
05085 &convconfig,
05086 0666);
05087 }
05088
05089 VALUE
05090 rb_file_open_str(VALUE fname, const char *modestr)
05091 {
05092 FilePathValue(fname);
05093 return rb_file_open_internal(io_alloc(rb_cFile), fname, modestr);
05094 }
05095
05096 VALUE
05097 rb_file_open(const char *fname, const char *modestr)
05098 {
05099 return rb_file_open_internal(io_alloc(rb_cFile), rb_str_new_cstr(fname), modestr);
05100 }
05101
05102 #if defined(__CYGWIN__) || !defined(HAVE_FORK)
05103 static struct pipe_list {
05104 rb_io_t *fptr;
05105 struct pipe_list *next;
05106 } *pipe_list;
05107
05108 static void
05109 pipe_add_fptr(rb_io_t *fptr)
05110 {
05111 struct pipe_list *list;
05112
05113 list = ALLOC(struct pipe_list);
05114 list->fptr = fptr;
05115 list->next = pipe_list;
05116 pipe_list = list;
05117 }
05118
05119 static void
05120 pipe_del_fptr(rb_io_t *fptr)
05121 {
05122 struct pipe_list *list = pipe_list;
05123 struct pipe_list *tmp;
05124
05125 if (list->fptr == fptr) {
05126 pipe_list = list->next;
05127 free(list);
05128 return;
05129 }
05130
05131 while (list->next) {
05132 if (list->next->fptr == fptr) {
05133 tmp = list->next;
05134 list->next = list->next->next;
05135 free(tmp);
05136 return;
05137 }
05138 list = list->next;
05139 }
05140 }
05141
05142 static void
05143 pipe_atexit(void)
05144 {
05145 struct pipe_list *list = pipe_list;
05146 struct pipe_list *tmp;
05147
05148 while (list) {
05149 tmp = list->next;
05150 rb_io_fptr_finalize(list->fptr);
05151 list = tmp;
05152 }
05153 }
05154
05155 static void
05156 pipe_finalize(rb_io_t *fptr, int noraise)
05157 {
05158 #if !defined(HAVE_FORK) && !defined(_WIN32)
05159 int status = 0;
05160 if (fptr->stdio_file) {
05161 status = pclose(fptr->stdio_file);
05162 }
05163 fptr->fd = -1;
05164 fptr->stdio_file = 0;
05165 rb_last_status_set(status, fptr->pid);
05166 #else
05167 fptr_finalize(fptr, noraise);
05168 #endif
05169 pipe_del_fptr(fptr);
05170 }
05171 #endif
05172
05173 void
05174 rb_io_synchronized(rb_io_t *fptr)
05175 {
05176 rb_io_check_initialized(fptr);
05177 fptr->mode |= FMODE_SYNC;
05178 }
05179
05180 void
05181 rb_io_unbuffered(rb_io_t *fptr)
05182 {
05183 rb_io_synchronized(fptr);
05184 }
05185
05186 int
05187 rb_pipe(int *pipes)
05188 {
05189 int ret;
05190 ret = pipe(pipes);
05191 if (ret == -1) {
05192 if (errno == EMFILE || errno == ENFILE) {
05193 rb_gc();
05194 ret = pipe(pipes);
05195 }
05196 }
05197 if (ret == 0) {
05198 rb_update_max_fd(pipes[0]);
05199 rb_update_max_fd(pipes[1]);
05200 }
05201 return ret;
05202 }
05203
05204 #ifdef HAVE_FORK
05205 struct popen_arg {
05206 struct rb_exec_arg *execp;
05207 int modef;
05208 int pair[2];
05209 int write_pair[2];
05210 };
05211
05212 static void
05213 popen_redirect(struct popen_arg *p)
05214 {
05215 if ((p->modef & FMODE_READABLE) && (p->modef & FMODE_WRITABLE)) {
05216 close(p->write_pair[1]);
05217 if (p->write_pair[0] != 0) {
05218 dup2(p->write_pair[0], 0);
05219 close(p->write_pair[0]);
05220 }
05221 close(p->pair[0]);
05222 if (p->pair[1] != 1) {
05223 dup2(p->pair[1], 1);
05224 close(p->pair[1]);
05225 }
05226 }
05227 else if (p->modef & FMODE_READABLE) {
05228 close(p->pair[0]);
05229 if (p->pair[1] != 1) {
05230 dup2(p->pair[1], 1);
05231 close(p->pair[1]);
05232 }
05233 }
05234 else {
05235 close(p->pair[1]);
05236 if (p->pair[0] != 0) {
05237 dup2(p->pair[0], 0);
05238 close(p->pair[0]);
05239 }
05240 }
05241 }
05242
05243 void
05244 rb_close_before_exec(int lowfd, int maxhint, VALUE noclose_fds)
05245 {
05246 int fd, ret;
05247 int max = max_file_descriptor;
05248 if (max < maxhint)
05249 max = maxhint;
05250 for (fd = lowfd; fd <= max; fd++) {
05251 if (!NIL_P(noclose_fds) &&
05252 RTEST(rb_hash_lookup(noclose_fds, INT2FIX(fd))))
05253 continue;
05254 #ifdef FD_CLOEXEC
05255 ret = fcntl(fd, F_GETFD);
05256 if (ret != -1 && !(ret & FD_CLOEXEC)) {
05257 fcntl(fd, F_SETFD, ret|FD_CLOEXEC);
05258 }
05259 #else
05260 ret = close(fd);
05261 #endif
05262 #define CONTIGUOUS_CLOSED_FDS 20
05263 if (ret != -1) {
05264 if (max < fd + CONTIGUOUS_CLOSED_FDS)
05265 max = fd + CONTIGUOUS_CLOSED_FDS;
05266 }
05267 }
05268 }
05269
05270 static int
05271 popen_exec(void *pp, char *errmsg, size_t errmsg_len)
05272 {
05273 struct popen_arg *p = (struct popen_arg*)pp;
05274
05275 rb_thread_atfork_before_exec();
05276 return rb_exec_err(p->execp, errmsg, errmsg_len);
05277 }
05278 #endif
05279
05280 static VALUE
05281 pipe_open(struct rb_exec_arg *eargp, VALUE prog, const char *modestr, int fmode, convconfig_t *convconfig)
05282 {
05283 rb_pid_t pid = 0;
05284 rb_io_t *fptr;
05285 VALUE port;
05286 rb_io_t *write_fptr;
05287 VALUE write_port;
05288 #if defined(HAVE_FORK)
05289 int status;
05290 struct popen_arg arg;
05291 char errmsg[80] = { '\0' };
05292 #elif defined(_WIN32)
05293 volatile VALUE argbuf;
05294 char **args = NULL;
05295 int pair[2], write_pair[2];
05296 #endif
05297 #if !defined(HAVE_FORK)
05298 struct rb_exec_arg sarg;
05299 #endif
05300 FILE *fp = 0;
05301 int fd = -1;
05302 int write_fd = -1;
05303 const char *cmd = 0;
05304 int argc;
05305 VALUE *argv;
05306
05307 if (prog)
05308 cmd = StringValueCStr(prog);
05309
05310 if (!eargp) {
05311
05312 argc = 0;
05313 argv = 0;
05314 }
05315 else if (eargp->argc) {
05316
05317 argc = eargp->argc;
05318 argv = eargp->argv;
05319 }
05320 else {
05321
05322 argc = 0;
05323 argv = 0;
05324 }
05325
05326 #if defined(HAVE_FORK)
05327 arg.execp = eargp;
05328 arg.modef = fmode;
05329 arg.pair[0] = arg.pair[1] = -1;
05330 arg.write_pair[0] = arg.write_pair[1] = -1;
05331 switch (fmode & (FMODE_READABLE|FMODE_WRITABLE)) {
05332 case FMODE_READABLE|FMODE_WRITABLE:
05333 if (rb_pipe(arg.write_pair) < 0)
05334 rb_sys_fail(cmd);
05335 if (rb_pipe(arg.pair) < 0) {
05336 int e = errno;
05337 close(arg.write_pair[0]);
05338 close(arg.write_pair[1]);
05339 errno = e;
05340 rb_sys_fail(cmd);
05341 }
05342 if (eargp) {
05343 rb_exec_arg_addopt(eargp, INT2FIX(0), INT2FIX(arg.write_pair[0]));
05344 rb_exec_arg_addopt(eargp, INT2FIX(1), INT2FIX(arg.pair[1]));
05345 }
05346 break;
05347 case FMODE_READABLE:
05348 if (rb_pipe(arg.pair) < 0)
05349 rb_sys_fail(cmd);
05350 if (eargp)
05351 rb_exec_arg_addopt(eargp, INT2FIX(1), INT2FIX(arg.pair[1]));
05352 break;
05353 case FMODE_WRITABLE:
05354 if (rb_pipe(arg.pair) < 0)
05355 rb_sys_fail(cmd);
05356 if (eargp)
05357 rb_exec_arg_addopt(eargp, INT2FIX(0), INT2FIX(arg.pair[0]));
05358 break;
05359 default:
05360 rb_sys_fail(cmd);
05361 }
05362 if (eargp) {
05363 rb_exec_arg_fixup(arg.execp);
05364 pid = rb_fork_err(&status, popen_exec, &arg, arg.execp->redirect_fds, errmsg, sizeof(errmsg));
05365 }
05366 else {
05367 fflush(stdin);
05368 pid = rb_fork(&status, 0, 0, Qnil);
05369 if (pid == 0) {
05370 rb_thread_atfork();
05371 popen_redirect(&arg);
05372 rb_io_synchronized(RFILE(orig_stdout)->fptr);
05373 rb_io_synchronized(RFILE(orig_stderr)->fptr);
05374 return Qnil;
05375 }
05376 }
05377
05378
05379 if (pid == -1) {
05380 int e = errno;
05381 close(arg.pair[0]);
05382 close(arg.pair[1]);
05383 if ((fmode & (FMODE_READABLE|FMODE_WRITABLE)) == (FMODE_READABLE|FMODE_WRITABLE)) {
05384 close(arg.write_pair[0]);
05385 close(arg.write_pair[1]);
05386 }
05387 errno = e;
05388 if (errmsg[0])
05389 rb_sys_fail(errmsg);
05390 rb_sys_fail(cmd);
05391 }
05392 if ((fmode & FMODE_READABLE) && (fmode & FMODE_WRITABLE)) {
05393 close(arg.pair[1]);
05394 fd = arg.pair[0];
05395 close(arg.write_pair[0]);
05396 write_fd = arg.write_pair[1];
05397 }
05398 else if (fmode & FMODE_READABLE) {
05399 close(arg.pair[1]);
05400 fd = arg.pair[0];
05401 }
05402 else {
05403 close(arg.pair[0]);
05404 fd = arg.pair[1];
05405 }
05406 #elif defined(_WIN32)
05407 if (argc) {
05408 int i;
05409
05410 if (argc >= (int)(FIXNUM_MAX / sizeof(char *))) {
05411 rb_raise(rb_eArgError, "too many arguments");
05412 }
05413 argbuf = rb_str_tmp_new((argc+1) * sizeof(char *));
05414 args = (void *)RSTRING_PTR(argbuf);
05415 for (i = 0; i < argc; ++i) {
05416 args[i] = StringValueCStr(argv[i]);
05417 }
05418 args[i] = NULL;
05419 }
05420 switch (fmode & (FMODE_READABLE|FMODE_WRITABLE)) {
05421 case FMODE_READABLE|FMODE_WRITABLE:
05422 if (rb_pipe(write_pair) < 0)
05423 rb_sys_fail(cmd);
05424 if (rb_pipe(pair) < 0) {
05425 int e = errno;
05426 close(write_pair[0]);
05427 close(write_pair[1]);
05428 errno = e;
05429 rb_sys_fail(cmd);
05430 }
05431 if (eargp) {
05432 rb_exec_arg_addopt(eargp, INT2FIX(0), INT2FIX(write_pair[0]));
05433 rb_exec_arg_addopt(eargp, INT2FIX(1), INT2FIX(pair[1]));
05434 }
05435 break;
05436 case FMODE_READABLE:
05437 if (rb_pipe(pair) < 0)
05438 rb_sys_fail(cmd);
05439 if (eargp)
05440 rb_exec_arg_addopt(eargp, INT2FIX(1), INT2FIX(pair[1]));
05441 break;
05442 case FMODE_WRITABLE:
05443 if (rb_pipe(pair) < 0)
05444 rb_sys_fail(cmd);
05445 if (eargp)
05446 rb_exec_arg_addopt(eargp, INT2FIX(0), INT2FIX(pair[0]));
05447 break;
05448 default:
05449 rb_sys_fail(cmd);
05450 }
05451 if (eargp) {
05452 rb_exec_arg_fixup(eargp);
05453 rb_run_exec_options(eargp, &sarg);
05454 }
05455 while ((pid = (args ?
05456 rb_w32_aspawn(P_NOWAIT, cmd, args) :
05457 rb_w32_spawn(P_NOWAIT, cmd, 0))) == -1) {
05458
05459 switch (errno) {
05460 case EAGAIN:
05461 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
05462 case EWOULDBLOCK:
05463 #endif
05464 rb_thread_sleep(1);
05465 break;
05466 default:
05467 {
05468 int e = errno;
05469 if (eargp)
05470 rb_run_exec_options(&sarg, NULL);
05471 close(pair[0]);
05472 close(pair[1]);
05473 if ((fmode & (FMODE_READABLE|FMODE_WRITABLE)) == (FMODE_READABLE|FMODE_WRITABLE)) {
05474 close(write_pair[0]);
05475 close(write_pair[1]);
05476 }
05477 errno = e;
05478 rb_sys_fail(cmd);
05479 }
05480 break;
05481 }
05482 }
05483
05484 RB_GC_GUARD(argbuf);
05485
05486 if (eargp)
05487 rb_run_exec_options(&sarg, NULL);
05488 if ((fmode & FMODE_READABLE) && (fmode & FMODE_WRITABLE)) {
05489 close(pair[1]);
05490 fd = pair[0];
05491 close(write_pair[0]);
05492 write_fd = write_pair[1];
05493 }
05494 else if (fmode & FMODE_READABLE) {
05495 close(pair[1]);
05496 fd = pair[0];
05497 }
05498 else {
05499 close(pair[0]);
05500 fd = pair[1];
05501 }
05502 #else
05503 if (argc) {
05504 prog = rb_ary_join(rb_ary_new4(argc, argv), rb_str_new2(" "));
05505 cmd = StringValueCStr(prog);
05506 }
05507 if (eargp) {
05508 rb_exec_arg_fixup(eargp);
05509 rb_run_exec_options(eargp, &sarg);
05510 }
05511 fp = popen(cmd, modestr);
05512 if (eargp)
05513 rb_run_exec_options(&sarg, NULL);
05514 if (!fp) rb_sys_fail_path(prog);
05515 fd = fileno(fp);
05516 #endif
05517
05518 port = io_alloc(rb_cIO);
05519 MakeOpenFile(port, fptr);
05520 fptr->fd = fd;
05521 fptr->stdio_file = fp;
05522 fptr->mode = fmode | FMODE_SYNC|FMODE_DUPLEX;
05523 if (convconfig) {
05524 fptr->encs = *convconfig;
05525 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
05526 if (fptr->encs.ecflags & ECONV_DEFAULT_NEWLINE_DECORATOR) {
05527 fptr->encs.ecflags |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;
05528 }
05529 #endif
05530 }
05531 else {
05532 if (NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {
05533 fptr->encs.ecflags |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;
05534 }
05535 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
05536 if (NEED_NEWLINE_DECORATOR_ON_WRITE(fptr)) {
05537 fptr->encs.ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
05538 }
05539 #endif
05540 }
05541 fptr->pid = pid;
05542
05543 if (0 <= write_fd) {
05544 write_port = io_alloc(rb_cIO);
05545 MakeOpenFile(write_port, write_fptr);
05546 write_fptr->fd = write_fd;
05547 write_fptr->mode = (fmode & ~FMODE_READABLE)| FMODE_SYNC|FMODE_DUPLEX;
05548 fptr->mode &= ~FMODE_WRITABLE;
05549 fptr->tied_io_for_writing = write_port;
05550 rb_ivar_set(port, rb_intern("@tied_io_for_writing"), write_port);
05551 }
05552
05553 #if defined (__CYGWIN__) || !defined(HAVE_FORK)
05554 fptr->finalize = pipe_finalize;
05555 pipe_add_fptr(fptr);
05556 #endif
05557 return port;
05558 }
05559
05560 static VALUE
05561 pipe_open_v(int argc, VALUE *argv, const char *modestr, int fmode, convconfig_t *convconfig)
05562 {
05563 VALUE prog;
05564 struct rb_exec_arg earg;
05565 prog = rb_exec_arg_init(argc, argv, FALSE, &earg);
05566 return pipe_open(&earg, prog, modestr, fmode, convconfig);
05567 }
05568
05569 static VALUE
05570 pipe_open_s(VALUE prog, const char *modestr, int fmode, convconfig_t *convconfig)
05571 {
05572 const char *cmd = RSTRING_PTR(prog);
05573 int argc = 1;
05574 VALUE *argv = &prog;
05575 struct rb_exec_arg earg;
05576
05577 if (RSTRING_LEN(prog) == 1 && cmd[0] == '-') {
05578 #if !defined(HAVE_FORK)
05579 rb_raise(rb_eNotImpError,
05580 "fork() function is unimplemented on this machine");
05581 #endif
05582 return pipe_open(0, 0, modestr, fmode, convconfig);
05583 }
05584
05585 rb_exec_arg_init(argc, argv, TRUE, &earg);
05586 return pipe_open(&earg, prog, modestr, fmode, convconfig);
05587 }
05588
05589
05590
05591
05592
05593
05594
05595
05596
05597
05598
05599
05600
05601
05602
05603
05604
05605
05606
05607
05608
05609
05610
05611
05612
05613
05614
05615
05616
05617
05618
05619
05620
05621
05622
05623
05624
05625
05626
05627
05628
05629
05630
05631
05632
05633
05634
05635
05636
05637
05638
05639
05640
05641
05642
05643
05644
05645
05646
05647
05648
05649
05650
05651
05652
05653
05654
05655
05656
05657
05658
05659
05660
05661
05662
05663
05664
05665
05666
05667
05668
05669
05670
05671
05672 static VALUE
05673 rb_io_s_popen(int argc, VALUE *argv, VALUE klass)
05674 {
05675 const char *modestr;
05676 VALUE pname, pmode, port, tmp, opt;
05677 int oflags, fmode;
05678 convconfig_t convconfig;
05679
05680 argc = rb_scan_args(argc, argv, "11:", &pname, &pmode, &opt);
05681
05682 rb_io_extract_modeenc(&pmode, 0, opt, &oflags, &fmode, &convconfig);
05683 modestr = rb_io_oflags_modestr(oflags);
05684
05685 tmp = rb_check_array_type(pname);
05686 if (!NIL_P(tmp)) {
05687 long len = RARRAY_LEN(tmp);
05688 #if SIZEOF_LONG > SIZEOF_INT
05689 if (len > INT_MAX) {
05690 rb_raise(rb_eArgError, "too many arguments");
05691 }
05692 #endif
05693 tmp = rb_ary_dup(tmp);
05694 RBASIC(tmp)->klass = 0;
05695 port = pipe_open_v((int)len, RARRAY_PTR(tmp), modestr, fmode, &convconfig);
05696 rb_ary_clear(tmp);
05697 }
05698 else {
05699 SafeStringValue(pname);
05700 port = pipe_open_s(pname, modestr, fmode, &convconfig);
05701 }
05702 if (NIL_P(port)) {
05703
05704 if (rb_block_given_p()) {
05705 rb_yield(Qnil);
05706 rb_io_flush(rb_stdout);
05707 rb_io_flush(rb_stderr);
05708 _exit(0);
05709 }
05710 return Qnil;
05711 }
05712 RBASIC(port)->klass = klass;
05713 if (rb_block_given_p()) {
05714 return rb_ensure(rb_yield, port, io_close, port);
05715 }
05716 return port;
05717 }
05718
05719 static void
05720 rb_scan_open_args(int argc, VALUE *argv,
05721 VALUE *fname_p, int *oflags_p, int *fmode_p,
05722 convconfig_t *convconfig_p, mode_t *perm_p)
05723 {
05724 VALUE opt, fname, vmode, vperm;
05725 int oflags, fmode;
05726 mode_t perm;
05727
05728 argc = rb_scan_args(argc, argv, "12:", &fname, &vmode, &vperm, &opt);
05729 FilePathValue(fname);
05730
05731 rb_io_extract_modeenc(&vmode, &vperm, opt, &oflags, &fmode, convconfig_p);
05732
05733 perm = NIL_P(vperm) ? 0666 : NUM2MODET(vperm);
05734
05735 *fname_p = fname;
05736 *oflags_p = oflags;
05737 *fmode_p = fmode;
05738 *perm_p = perm;
05739 }
05740
05741 static VALUE
05742 rb_open_file(int argc, VALUE *argv, VALUE io)
05743 {
05744 VALUE fname;
05745 int oflags, fmode;
05746 convconfig_t convconfig;
05747 mode_t perm;
05748
05749 rb_scan_open_args(argc, argv, &fname, &oflags, &fmode, &convconfig, &perm);
05750 rb_file_open_generic(io, fname, oflags, fmode, &convconfig, perm);
05751
05752 return io;
05753 }
05754
05755
05756
05757
05758
05759
05760
05761
05762
05763
05764
05765
05766
05767
05768
05769
05770
05771
05772
05773
05774
05775
05776
05777
05778
05779
05780
05781
05782
05783
05784
05785
05786
05787
05788
05789
05790 static VALUE
05791 rb_io_s_open(int argc, VALUE *argv, VALUE klass)
05792 {
05793 VALUE io = rb_class_new_instance(argc, argv, klass);
05794
05795 if (rb_block_given_p()) {
05796 return rb_ensure(rb_yield, io, io_close, io);
05797 }
05798
05799 return io;
05800 }
05801
05802
05803
05804
05805
05806
05807
05808
05809
05810
05811
05812
05813 static VALUE
05814 rb_io_s_sysopen(int argc, VALUE *argv)
05815 {
05816 VALUE fname, vmode, vperm;
05817 VALUE intmode;
05818 int oflags, fd;
05819 mode_t perm;
05820
05821 rb_scan_args(argc, argv, "12", &fname, &vmode, &vperm);
05822 FilePathValue(fname);
05823
05824 if (NIL_P(vmode))
05825 oflags = O_RDONLY;
05826 else if (!NIL_P(intmode = rb_check_to_integer(vmode, "to_int")))
05827 oflags = NUM2INT(intmode);
05828 else {
05829 SafeStringValue(vmode);
05830 oflags = rb_io_modestr_oflags(StringValueCStr(vmode));
05831 }
05832 if (NIL_P(vperm)) perm = 0666;
05833 else perm = NUM2MODET(vperm);
05834
05835 RB_GC_GUARD(fname) = rb_str_new4(fname);
05836 fd = rb_sysopen(fname, oflags, perm);
05837 return INT2NUM(fd);
05838 }
05839
05840 static VALUE
05841 check_pipe_command(VALUE filename_or_command)
05842 {
05843 char *s = RSTRING_PTR(filename_or_command);
05844 long l = RSTRING_LEN(filename_or_command);
05845 char *e = s + l;
05846 int chlen;
05847
05848 if (rb_enc_ascget(s, e, &chlen, rb_enc_get(filename_or_command)) == '|') {
05849 VALUE cmd = rb_str_new(s+chlen, l-chlen);
05850 OBJ_INFECT(cmd, filename_or_command);
05851 return cmd;
05852 }
05853 return Qnil;
05854 }
05855
05856
05857
05858
05859
05860
05861
05862
05863
05864
05865
05866
05867
05868
05869
05870
05871
05872
05873
05874
05875
05876
05877
05878
05879
05880
05881
05882
05883
05884
05885
05886
05887
05888
05889
05890
05891
05892
05893
05894
05895
05896
05897
05898
05899
05900
05901
05902
05903
05904
05905
05906
05907
05908
05909
05910
05911
05912
05913
05914
05915
05916
05917
05918
05919
05920
05921
05922
05923
05924
05925
05926
05927
05928
05929
05930
05931
05932
05933
05934
05935
05936
05937
05938
05939
05940
05941
05942
05943
05944
05945
05946
05947
05948
05949
05950
05951
05952
05953
05954
05955
05956
05957
05958
05959
05960
05961
05962
05963
05964
05965
05966 static VALUE
05967 rb_f_open(int argc, VALUE *argv)
05968 {
05969 ID to_open = 0;
05970 int redirect = FALSE;
05971
05972 if (argc >= 1) {
05973 CONST_ID(to_open, "to_open");
05974 if (rb_respond_to(argv[0], to_open)) {
05975 redirect = TRUE;
05976 }
05977 else {
05978 VALUE tmp = argv[0];
05979 FilePathValue(tmp);
05980 if (NIL_P(tmp)) {
05981 redirect = TRUE;
05982 }
05983 else {
05984 VALUE cmd = check_pipe_command(tmp);
05985 if (!NIL_P(cmd)) {
05986 argv[0] = cmd;
05987 return rb_io_s_popen(argc, argv, rb_cIO);
05988 }
05989 }
05990 }
05991 }
05992 if (redirect) {
05993 VALUE io = rb_funcall2(argv[0], to_open, argc-1, argv+1);
05994
05995 if (rb_block_given_p()) {
05996 return rb_ensure(rb_yield, io, io_close, io);
05997 }
05998 return io;
05999 }
06000 return rb_io_s_open(argc, argv, rb_cFile);
06001 }
06002
06003 static VALUE
06004 rb_io_open(VALUE filename, VALUE vmode, VALUE vperm, VALUE opt)
06005 {
06006 VALUE cmd;
06007 int oflags, fmode;
06008 convconfig_t convconfig;
06009 mode_t perm;
06010
06011 rb_io_extract_modeenc(&vmode, &vperm, opt, &oflags, &fmode, &convconfig);
06012 perm = NIL_P(vperm) ? 0666 : NUM2MODET(vperm);
06013
06014 if (!NIL_P(cmd = check_pipe_command(filename))) {
06015 return pipe_open_s(cmd, rb_io_oflags_modestr(oflags), fmode, &convconfig);
06016 }
06017 else {
06018 return rb_file_open_generic(io_alloc(rb_cFile), filename,
06019 oflags, fmode, &convconfig, perm);
06020 }
06021 }
06022
06023 static VALUE
06024 rb_io_open_with_args(int argc, VALUE *argv)
06025 {
06026 VALUE io;
06027
06028 io = io_alloc(rb_cFile);
06029 rb_open_file(argc, argv, io);
06030 return io;
06031 }
06032
06033 static VALUE
06034 io_reopen(VALUE io, VALUE nfile)
06035 {
06036 rb_io_t *fptr, *orig;
06037 int fd, fd2;
06038 off_t pos = 0;
06039
06040 nfile = rb_io_get_io(nfile);
06041 if (rb_safe_level() >= 4 &&
06042 (!OBJ_UNTRUSTED(io) || !OBJ_UNTRUSTED(nfile))) {
06043 rb_raise(rb_eSecurityError, "Insecure: can't reopen");
06044 }
06045 GetOpenFile(io, fptr);
06046 GetOpenFile(nfile, orig);
06047
06048 if (fptr == orig) return io;
06049 if (IS_PREP_STDIO(fptr)) {
06050 if ((fptr->stdio_file == stdin && !(orig->mode & FMODE_READABLE)) ||
06051 (fptr->stdio_file == stdout && !(orig->mode & FMODE_WRITABLE)) ||
06052 (fptr->stdio_file == stderr && !(orig->mode & FMODE_WRITABLE))) {
06053 rb_raise(rb_eArgError,
06054 "%s can't change access mode from \"%s\" to \"%s\"",
06055 PREP_STDIO_NAME(fptr), rb_io_fmode_modestr(fptr->mode),
06056 rb_io_fmode_modestr(orig->mode));
06057 }
06058 }
06059 if (fptr->mode & FMODE_WRITABLE) {
06060 if (io_fflush(fptr) < 0)
06061 rb_sys_fail(0);
06062 }
06063 else {
06064 io_tell(fptr);
06065 }
06066 if (orig->mode & FMODE_READABLE) {
06067 pos = io_tell(orig);
06068 }
06069 if (orig->mode & FMODE_WRITABLE) {
06070 if (io_fflush(orig) < 0)
06071 rb_sys_fail(0);
06072 }
06073
06074
06075 fptr->mode = orig->mode | (fptr->mode & FMODE_PREP);
06076 fptr->pid = orig->pid;
06077 fptr->lineno = orig->lineno;
06078 if (RTEST(orig->pathv)) fptr->pathv = orig->pathv;
06079 else if (!IS_PREP_STDIO(fptr)) fptr->pathv = Qnil;
06080 fptr->finalize = orig->finalize;
06081 #if defined (__CYGWIN__) || !defined(HAVE_FORK)
06082 if (fptr->finalize == pipe_finalize)
06083 pipe_add_fptr(fptr);
06084 #endif
06085
06086 fd = fptr->fd;
06087 fd2 = orig->fd;
06088 if (fd != fd2) {
06089 if (IS_PREP_STDIO(fptr) || fd <= 2 || !fptr->stdio_file) {
06090
06091 if (dup2(fd2, fd) < 0)
06092 rb_sys_fail_path(orig->pathv);
06093 rb_update_max_fd(fd);
06094 }
06095 else {
06096 fclose(fptr->stdio_file);
06097 fptr->stdio_file = 0;
06098 fptr->fd = -1;
06099 if (dup2(fd2, fd) < 0)
06100 rb_sys_fail_path(orig->pathv);
06101 rb_update_max_fd(fd);
06102 fptr->fd = fd;
06103 }
06104 rb_thread_fd_close(fd);
06105 if ((orig->mode & FMODE_READABLE) && pos >= 0) {
06106 if (io_seek(fptr, pos, SEEK_SET) < 0 && errno) {
06107 rb_sys_fail_path(fptr->pathv);
06108 }
06109 if (io_seek(orig, pos, SEEK_SET) < 0 && errno) {
06110 rb_sys_fail_path(orig->pathv);
06111 }
06112 }
06113 }
06114
06115 if (fptr->mode & FMODE_BINMODE) {
06116 rb_io_binmode(io);
06117 }
06118
06119 RBASIC(io)->klass = rb_obj_class(nfile);
06120 return io;
06121 }
06122
06123
06124
06125
06126
06127
06128
06129
06130
06131
06132
06133
06134
06135
06136
06137
06138
06139 static VALUE
06140 rb_io_reopen(int argc, VALUE *argv, VALUE file)
06141 {
06142 VALUE fname, nmode;
06143 int oflags;
06144 rb_io_t *fptr;
06145
06146 rb_secure(4);
06147 if (rb_scan_args(argc, argv, "11", &fname, &nmode) == 1) {
06148 VALUE tmp = rb_io_check_io(fname);
06149 if (!NIL_P(tmp)) {
06150 return io_reopen(file, tmp);
06151 }
06152 }
06153
06154 FilePathValue(fname);
06155 rb_io_taint_check(file);
06156 fptr = RFILE(file)->fptr;
06157 if (!fptr) {
06158 fptr = RFILE(file)->fptr = ALLOC(rb_io_t);
06159 MEMZERO(fptr, rb_io_t, 1);
06160 }
06161
06162 if (!NIL_P(nmode)) {
06163 int fmode = rb_io_modestr_fmode(StringValueCStr(nmode));
06164 if (IS_PREP_STDIO(fptr) &&
06165 ((fptr->mode & FMODE_READWRITE) & (fmode & FMODE_READWRITE)) !=
06166 (fptr->mode & FMODE_READWRITE)) {
06167 rb_raise(rb_eArgError,
06168 "%s can't change access mode from \"%s\" to \"%s\"",
06169 PREP_STDIO_NAME(fptr), rb_io_fmode_modestr(fptr->mode),
06170 rb_io_fmode_modestr(fmode));
06171 }
06172 fptr->mode = fmode;
06173 rb_io_mode_enc(fptr, StringValueCStr(nmode));
06174 fptr->encs.ecflags = 0;
06175 fptr->encs.ecopts = Qnil;
06176 }
06177
06178 fptr->pathv = rb_str_new_frozen(fname);
06179 oflags = rb_io_fmode_oflags(fptr->mode);
06180 if (fptr->fd < 0) {
06181 fptr->fd = rb_sysopen(fptr->pathv, oflags, 0666);
06182 fptr->stdio_file = 0;
06183 return file;
06184 }
06185
06186 if (fptr->mode & FMODE_WRITABLE) {
06187 if (io_fflush(fptr) < 0)
06188 rb_sys_fail(0);
06189 }
06190 fptr->rbuf.off = fptr->rbuf.len = 0;
06191
06192 if (fptr->stdio_file) {
06193 if (freopen(RSTRING_PTR(fptr->pathv), rb_io_oflags_modestr(oflags), fptr->stdio_file) == 0) {
06194 rb_sys_fail_path(fptr->pathv);
06195 }
06196 fptr->fd = fileno(fptr->stdio_file);
06197 #ifdef USE_SETVBUF
06198 if (setvbuf(fptr->stdio_file, NULL, _IOFBF, 0) != 0)
06199 rb_warn("setvbuf() can't be honoured for %s", RSTRING_PTR(fptr->pathv));
06200 #endif
06201 }
06202 else {
06203 if (close(fptr->fd) < 0)
06204 rb_sys_fail_path(fptr->pathv);
06205 fptr->fd = -1;
06206 fptr->fd = rb_sysopen(fptr->pathv, oflags, 0666);
06207 }
06208
06209 return file;
06210 }
06211
06212
06213 static VALUE
06214 rb_io_init_copy(VALUE dest, VALUE io)
06215 {
06216 rb_io_t *fptr, *orig;
06217 int fd;
06218 VALUE write_io;
06219 off_t pos;
06220
06221 io = rb_io_get_io(io);
06222 if (dest == io) return dest;
06223 GetOpenFile(io, orig);
06224 MakeOpenFile(dest, fptr);
06225
06226 rb_io_flush(io);
06227
06228
06229 fptr->mode = orig->mode & ~FMODE_PREP;
06230 fptr->encs = orig->encs;
06231 fptr->pid = orig->pid;
06232 fptr->lineno = orig->lineno;
06233 if (!NIL_P(orig->pathv)) fptr->pathv = orig->pathv;
06234 fptr->finalize = orig->finalize;
06235 #if defined (__CYGWIN__) || !defined(HAVE_FORK)
06236 if (fptr->finalize == pipe_finalize)
06237 pipe_add_fptr(fptr);
06238 #endif
06239
06240 fd = ruby_dup(orig->fd);
06241 fptr->fd = fd;
06242 pos = io_tell(orig);
06243 if (0 <= pos)
06244 io_seek(fptr, pos, SEEK_SET);
06245 if (fptr->mode & FMODE_BINMODE) {
06246 rb_io_binmode(dest);
06247 }
06248
06249 write_io = GetWriteIO(io);
06250 if (io != write_io) {
06251 write_io = rb_obj_dup(write_io);
06252 fptr->tied_io_for_writing = write_io;
06253 rb_ivar_set(dest, rb_intern("@tied_io_for_writing"), write_io);
06254 }
06255
06256 return dest;
06257 }
06258
06259
06260
06261
06262
06263
06264
06265
06266
06267
06268 VALUE
06269 rb_io_printf(int argc, VALUE *argv, VALUE out)
06270 {
06271 rb_io_write(out, rb_f_sprintf(argc, argv));
06272 return Qnil;
06273 }
06274
06275
06276
06277
06278
06279
06280
06281
06282
06283
06284
06285
06286 static VALUE
06287 rb_f_printf(int argc, VALUE *argv)
06288 {
06289 VALUE out;
06290
06291 if (argc == 0) return Qnil;
06292 if (TYPE(argv[0]) == T_STRING) {
06293 out = rb_stdout;
06294 }
06295 else {
06296 out = argv[0];
06297 argv++;
06298 argc--;
06299 }
06300 rb_io_write(out, rb_f_sprintf(argc, argv));
06301
06302 return Qnil;
06303 }
06304
06305
06306
06307
06308
06309
06310
06311
06312
06313
06314
06315
06316
06317
06318
06319
06320
06321
06322
06323
06324
06325
06326
06327 VALUE
06328 rb_io_print(int argc, VALUE *argv, VALUE out)
06329 {
06330 int i;
06331 VALUE line;
06332
06333
06334 if (argc == 0) {
06335 argc = 1;
06336 line = rb_lastline_get();
06337 argv = &line;
06338 }
06339 for (i=0; i<argc; i++) {
06340 if (!NIL_P(rb_output_fs) && i>0) {
06341 rb_io_write(out, rb_output_fs);
06342 }
06343 rb_io_write(out, argv[i]);
06344 }
06345 if (argc > 0 && !NIL_P(rb_output_rs)) {
06346 rb_io_write(out, rb_output_rs);
06347 }
06348
06349 return Qnil;
06350 }
06351
06352
06353
06354
06355
06356
06357
06358
06359
06360
06361
06362
06363
06364
06365
06366
06367
06368
06369
06370
06371
06372
06373
06374
06375 static VALUE
06376 rb_f_print(int argc, VALUE *argv)
06377 {
06378 rb_io_print(argc, argv, rb_stdout);
06379 return Qnil;
06380 }
06381
06382
06383
06384
06385
06386
06387
06388
06389
06390
06391
06392
06393
06394
06395
06396
06397
06398
06399
06400 static VALUE
06401 rb_io_putc(VALUE io, VALUE ch)
06402 {
06403 VALUE str;
06404 if (TYPE(ch) == T_STRING) {
06405 str = rb_str_substr(ch, 0, 1);
06406 }
06407 else {
06408 char c = NUM2CHR(ch);
06409 str = rb_str_new(&c, 1);
06410 }
06411 rb_io_write(io, str);
06412 return ch;
06413 }
06414
06415
06416
06417
06418
06419
06420
06421
06422
06423
06424
06425
06426
06427 static VALUE
06428 rb_f_putc(VALUE recv, VALUE ch)
06429 {
06430 if (recv == rb_stdout) {
06431 return rb_io_putc(recv, ch);
06432 }
06433 return rb_funcall2(rb_stdout, rb_intern("putc"), 1, &ch);
06434 }
06435
06436
06437 static int
06438 str_end_with_asciichar(VALUE str, int c)
06439 {
06440 long len = RSTRING_LEN(str);
06441 const char *ptr = RSTRING_PTR(str);
06442 rb_encoding *enc = rb_enc_from_index(ENCODING_GET(str));
06443 int n;
06444
06445 if (len == 0) return 0;
06446 if ((n = rb_enc_mbminlen(enc)) == 1) {
06447 return ptr[len - 1] == c;
06448 }
06449 return rb_enc_ascget(ptr + ((len - 1) / n) * n, ptr + len, &n, enc) == c;
06450 }
06451
06452 static VALUE
06453 io_puts_ary(VALUE ary, VALUE out, int recur)
06454 {
06455 VALUE tmp;
06456 long i;
06457
06458 if (recur) {
06459 tmp = rb_str_new2("[...]");
06460 rb_io_puts(1, &tmp, out);
06461 return Qnil;
06462 }
06463 for (i=0; i<RARRAY_LEN(ary); i++) {
06464 tmp = RARRAY_PTR(ary)[i];
06465 rb_io_puts(1, &tmp, out);
06466 }
06467 return Qnil;
06468 }
06469
06470
06471
06472
06473
06474
06475
06476
06477
06478
06479
06480
06481
06482
06483
06484
06485
06486
06487
06488
06489
06490 VALUE
06491 rb_io_puts(int argc, VALUE *argv, VALUE out)
06492 {
06493 int i;
06494 VALUE line;
06495
06496
06497 if (argc == 0) {
06498 rb_io_write(out, rb_default_rs);
06499 return Qnil;
06500 }
06501 for (i=0; i<argc; i++) {
06502 if (TYPE(argv[i]) == T_STRING) {
06503 line = argv[i];
06504 goto string;
06505 }
06506 line = rb_check_array_type(argv[i]);
06507 if (!NIL_P(line)) {
06508 rb_exec_recursive(io_puts_ary, line, out);
06509 continue;
06510 }
06511 line = rb_obj_as_string(argv[i]);
06512 string:
06513 rb_io_write(out, line);
06514 if (RSTRING_LEN(line) == 0 ||
06515 !str_end_with_asciichar(line, '\n')) {
06516 rb_io_write(out, rb_default_rs);
06517 }
06518 }
06519
06520 return Qnil;
06521 }
06522
06523
06524
06525
06526
06527
06528
06529
06530
06531
06532 static VALUE
06533 rb_f_puts(int argc, VALUE *argv, VALUE recv)
06534 {
06535 if (recv == rb_stdout) {
06536 return rb_io_puts(argc, argv, recv);
06537 }
06538 return rb_funcall2(rb_stdout, rb_intern("puts"), argc, argv);
06539 }
06540
06541 void
06542 rb_p(VALUE obj)
06543 {
06544 VALUE str = rb_obj_as_string(rb_inspect(obj));
06545 if (TYPE(rb_stdout) == T_FILE &&
06546 rb_method_basic_definition_p(CLASS_OF(rb_stdout), id_write)) {
06547 io_write(rb_stdout, str, 1);
06548 io_write(rb_stdout, rb_default_rs, 0);
06549 }
06550 else {
06551 rb_io_write(rb_stdout, str);
06552 rb_io_write(rb_stdout, rb_default_rs);
06553 }
06554 }
06555
06556
06557
06558
06559
06560
06561
06562
06563
06564
06565
06566
06567
06568
06569
06570
06571
06572
06573
06574 static VALUE
06575 rb_f_p(int argc, VALUE *argv, VALUE self)
06576 {
06577 int i;
06578 VALUE ret = Qnil;
06579
06580 for (i=0; i<argc; i++) {
06581 rb_p(argv[i]);
06582 }
06583 if (argc == 1) {
06584 ret = argv[0];
06585 }
06586 else if (argc > 1) {
06587 ret = rb_ary_new4(argc, argv);
06588 }
06589 if (TYPE(rb_stdout) == T_FILE) {
06590 rb_io_flush(rb_stdout);
06591 }
06592 return ret;
06593 }
06594
06595
06596
06597
06598
06599
06600
06601
06602
06603
06604
06605
06606
06607
06608
06609
06610
06611
06612
06613
06614
06615
06616
06617
06618 static VALUE
06619 rb_obj_display(int argc, VALUE *argv, VALUE self)
06620 {
06621 VALUE out;
06622
06623 if (argc == 0) {
06624 out = rb_stdout;
06625 }
06626 else {
06627 rb_scan_args(argc, argv, "01", &out);
06628 }
06629 rb_io_write(out, self);
06630
06631 return Qnil;
06632 }
06633
06634 void
06635 rb_write_error2(const char *mesg, long len)
06636 {
06637 if (rb_stderr == orig_stderr || RFILE(orig_stderr)->fptr->fd < 0) {
06638 (void)fwrite(mesg, sizeof(char), len, stderr);
06639 }
06640 else {
06641 rb_io_write(rb_stderr, rb_str_new(mesg, len));
06642 }
06643 }
06644
06645 void
06646 rb_write_error(const char *mesg)
06647 {
06648 rb_write_error2(mesg, strlen(mesg));
06649 }
06650
06651 static void
06652 must_respond_to(ID mid, VALUE val, ID id)
06653 {
06654 if (!rb_respond_to(val, mid)) {
06655 rb_raise(rb_eTypeError, "%s must have %s method, %s given",
06656 rb_id2name(id), rb_id2name(mid),
06657 rb_obj_classname(val));
06658 }
06659 }
06660
06661 static void
06662 stdout_setter(VALUE val, ID id, VALUE *variable)
06663 {
06664 must_respond_to(id_write, val, id);
06665 *variable = val;
06666 }
06667
06668 static VALUE
06669 prep_io(int fd, int fmode, VALUE klass, const char *path)
06670 {
06671 rb_io_t *fp;
06672 VALUE io = io_alloc(klass);
06673
06674 MakeOpenFile(io, fp);
06675 fp->fd = fd;
06676 #ifdef __CYGWIN__
06677 if (!isatty(fd)) {
06678 fmode |= FMODE_BINMODE;
06679 setmode(fd, O_BINARY);
06680 }
06681 #endif
06682 fp->mode = fmode;
06683 io_check_tty(fp);
06684 if (path) fp->pathv = rb_obj_freeze(rb_str_new_cstr(path));
06685 rb_update_max_fd(fd);
06686
06687 return io;
06688 }
06689
06690 VALUE
06691 rb_io_fdopen(int fd, int oflags, const char *path)
06692 {
06693 VALUE klass = rb_cIO;
06694
06695 if (path && strcmp(path, "-")) klass = rb_cFile;
06696 return prep_io(fd, rb_io_oflags_fmode(oflags), klass, path);
06697 }
06698
06699 static VALUE
06700 prep_stdio(FILE *f, int fmode, VALUE klass, const char *path)
06701 {
06702 rb_io_t *fptr;
06703 VALUE io = prep_io(fileno(f), fmode|FMODE_PREP|DEFAULT_TEXTMODE, klass, path);
06704
06705 GetOpenFile(io, fptr);
06706 fptr->encs.ecflags |= ECONV_DEFAULT_NEWLINE_DECORATOR;
06707 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
06708 fptr->encs.ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
06709 if (fmode & FMODE_READABLE) {
06710 fptr->encs.ecflags |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;
06711 }
06712 #endif
06713 fptr->stdio_file = f;
06714
06715 return io;
06716 }
06717
06718 FILE *
06719 rb_io_stdio_file(rb_io_t *fptr)
06720 {
06721 if (!fptr->stdio_file) {
06722 int oflags = rb_io_fmode_oflags(fptr->mode);
06723 fptr->stdio_file = rb_fdopen(fptr->fd, rb_io_oflags_modestr(oflags));
06724 }
06725 return fptr->stdio_file;
06726 }
06727
06728
06729
06730
06731
06732
06733
06734
06735
06736
06737
06738
06739
06740
06741
06742
06743
06744
06745
06746
06747
06748
06749
06750
06751
06752
06753
06754
06755
06756
06757
06758
06759
06760
06761
06762
06763
06764
06765
06766
06767
06768
06769
06770
06771
06772
06773
06774
06775
06776
06777
06778
06779
06780
06781
06782
06783
06784
06785
06786
06787
06788
06789
06790
06791
06792
06793
06794
06795
06796
06797
06798
06799
06800
06801
06802
06803
06804
06805
06806
06807
06808
06809
06810
06811
06812
06813
06814
06815
06816 static VALUE
06817 rb_io_initialize(int argc, VALUE *argv, VALUE io)
06818 {
06819 VALUE fnum, vmode;
06820 rb_io_t *fp;
06821 int fd, fmode, oflags = O_RDONLY;
06822 convconfig_t convconfig;
06823 VALUE opt;
06824 #if defined(HAVE_FCNTL) && defined(F_GETFL)
06825 int ofmode;
06826 #else
06827 struct stat st;
06828 #endif
06829
06830 rb_secure(4);
06831
06832 argc = rb_scan_args(argc, argv, "11:", &fnum, &vmode, &opt);
06833 rb_io_extract_modeenc(&vmode, 0, opt, &oflags, &fmode, &convconfig);
06834
06835 fd = NUM2INT(fnum);
06836 if (rb_reserved_fd_p(fd)) {
06837 rb_raise(rb_eArgError, "The given fd is not accessible because RubyVM reserves it");
06838 }
06839 #if defined(HAVE_FCNTL) && defined(F_GETFL)
06840 oflags = fcntl(fd, F_GETFL);
06841 if (oflags == -1) rb_sys_fail(0);
06842 #else
06843 if (fstat(fd, &st) == -1) rb_sys_fail(0);
06844 #endif
06845 rb_update_max_fd(fd);
06846 #if defined(HAVE_FCNTL) && defined(F_GETFL)
06847 ofmode = rb_io_oflags_fmode(oflags);
06848 if (NIL_P(vmode)) {
06849 fmode = ofmode;
06850 }
06851 else if ((~ofmode & fmode) & FMODE_READWRITE) {
06852 VALUE error = INT2FIX(EINVAL);
06853 rb_exc_raise(rb_class_new_instance(1, &error, rb_eSystemCallError));
06854 }
06855 #endif
06856 if (!NIL_P(opt) && rb_hash_aref(opt, sym_autoclose) == Qfalse) {
06857 fmode |= FMODE_PREP;
06858 }
06859 MakeOpenFile(io, fp);
06860 fp->fd = fd;
06861 fp->mode = fmode;
06862 fp->encs = convconfig;
06863 clear_codeconv(fp);
06864 io_check_tty(fp);
06865 if (fileno(stdin) == fd)
06866 fp->stdio_file = stdin;
06867 else if (fileno(stdout) == fd)
06868 fp->stdio_file = stdout;
06869 else if (fileno(stderr) == fd)
06870 fp->stdio_file = stderr;
06871
06872 if (fmode & FMODE_SETENC_BY_BOM) io_set_encoding_by_bom(io);
06873 return io;
06874 }
06875
06876
06877
06878
06879
06880
06881
06882
06883
06884
06885
06886
06887
06888
06889
06890
06891
06892
06893
06894
06895
06896
06897
06898
06899
06900
06901
06902
06903 static VALUE
06904 rb_file_initialize(int argc, VALUE *argv, VALUE io)
06905 {
06906 if (RFILE(io)->fptr) {
06907 rb_raise(rb_eRuntimeError, "reinitializing File");
06908 }
06909 if (0 < argc && argc < 3) {
06910 VALUE fd = rb_check_convert_type(argv[0], T_FIXNUM, "Fixnum", "to_int");
06911
06912 if (!NIL_P(fd)) {
06913 argv[0] = fd;
06914 return rb_io_initialize(argc, argv, io);
06915 }
06916 }
06917 rb_open_file(argc, argv, io);
06918
06919 return io;
06920 }
06921
06922
06923 static VALUE
06924 rb_io_s_new(int argc, VALUE *argv, VALUE klass)
06925 {
06926 if (rb_block_given_p()) {
06927 const char *cname = rb_class2name(klass);
06928
06929 rb_warn("%s::new() does not take block; use %s::open() instead",
06930 cname, cname);
06931 }
06932 return rb_class_new_instance(argc, argv, klass);
06933 }
06934
06935
06936
06937
06938
06939
06940
06941
06942
06943
06944 static VALUE
06945 rb_io_s_for_fd(int argc, VALUE *argv, VALUE klass)
06946 {
06947 VALUE io = rb_obj_alloc(klass);
06948 rb_io_initialize(argc, argv, io);
06949 return io;
06950 }
06951
06952
06953
06954
06955
06956
06957
06958
06959
06960 static VALUE
06961 rb_io_autoclose_p(VALUE io)
06962 {
06963 rb_io_t *fptr;
06964 rb_secure(4);
06965 GetOpenFile(io, fptr);
06966 return (fptr->mode & FMODE_PREP) ? Qfalse : Qtrue;
06967 }
06968
06969
06970
06971
06972
06973
06974
06975
06976
06977
06978
06979
06980
06981
06982
06983
06984
06985
06986 static VALUE
06987 rb_io_set_autoclose(VALUE io, VALUE autoclose)
06988 {
06989 rb_io_t *fptr;
06990 rb_secure(4);
06991 GetOpenFile(io, fptr);
06992 if (!RTEST(autoclose))
06993 fptr->mode |= FMODE_PREP;
06994 else
06995 fptr->mode &= ~FMODE_PREP;
06996 return io;
06997 }
06998
06999 static void
07000 argf_mark(void *ptr)
07001 {
07002 struct argf *p = ptr;
07003 rb_gc_mark(p->filename);
07004 rb_gc_mark(p->current_file);
07005 rb_gc_mark(p->argv);
07006 rb_gc_mark(p->encs.ecopts);
07007 }
07008
07009 static void
07010 argf_free(void *ptr)
07011 {
07012 struct argf *p = ptr;
07013 xfree(p->inplace);
07014 xfree(p);
07015 }
07016
07017 static inline void
07018 argf_init(struct argf *p, VALUE v)
07019 {
07020 p->filename = Qnil;
07021 p->current_file = Qnil;
07022 p->lineno = 0;
07023 p->argv = v;
07024 }
07025
07026 static VALUE
07027 argf_alloc(VALUE klass)
07028 {
07029 struct argf *p;
07030 VALUE argf = Data_Make_Struct(klass, struct argf, argf_mark, argf_free, p);
07031
07032 argf_init(p, Qnil);
07033 return argf;
07034 }
07035
07036 #undef rb_argv
07037
07038
07039 static VALUE
07040 argf_initialize(VALUE argf, VALUE argv)
07041 {
07042 memset(&ARGF, 0, sizeof(ARGF));
07043 argf_init(&ARGF, argv);
07044
07045 return argf;
07046 }
07047
07048
07049 static VALUE
07050 argf_initialize_copy(VALUE argf, VALUE orig)
07051 {
07052 ARGF = argf_of(orig);
07053 ARGF.argv = rb_obj_dup(ARGF.argv);
07054 if (ARGF.inplace) {
07055 const char *inplace = ARGF.inplace;
07056 ARGF.inplace = 0;
07057 ARGF.inplace = ruby_strdup(inplace);
07058 }
07059 return argf;
07060 }
07061
07062
07063
07064
07065
07066
07067
07068
07069
07070
07071
07072
07073
07074
07075
07076
07077
07078
07079
07080 static VALUE
07081 argf_set_lineno(VALUE argf, VALUE val)
07082 {
07083 ARGF.lineno = NUM2INT(val);
07084 ARGF.last_lineno = ARGF.lineno;
07085 return Qnil;
07086 }
07087
07088
07089
07090
07091
07092
07093
07094
07095
07096
07097
07098
07099
07100
07101 static VALUE
07102 argf_lineno(VALUE argf)
07103 {
07104 return INT2FIX(ARGF.lineno);
07105 }
07106
07107 static VALUE
07108 argf_forward(int argc, VALUE *argv, VALUE argf)
07109 {
07110 return rb_funcall3(ARGF.current_file, rb_frame_this_func(), argc, argv);
07111 }
07112
07113 #define next_argv() argf_next_argv(argf)
07114 #define ARGF_GENERIC_INPUT_P() \
07115 (ARGF.current_file == rb_stdin && TYPE(ARGF.current_file) != T_FILE)
07116 #define ARGF_FORWARD(argc, argv) do {\
07117 if (ARGF_GENERIC_INPUT_P())\
07118 return argf_forward((argc), (argv), argf);\
07119 } while (0)
07120 #define NEXT_ARGF_FORWARD(argc, argv) do {\
07121 if (!next_argv()) return Qnil;\
07122 ARGF_FORWARD((argc), (argv));\
07123 } while (0)
07124
07125 static void
07126 argf_close(VALUE file)
07127 {
07128 if (file == rb_stdin) return;
07129 if (RB_TYPE_P(file, T_FILE)) {
07130 rb_io_set_write_io(file, Qnil);
07131 }
07132 rb_funcall3(file, rb_intern("close"), 0, 0);
07133 }
07134
07135 static int
07136 argf_next_argv(VALUE argf)
07137 {
07138 char *fn;
07139 rb_io_t *fptr;
07140 int stdout_binmode = 0;
07141 int fmode;
07142
07143 if (TYPE(rb_stdout) == T_FILE) {
07144 GetOpenFile(rb_stdout, fptr);
07145 if (fptr->mode & FMODE_BINMODE)
07146 stdout_binmode = 1;
07147 }
07148
07149 if (ARGF.init_p == 0) {
07150 if (!NIL_P(ARGF.argv) && RARRAY_LEN(ARGF.argv) > 0) {
07151 ARGF.next_p = 1;
07152 }
07153 else {
07154 ARGF.next_p = -1;
07155 }
07156 ARGF.init_p = 1;
07157 }
07158 else {
07159 if (NIL_P(ARGF.argv)) {
07160 ARGF.next_p = -1;
07161 }
07162 else if (ARGF.next_p == -1 && RARRAY_LEN(ARGF.argv) > 0) {
07163 ARGF.next_p = 1;
07164 }
07165 }
07166
07167 if (ARGF.next_p == 1) {
07168 retry:
07169 if (RARRAY_LEN(ARGF.argv) > 0) {
07170 ARGF.filename = rb_ary_shift(ARGF.argv);
07171 fn = StringValueCStr(ARGF.filename);
07172 if (strlen(fn) == 1 && fn[0] == '-') {
07173 ARGF.current_file = rb_stdin;
07174 if (ARGF.inplace) {
07175 rb_warn("Can't do inplace edit for stdio; skipping");
07176 goto retry;
07177 }
07178 }
07179 else {
07180 VALUE write_io = Qnil;
07181 int fr = rb_sysopen(ARGF.filename, O_RDONLY, 0);
07182
07183 if (ARGF.inplace) {
07184 struct stat st;
07185 #ifndef NO_SAFE_RENAME
07186 struct stat st2;
07187 #endif
07188 VALUE str;
07189 int fw;
07190
07191 if (TYPE(rb_stdout) == T_FILE && rb_stdout != orig_stdout) {
07192 rb_io_close(rb_stdout);
07193 }
07194 fstat(fr, &st);
07195 if (*ARGF.inplace) {
07196 str = rb_str_new2(fn);
07197 rb_str_cat2(str, ARGF.inplace);
07198 #ifdef NO_SAFE_RENAME
07199 (void)close(fr);
07200 (void)unlink(RSTRING_PTR(str));
07201 if (rename(fn, RSTRING_PTR(str)) < 0) {
07202 rb_warn("Can't rename %s to %s: %s, skipping file",
07203 fn, RSTRING_PTR(str), strerror(errno));
07204 goto retry;
07205 }
07206 fr = rb_sysopen(str, O_RDONLY, 0);
07207 #else
07208 if (rename(fn, RSTRING_PTR(str)) < 0) {
07209 rb_warn("Can't rename %s to %s: %s, skipping file",
07210 fn, RSTRING_PTR(str), strerror(errno));
07211 close(fr);
07212 goto retry;
07213 }
07214 #endif
07215 }
07216 else {
07217 #ifdef NO_SAFE_RENAME
07218 rb_fatal("Can't do inplace edit without backup");
07219 #else
07220 if (unlink(fn) < 0) {
07221 rb_warn("Can't remove %s: %s, skipping file",
07222 fn, strerror(errno));
07223 close(fr);
07224 goto retry;
07225 }
07226 #endif
07227 }
07228 fw = rb_sysopen(ARGF.filename, O_WRONLY|O_CREAT|O_TRUNC, 0666);
07229 #ifndef NO_SAFE_RENAME
07230 fstat(fw, &st2);
07231 #ifdef HAVE_FCHMOD
07232 fchmod(fw, st.st_mode);
07233 #else
07234 chmod(fn, st.st_mode);
07235 #endif
07236 if (st.st_uid!=st2.st_uid || st.st_gid!=st2.st_gid) {
07237 int err;
07238 #ifdef HAVE_FCHOWN
07239 err = fchown(fw, st.st_uid, st.st_gid);
07240 #else
07241 err = chown(fn, st.st_uid, st.st_gid);
07242 #endif
07243 if (err && getuid() == 0 && st2.st_uid == 0) {
07244 const char *wkfn = RSTRING_PTR(ARGF.filename);
07245 rb_warn("Can't set owner/group of %s to same as %s: %s, skipping file",
07246 wkfn, fn, strerror(errno));
07247 (void)close(fr);
07248 (void)close(fw);
07249 (void)unlink(wkfn);
07250 goto retry;
07251 }
07252 }
07253 #endif
07254 write_io = prep_io(fw, FMODE_WRITABLE, rb_cFile, fn);
07255 rb_stdout = write_io;
07256 if (stdout_binmode) rb_io_binmode(rb_stdout);
07257 }
07258 fmode = FMODE_READABLE;
07259 if (!ARGF.binmode) {
07260 fmode |= DEFAULT_TEXTMODE;
07261 }
07262 ARGF.current_file = prep_io(fr, fmode, rb_cFile, fn);
07263 if (!NIL_P(write_io)) {
07264 rb_io_set_write_io(ARGF.current_file, write_io);
07265 }
07266 }
07267 if (ARGF.binmode) rb_io_ascii8bit_binmode(ARGF.current_file);
07268 GetOpenFile(ARGF.current_file, fptr);
07269 if (ARGF.encs.enc) {
07270 fptr->encs = ARGF.encs;
07271 clear_codeconv(fptr);
07272 }
07273 else {
07274 fptr->encs.ecflags &= ~ECONV_NEWLINE_DECORATOR_MASK;
07275 if (!ARGF.binmode) {
07276 fptr->encs.ecflags |= ECONV_DEFAULT_NEWLINE_DECORATOR;
07277 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
07278 fptr->encs.ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
07279 #endif
07280 }
07281 }
07282 ARGF.next_p = 0;
07283 }
07284 else {
07285 ARGF.next_p = 1;
07286 return FALSE;
07287 }
07288 }
07289 else if (ARGF.next_p == -1) {
07290 ARGF.current_file = rb_stdin;
07291 ARGF.filename = rb_str_new2("-");
07292 if (ARGF.inplace) {
07293 rb_warn("Can't do inplace edit for stdio");
07294 rb_stdout = orig_stdout;
07295 }
07296 }
07297 return TRUE;
07298 }
07299
07300 static VALUE
07301 argf_getline(int argc, VALUE *argv, VALUE argf)
07302 {
07303 VALUE line;
07304 long lineno = ARGF.lineno;
07305
07306 retry:
07307 if (!next_argv()) return Qnil;
07308 if (ARGF_GENERIC_INPUT_P()) {
07309 line = rb_funcall3(ARGF.current_file, rb_intern("gets"), argc, argv);
07310 }
07311 else {
07312 if (argc == 0 && rb_rs == rb_default_rs) {
07313 line = rb_io_gets(ARGF.current_file);
07314 }
07315 else {
07316 line = rb_io_getline(argc, argv, ARGF.current_file);
07317 }
07318 if (NIL_P(line) && ARGF.next_p != -1) {
07319 argf_close(ARGF.current_file);
07320 ARGF.next_p = 1;
07321 goto retry;
07322 }
07323 }
07324 if (!NIL_P(line)) {
07325 ARGF.lineno = ++lineno;
07326 ARGF.last_lineno = ARGF.lineno;
07327 }
07328 return line;
07329 }
07330
07331 static VALUE
07332 argf_lineno_getter(ID id, VALUE *var)
07333 {
07334 VALUE argf = *var;
07335 return INT2FIX(ARGF.last_lineno);
07336 }
07337
07338 static void
07339 argf_lineno_setter(VALUE val, ID id, VALUE *var)
07340 {
07341 VALUE argf = *var;
07342 int n = NUM2INT(val);
07343 ARGF.last_lineno = ARGF.lineno = n;
07344 }
07345
07346 static VALUE argf_gets(int, VALUE *, VALUE);
07347
07348
07349
07350
07351
07352
07353
07354
07355
07356
07357
07358
07359
07360
07361
07362
07363
07364
07365
07366
07367
07368
07369
07370
07371
07372
07373
07374
07375
07376
07377
07378
07379
07380
07381 static VALUE
07382 rb_f_gets(int argc, VALUE *argv, VALUE recv)
07383 {
07384 if (recv == argf) {
07385 return argf_gets(argc, argv, argf);
07386 }
07387 return rb_funcall2(argf, rb_intern("gets"), argc, argv);
07388 }
07389
07390
07391
07392
07393
07394
07395
07396
07397
07398
07399
07400
07401
07402
07403
07404
07405 static VALUE
07406 argf_gets(int argc, VALUE *argv, VALUE argf)
07407 {
07408 VALUE line;
07409
07410 line = argf_getline(argc, argv, argf);
07411 rb_lastline_set(line);
07412
07413 return line;
07414 }
07415
07416 VALUE
07417 rb_gets(void)
07418 {
07419 VALUE line;
07420
07421 if (rb_rs != rb_default_rs) {
07422 return rb_f_gets(0, 0, argf);
07423 }
07424
07425 retry:
07426 if (!next_argv()) return Qnil;
07427 line = rb_io_gets(ARGF.current_file);
07428 if (NIL_P(line) && ARGF.next_p != -1) {
07429 rb_io_close(ARGF.current_file);
07430 ARGF.next_p = 1;
07431 goto retry;
07432 }
07433 rb_lastline_set(line);
07434 if (!NIL_P(line)) {
07435 ARGF.lineno++;
07436 ARGF.last_lineno = ARGF.lineno;
07437 }
07438
07439 return line;
07440 }
07441
07442 static VALUE argf_readline(int, VALUE *, VALUE);
07443
07444
07445
07446
07447
07448
07449
07450
07451
07452
07453
07454 static VALUE
07455 rb_f_readline(int argc, VALUE *argv, VALUE recv)
07456 {
07457 if (recv == argf) {
07458 return argf_readline(argc, argv, argf);
07459 }
07460 return rb_funcall2(argf, rb_intern("readline"), argc, argv);
07461 }
07462
07463
07464
07465
07466
07467
07468
07469
07470
07471
07472
07473
07474
07475
07476
07477
07478
07479
07480 static VALUE
07481 argf_readline(int argc, VALUE *argv, VALUE argf)
07482 {
07483 VALUE line;
07484
07485 if (!next_argv()) rb_eof_error();
07486 ARGF_FORWARD(argc, argv);
07487 line = argf_gets(argc, argv, argf);
07488 if (NIL_P(line)) {
07489 rb_eof_error();
07490 }
07491
07492 return line;
07493 }
07494
07495 static VALUE argf_readlines(int, VALUE *, VALUE);
07496
07497
07498
07499
07500
07501
07502
07503
07504
07505
07506
07507 static VALUE
07508 rb_f_readlines(int argc, VALUE *argv, VALUE recv)
07509 {
07510 if (recv == argf) {
07511 return argf_readlines(argc, argv, argf);
07512 }
07513 return rb_funcall2(argf, rb_intern("readlines"), argc, argv);
07514 }
07515
07516
07517
07518
07519
07520
07521
07522
07523
07524
07525
07526
07527
07528
07529
07530
07531
07532 static VALUE
07533 argf_readlines(int argc, VALUE *argv, VALUE argf)
07534 {
07535 long lineno = ARGF.lineno;
07536 VALUE lines, ary;
07537
07538 ary = rb_ary_new();
07539 while (next_argv()) {
07540 if (ARGF_GENERIC_INPUT_P()) {
07541 lines = rb_funcall3(ARGF.current_file, rb_intern("readlines"), argc, argv);
07542 }
07543 else {
07544 lines = rb_io_readlines(argc, argv, ARGF.current_file);
07545 argf_close(ARGF.current_file);
07546 }
07547 ARGF.next_p = 1;
07548 rb_ary_concat(ary, lines);
07549 ARGF.lineno = lineno + RARRAY_LEN(ary);
07550 ARGF.last_lineno = ARGF.lineno;
07551 }
07552 ARGF.init_p = 0;
07553 return ary;
07554 }
07555
07556
07557
07558
07559
07560
07561
07562
07563
07564
07565
07566
07567
07568
07569
07570 static VALUE
07571 rb_f_backquote(VALUE obj, VALUE str)
07572 {
07573 volatile VALUE port;
07574 VALUE result;
07575 rb_io_t *fptr;
07576
07577 SafeStringValue(str);
07578 port = pipe_open_s(str, "r", FMODE_READABLE|DEFAULT_TEXTMODE, NULL);
07579 if (NIL_P(port)) return rb_str_new(0,0);
07580
07581 GetOpenFile(port, fptr);
07582 result = read_all(fptr, remain_size(fptr), Qnil);
07583 rb_io_close(port);
07584
07585 return result;
07586 }
07587
07588 #ifdef HAVE_SYS_SELECT_H
07589 #include <sys/select.h>
07590 #endif
07591
07592 static VALUE
07593 select_internal(VALUE read, VALUE write, VALUE except, struct timeval *tp, rb_fdset_t *fds)
07594 {
07595 VALUE res, list;
07596 rb_fdset_t *rp, *wp, *ep;
07597 rb_io_t *fptr;
07598 long i;
07599 int max = 0, n;
07600 int pending = 0;
07601 struct timeval timerec;
07602
07603 if (!NIL_P(read)) {
07604 Check_Type(read, T_ARRAY);
07605 for (i=0; i<RARRAY_LEN(read); i++) {
07606 GetOpenFile(rb_io_get_io(RARRAY_PTR(read)[i]), fptr);
07607 rb_fd_set(fptr->fd, &fds[0]);
07608 if (READ_DATA_PENDING(fptr) || READ_CHAR_PENDING(fptr)) {
07609 pending++;
07610 rb_fd_set(fptr->fd, &fds[3]);
07611 }
07612 if (max < fptr->fd) max = fptr->fd;
07613 }
07614 if (pending) {
07615 timerec.tv_sec = timerec.tv_usec = 0;
07616 tp = &timerec;
07617 }
07618 rp = &fds[0];
07619 }
07620 else
07621 rp = 0;
07622
07623 if (!NIL_P(write)) {
07624 Check_Type(write, T_ARRAY);
07625 for (i=0; i<RARRAY_LEN(write); i++) {
07626 VALUE write_io = GetWriteIO(rb_io_get_io(RARRAY_PTR(write)[i]));
07627 GetOpenFile(write_io, fptr);
07628 rb_fd_set(fptr->fd, &fds[1]);
07629 if (max < fptr->fd) max = fptr->fd;
07630 }
07631 wp = &fds[1];
07632 }
07633 else
07634 wp = 0;
07635
07636 if (!NIL_P(except)) {
07637 Check_Type(except, T_ARRAY);
07638 for (i=0; i<RARRAY_LEN(except); i++) {
07639 VALUE io = rb_io_get_io(RARRAY_PTR(except)[i]);
07640 VALUE write_io = GetWriteIO(io);
07641 GetOpenFile(io, fptr);
07642 rb_fd_set(fptr->fd, &fds[2]);
07643 if (max < fptr->fd) max = fptr->fd;
07644 if (io != write_io) {
07645 GetOpenFile(write_io, fptr);
07646 rb_fd_set(fptr->fd, &fds[2]);
07647 if (max < fptr->fd) max = fptr->fd;
07648 }
07649 }
07650 ep = &fds[2];
07651 }
07652 else {
07653 ep = 0;
07654 }
07655
07656 max++;
07657
07658 n = rb_thread_fd_select(max, rp, wp, ep, tp);
07659 if (n < 0) {
07660 rb_sys_fail(0);
07661 }
07662 if (!pending && n == 0) return Qnil;
07663
07664 res = rb_ary_new2(3);
07665 rb_ary_push(res, rp?rb_ary_new():rb_ary_new2(0));
07666 rb_ary_push(res, wp?rb_ary_new():rb_ary_new2(0));
07667 rb_ary_push(res, ep?rb_ary_new():rb_ary_new2(0));
07668
07669 if (rp) {
07670 list = RARRAY_PTR(res)[0];
07671 for (i=0; i< RARRAY_LEN(read); i++) {
07672 VALUE obj = rb_ary_entry(read, i);
07673 VALUE io = rb_io_get_io(obj);
07674 GetOpenFile(io, fptr);
07675 if (rb_fd_isset(fptr->fd, &fds[0]) ||
07676 rb_fd_isset(fptr->fd, &fds[3])) {
07677 rb_ary_push(list, obj);
07678 }
07679 }
07680 }
07681
07682 if (wp) {
07683 list = RARRAY_PTR(res)[1];
07684 for (i=0; i< RARRAY_LEN(write); i++) {
07685 VALUE obj = rb_ary_entry(write, i);
07686 VALUE io = rb_io_get_io(obj);
07687 VALUE write_io = GetWriteIO(io);
07688 GetOpenFile(write_io, fptr);
07689 if (rb_fd_isset(fptr->fd, &fds[1])) {
07690 rb_ary_push(list, obj);
07691 }
07692 }
07693 }
07694
07695 if (ep) {
07696 list = RARRAY_PTR(res)[2];
07697 for (i=0; i< RARRAY_LEN(except); i++) {
07698 VALUE obj = rb_ary_entry(except, i);
07699 VALUE io = rb_io_get_io(obj);
07700 VALUE write_io = GetWriteIO(io);
07701 GetOpenFile(io, fptr);
07702 if (rb_fd_isset(fptr->fd, &fds[2])) {
07703 rb_ary_push(list, obj);
07704 }
07705 else if (io != write_io) {
07706 GetOpenFile(write_io, fptr);
07707 if (rb_fd_isset(fptr->fd, &fds[2])) {
07708 rb_ary_push(list, obj);
07709 }
07710 }
07711 }
07712 }
07713
07714 return res;
07715 }
07716
07717 struct select_args {
07718 VALUE read, write, except;
07719 struct timeval *timeout;
07720 rb_fdset_t fdsets[4];
07721 };
07722
07723 static VALUE
07724 select_call(VALUE arg)
07725 {
07726 struct select_args *p = (struct select_args *)arg;
07727
07728 return select_internal(p->read, p->write, p->except, p->timeout, p->fdsets);
07729 }
07730
07731 static VALUE
07732 select_end(VALUE arg)
07733 {
07734 struct select_args *p = (struct select_args *)arg;
07735 int i;
07736
07737 for (i = 0; i < numberof(p->fdsets); ++i)
07738 rb_fd_term(&p->fdsets[i]);
07739 return Qnil;
07740 }
07741
07742 static VALUE sym_normal, sym_sequential, sym_random,
07743 sym_willneed, sym_dontneed, sym_noreuse;
07744
07745 #ifdef HAVE_POSIX_FADVISE
07746 struct io_advise_struct {
07747 int fd;
07748 off_t offset;
07749 off_t len;
07750 int advice;
07751 };
07752
07753 static VALUE
07754 io_advise_internal(void *arg)
07755 {
07756 struct io_advise_struct *ptr = arg;
07757 return posix_fadvise(ptr->fd, ptr->offset, ptr->len, ptr->advice);
07758 }
07759
07760 static VALUE
07761 io_advise_sym_to_const(VALUE sym)
07762 {
07763 #ifdef POSIX_FADV_NORMAL
07764 if (sym == sym_normal)
07765 return INT2NUM(POSIX_FADV_NORMAL);
07766 #endif
07767
07768 #ifdef POSIX_FADV_RANDOM
07769 if (sym == sym_random)
07770 return INT2NUM(POSIX_FADV_RANDOM);
07771 #endif
07772
07773 #ifdef POSIX_FADV_SEQUENTIAL
07774 if (sym == sym_sequential)
07775 return INT2NUM(POSIX_FADV_SEQUENTIAL);
07776 #endif
07777
07778 #ifdef POSIX_FADV_WILLNEED
07779 if (sym == sym_willneed)
07780 return INT2NUM(POSIX_FADV_WILLNEED);
07781 #endif
07782
07783 #ifdef POSIX_FADV_DONTNEED
07784 if (sym == sym_dontneed)
07785 return INT2NUM(POSIX_FADV_DONTNEED);
07786 #endif
07787
07788 #ifdef POSIX_FADV_NOREUSE
07789 if (sym == sym_noreuse)
07790 return INT2NUM(POSIX_FADV_NOREUSE);
07791 #endif
07792
07793 return Qnil;
07794 }
07795
07796 static VALUE
07797 do_io_advise(rb_io_t *fptr, VALUE advice, off_t offset, off_t len)
07798 {
07799 int rv;
07800 struct io_advise_struct ias;
07801 VALUE num_adv;
07802
07803 num_adv = io_advise_sym_to_const(advice);
07804
07805
07806
07807
07808
07809 if (num_adv == Qnil)
07810 return Qnil;
07811
07812 ias.fd = fptr->fd;
07813 ias.advice = NUM2INT(num_adv);
07814 ias.offset = offset;
07815 ias.len = len;
07816
07817 rv = (int)rb_thread_io_blocking_region(io_advise_internal, &ias, fptr->fd);
07818 if (rv)
07819
07820
07821 rb_syserr_fail(rv, RSTRING_PTR(fptr->pathv));
07822
07823 return Qnil;
07824 }
07825
07826 #endif
07827
07828 static void
07829 advice_arg_check(VALUE advice)
07830 {
07831 if (!SYMBOL_P(advice))
07832 rb_raise(rb_eTypeError, "advice must be a Symbol");
07833
07834 if (advice != sym_normal &&
07835 advice != sym_sequential &&
07836 advice != sym_random &&
07837 advice != sym_willneed &&
07838 advice != sym_dontneed &&
07839 advice != sym_noreuse) {
07840 VALUE symname = rb_inspect(advice);
07841 rb_raise(rb_eNotImpError, "Unsupported advice: %s",
07842 StringValuePtr(symname));
07843 }
07844 }
07845
07846
07847
07848
07849
07850
07851
07852
07853
07854
07855
07856
07857
07858
07859
07860
07861
07862
07863
07864
07865
07866
07867
07868
07869
07870
07871
07872
07873
07874
07875
07876
07877
07878
07879
07880
07881
07882
07883
07884
07885
07886
07887 static VALUE
07888 rb_io_advise(int argc, VALUE *argv, VALUE io)
07889 {
07890 VALUE advice, offset, len;
07891 off_t off, l;
07892 rb_io_t *fptr;
07893
07894 rb_scan_args(argc, argv, "12", &advice, &offset, &len);
07895 advice_arg_check(advice);
07896
07897 io = GetWriteIO(io);
07898 GetOpenFile(io, fptr);
07899
07900 off = NIL_P(offset) ? 0 : NUM2OFFT(offset);
07901 l = NIL_P(len) ? 0 : NUM2OFFT(len);
07902
07903 #ifdef HAVE_POSIX_FADVISE
07904 return do_io_advise(fptr, advice, off, l);
07905 #else
07906
07907 return Qnil;
07908 #endif
07909 }
07910
07911
07912
07913
07914
07915
07916
07917
07918
07919
07920
07921
07922
07923
07924
07925
07926
07927
07928
07929
07930
07931
07932
07933
07934
07935
07936
07937
07938
07939
07940
07941
07942
07943
07944
07945
07946
07947
07948
07949
07950
07951
07952
07953
07954
07955
07956
07957
07958
07959
07960
07961
07962 static VALUE
07963 rb_f_select(int argc, VALUE *argv, VALUE obj)
07964 {
07965 VALUE timeout;
07966 struct select_args args;
07967 struct timeval timerec;
07968 int i;
07969
07970 rb_scan_args(argc, argv, "13", &args.read, &args.write, &args.except, &timeout);
07971 if (NIL_P(timeout)) {
07972 args.timeout = 0;
07973 }
07974 else {
07975 timerec = rb_time_interval(timeout);
07976 args.timeout = &timerec;
07977 }
07978
07979 for (i = 0; i < numberof(args.fdsets); ++i)
07980 rb_fd_init(&args.fdsets[i]);
07981
07982 return rb_ensure(select_call, (VALUE)&args, select_end, (VALUE)&args);
07983 }
07984
07985 #if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
07986 typedef unsigned long ioctl_req_t;
07987 #define NUM2IOCTLREQ(num) NUM2ULONG(num)
07988 #else
07989 typedef int ioctl_req_t;
07990 #define NUM2IOCTLREQ(num) NUM2INT(num)
07991 #endif
07992
07993 struct ioctl_arg {
07994 int fd;
07995 ioctl_req_t cmd;
07996 long narg;
07997 };
07998
07999 static VALUE nogvl_ioctl(void *ptr)
08000 {
08001 struct ioctl_arg *arg = ptr;
08002
08003 return (VALUE)ioctl(arg->fd, arg->cmd, arg->narg);
08004 }
08005
08006 static int
08007 do_ioctl(int fd, ioctl_req_t cmd, long narg)
08008 {
08009 int retval;
08010 struct ioctl_arg arg;
08011
08012 arg.fd = fd;
08013 arg.cmd = cmd;
08014 arg.narg = narg;
08015
08016 retval = (int)rb_thread_io_blocking_region(nogvl_ioctl, &arg, fd);
08017
08018 return retval;
08019 }
08020
08021 #define DEFULT_IOCTL_NARG_LEN (256)
08022
08023 #ifdef __linux__
08024 static long
08025 linux_iocparm_len(ioctl_req_t cmd)
08026 {
08027 long len;
08028
08029 if ((cmd & 0xFFFF0000) == 0) {
08030
08031 return DEFULT_IOCTL_NARG_LEN;
08032 }
08033
08034 len = _IOC_SIZE(cmd);
08035
08036
08037 if (len < DEFULT_IOCTL_NARG_LEN)
08038 len = DEFULT_IOCTL_NARG_LEN;
08039
08040 return len;
08041 }
08042 #endif
08043
08044 static long
08045 ioctl_narg_len(ioctl_req_t cmd)
08046 {
08047 long len;
08048
08049 #ifdef IOCPARM_MASK
08050 #ifndef IOCPARM_LEN
08051 #define IOCPARM_LEN(x) (((x) >> 16) & IOCPARM_MASK)
08052 #endif
08053 #endif
08054 #ifdef IOCPARM_LEN
08055 len = IOCPARM_LEN(cmd);
08056 #elif defined(__linux__)
08057 len = linux_iocparm_len(cmd);
08058 #else
08059
08060 len = DEFULT_IOCTL_NARG_LEN;
08061 #endif
08062
08063 return len;
08064 }
08065
08066 #ifdef HAVE_FCNTL
08067 #ifdef __linux__
08068 typedef long fcntl_arg_t;
08069 #else
08070
08071 typedef int fcntl_arg_t;
08072 #endif
08073
08074 static long
08075 fcntl_narg_len(int cmd)
08076 {
08077 long len;
08078
08079 switch (cmd) {
08080 #ifdef F_DUPFD
08081 case F_DUPFD:
08082 len = sizeof(fcntl_arg_t);
08083 break;
08084 #endif
08085 #ifdef F_DUP2FD
08086 case F_DUP2FD:
08087 len = sizeof(int);
08088 break;
08089 #endif
08090 #ifdef F_DUPFD_CLOEXEC
08091 case F_DUPFD_CLOEXEC:
08092 len = sizeof(fcntl_arg_t);
08093 break;
08094 #endif
08095 #ifdef F_GETFD
08096 case F_GETFD:
08097 len = 1;
08098 break;
08099 #endif
08100 #ifdef F_SETFD
08101 case F_SETFD:
08102 len = sizeof(fcntl_arg_t);
08103 break;
08104 #endif
08105 #ifdef F_GETFL
08106 case F_GETFL:
08107 len = 1;
08108 break;
08109 #endif
08110 #ifdef F_SETFL
08111 case F_SETFL:
08112 len = sizeof(fcntl_arg_t);
08113 break;
08114 #endif
08115 #ifdef F_GETOWN
08116 case F_GETOWN:
08117 len = 1;
08118 break;
08119 #endif
08120 #ifdef F_SETOWN
08121 case F_SETOWN:
08122 len = sizeof(fcntl_arg_t);
08123 break;
08124 #endif
08125 #ifdef F_GETOWN_EX
08126 case F_GETOWN_EX:
08127 len = sizeof(struct f_owner_ex);
08128 break;
08129 #endif
08130 #ifdef F_SETOWN_EX
08131 case F_SETOWN_EX:
08132 len = sizeof(struct f_owner_ex);
08133 break;
08134 #endif
08135 #ifdef F_GETLK
08136 case F_GETLK:
08137 len = sizeof(struct flock);
08138 break;
08139 #endif
08140 #ifdef F_SETLK
08141 case F_SETLK:
08142 len = sizeof(struct flock);
08143 break;
08144 #endif
08145 #ifdef F_SETLKW
08146 case F_SETLKW:
08147 len = sizeof(struct flock);
08148 break;
08149 #endif
08150 #ifdef F_READAHEAD
08151 case F_READAHEAD:
08152 len = sizeof(int);
08153 break;
08154 #endif
08155 #ifdef F_RDAHEAD
08156 case F_RDAHEAD:
08157 len = sizeof(int);
08158 break;
08159 #endif
08160 #ifdef F_GETSIG
08161 case F_GETSIG:
08162 len = 1;
08163 break;
08164 #endif
08165 #ifdef F_SETSIG
08166 case F_SETSIG:
08167 len = sizeof(fcntl_arg_t);
08168 break;
08169 #endif
08170 #ifdef F_GETLEASE
08171 case F_GETLEASE:
08172 len = 1;
08173 break;
08174 #endif
08175 #ifdef F_SETLEASE
08176 case F_SETLEASE:
08177 len = sizeof(fcntl_arg_t);
08178 break;
08179 #endif
08180 #ifdef F_NOTIFY
08181 case F_NOTIFY:
08182 len = sizeof(fcntl_arg_t);
08183 break;
08184 #endif
08185
08186 default:
08187 len = 256;
08188 break;
08189 }
08190
08191 return len;
08192 }
08193 #else
08194 static long
08195 fcntl_narg_len(int cmd)
08196 {
08197 return 0;
08198 }
08199 #endif
08200
08201 static long
08202 setup_narg(ioctl_req_t cmd, VALUE *argp, int io_p)
08203 {
08204 long narg = 0;
08205 VALUE arg = *argp;
08206
08207 if (NIL_P(arg) || arg == Qfalse) {
08208 narg = 0;
08209 }
08210 else if (FIXNUM_P(arg)) {
08211 narg = FIX2LONG(arg);
08212 }
08213 else if (arg == Qtrue) {
08214 narg = 1;
08215 }
08216 else {
08217 VALUE tmp = rb_check_string_type(arg);
08218
08219 if (NIL_P(tmp)) {
08220 narg = NUM2LONG(arg);
08221 }
08222 else {
08223 long len;
08224
08225 *argp = arg = tmp;
08226 if (io_p)
08227 len = ioctl_narg_len(cmd);
08228 else
08229 len = fcntl_narg_len((int)cmd);
08230 rb_str_modify(arg);
08231
08232
08233 if (RSTRING_LEN(arg) < len+1) {
08234 rb_str_resize(arg, len+1);
08235 }
08236
08237 RSTRING_PTR(arg)[RSTRING_LEN(arg) - 1] = 17;
08238 narg = (long)(SIGNED_VALUE)RSTRING_PTR(arg);
08239 }
08240 }
08241 return narg;
08242 }
08243
08244 static VALUE
08245 rb_ioctl(VALUE io, VALUE req, VALUE arg)
08246 {
08247 ioctl_req_t cmd = NUM2IOCTLREQ(req);
08248 rb_io_t *fptr;
08249 long narg;
08250 int retval;
08251
08252 rb_secure(2);
08253
08254 narg = setup_narg(cmd, &arg, 1);
08255 GetOpenFile(io, fptr);
08256 retval = do_ioctl(fptr->fd, cmd, narg);
08257 if (retval < 0) rb_sys_fail_path(fptr->pathv);
08258 if (RB_TYPE_P(arg, T_STRING)) {
08259 if (RSTRING_PTR(arg)[RSTRING_LEN(arg)-1] != 17)
08260 rb_raise(rb_eArgError, "return value overflowed string");
08261 RSTRING_PTR(arg)[RSTRING_LEN(arg)-1] = '\0';
08262 }
08263
08264 return INT2NUM(retval);
08265 }
08266
08267
08268
08269
08270
08271
08272
08273
08274
08275
08276
08277
08278
08279 static VALUE
08280 rb_io_ioctl(int argc, VALUE *argv, VALUE io)
08281 {
08282 VALUE req, arg;
08283
08284 rb_scan_args(argc, argv, "11", &req, &arg);
08285 return rb_ioctl(io, req, arg);
08286 }
08287
08288 #ifdef HAVE_FCNTL
08289 struct fcntl_arg {
08290 int fd;
08291 int cmd;
08292 long narg;
08293 };
08294
08295 static VALUE nogvl_fcntl(void *ptr)
08296 {
08297 struct fcntl_arg *arg = ptr;
08298
08299 #if defined(F_DUPFD)
08300 if (arg->cmd == F_DUPFD)
08301 return (VALUE)rb_cloexec_fcntl_dupfd(arg->fd, (int)arg->narg);
08302 #endif
08303 return (VALUE)fcntl(arg->fd, arg->cmd, arg->narg);
08304 }
08305
08306 static int
08307 do_fcntl(int fd, int cmd, long narg)
08308 {
08309 int retval;
08310 struct fcntl_arg arg;
08311
08312 arg.fd = fd;
08313 arg.cmd = cmd;
08314 arg.narg = narg;
08315
08316 retval = (int)rb_thread_io_blocking_region(nogvl_fcntl, &arg, fd);
08317 #if defined(F_DUPFD)
08318 if (retval != -1 && cmd == F_DUPFD) {
08319 rb_update_max_fd(retval);
08320 }
08321 #endif
08322
08323 return retval;
08324 }
08325
08326 static VALUE
08327 rb_fcntl(VALUE io, VALUE req, VALUE arg)
08328 {
08329 int cmd = NUM2INT(req);
08330 rb_io_t *fptr;
08331 long narg;
08332 int retval;
08333
08334 rb_secure(2);
08335
08336 narg = setup_narg(cmd, &arg, 0);
08337 GetOpenFile(io, fptr);
08338 retval = do_fcntl(fptr->fd, cmd, narg);
08339 if (retval < 0) rb_sys_fail_path(fptr->pathv);
08340 if (RB_TYPE_P(arg, T_STRING)) {
08341 if (RSTRING_PTR(arg)[RSTRING_LEN(arg)-1] != 17)
08342 rb_raise(rb_eArgError, "return value overflowed string");
08343 RSTRING_PTR(arg)[RSTRING_LEN(arg)-1] = '\0';
08344 }
08345
08346 if (cmd == F_SETFL) {
08347 if (narg & O_NONBLOCK) {
08348 fptr->mode |= FMODE_WSPLIT_INITIALIZED;
08349 fptr->mode &= ~FMODE_WSPLIT;
08350 }
08351 else {
08352 fptr->mode &= ~(FMODE_WSPLIT_INITIALIZED|FMODE_WSPLIT);
08353 }
08354 }
08355
08356 return INT2NUM(retval);
08357 }
08358
08359
08360
08361
08362
08363
08364
08365
08366
08367
08368
08369
08370
08371
08372 static VALUE
08373 rb_io_fcntl(int argc, VALUE *argv, VALUE io)
08374 {
08375 VALUE req, arg;
08376
08377 rb_scan_args(argc, argv, "11", &req, &arg);
08378 return rb_fcntl(io, req, arg);
08379 }
08380 #else
08381 #define rb_io_fcntl rb_f_notimplement
08382 #endif
08383
08384 #if defined(HAVE_SYSCALL) || defined(HAVE___SYSCALL)
08385
08386
08387
08388
08389
08390
08391
08392
08393
08394
08395
08396
08397
08398
08399
08400
08401
08402
08403
08404
08405
08406
08407
08408
08409
08410
08411
08412
08413
08414
08415
08416
08417
08418 static VALUE
08419 rb_f_syscall(int argc, VALUE *argv)
08420 {
08421 #ifdef atarist
08422 VALUE arg[13];
08423 #else
08424 VALUE arg[8];
08425 #endif
08426 #if SIZEOF_VOIDP == 8 && defined(HAVE___SYSCALL) && SIZEOF_INT != 8
08427 # define SYSCALL __syscall
08428 # define NUM2SYSCALLID(x) NUM2LONG(x)
08429 # define RETVAL2NUM(x) LONG2NUM(x)
08430 # if SIZEOF_LONG == 8
08431 long num, retval = -1;
08432 # elif SIZEOF_LONG_LONG == 8
08433 long long num, retval = -1;
08434 # else
08435 # error ---->> it is asserted that __syscall takes the first argument and returns retval in 64bit signed integer. <<----
08436 # endif
08437 #elif defined linux
08438 # define SYSCALL syscall
08439 # define NUM2SYSCALLID(x) NUM2LONG(x)
08440 # define RETVAL2NUM(x) LONG2NUM(x)
08441
08442
08443
08444
08445
08446
08447
08448 long num, retval = -1;
08449 #else
08450 # define SYSCALL syscall
08451 # define NUM2SYSCALLID(x) NUM2INT(x)
08452 # define RETVAL2NUM(x) INT2NUM(x)
08453 int num, retval = -1;
08454 #endif
08455 int i;
08456
08457 if (RTEST(ruby_verbose)) {
08458 rb_warning("We plan to remove a syscall function at future release. DL(Fiddle) provides safer alternative.");
08459 }
08460
08461 rb_secure(2);
08462 if (argc == 0)
08463 rb_raise(rb_eArgError, "too few arguments for syscall");
08464 if (argc > numberof(arg))
08465 rb_raise(rb_eArgError, "too many arguments for syscall");
08466 num = NUM2SYSCALLID(argv[0]); ++argv;
08467 for (i = argc - 1; i--; ) {
08468 VALUE v = rb_check_string_type(argv[i]);
08469
08470 if (!NIL_P(v)) {
08471 SafeStringValue(v);
08472 rb_str_modify(v);
08473 arg[i] = (VALUE)StringValueCStr(v);
08474 }
08475 else {
08476 arg[i] = (VALUE)NUM2LONG(argv[i]);
08477 }
08478 }
08479
08480 switch (argc) {
08481 case 1:
08482 retval = SYSCALL(num);
08483 break;
08484 case 2:
08485 retval = SYSCALL(num, arg[0]);
08486 break;
08487 case 3:
08488 retval = SYSCALL(num, arg[0],arg[1]);
08489 break;
08490 case 4:
08491 retval = SYSCALL(num, arg[0],arg[1],arg[2]);
08492 break;
08493 case 5:
08494 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3]);
08495 break;
08496 case 6:
08497 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4]);
08498 break;
08499 case 7:
08500 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5]);
08501 break;
08502 case 8:
08503 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6]);
08504 break;
08505 #ifdef atarist
08506 case 9:
08507 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
08508 arg[7]);
08509 break;
08510 case 10:
08511 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
08512 arg[7], arg[8]);
08513 break;
08514 case 11:
08515 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
08516 arg[7], arg[8], arg[9]);
08517 break;
08518 case 12:
08519 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
08520 arg[7], arg[8], arg[9], arg[10]);
08521 break;
08522 case 13:
08523 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
08524 arg[7], arg[8], arg[9], arg[10], arg[11]);
08525 break;
08526 case 14:
08527 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
08528 arg[7], arg[8], arg[9], arg[10], arg[11], arg[12]);
08529 break;
08530 #endif
08531 }
08532
08533 if (retval == -1)
08534 rb_sys_fail(0);
08535 return RETVAL2NUM(retval);
08536 #undef SYSCALL
08537 #undef NUM2SYSCALLID
08538 #undef RETVAL2NUM
08539 }
08540 #else
08541 #define rb_f_syscall rb_f_notimplement
08542 #endif
08543
08544 static VALUE
08545 io_new_instance(VALUE args)
08546 {
08547 return rb_class_new_instance(2, (VALUE*)args+1, *(VALUE*)args);
08548 }
08549
08550 static void
08551 io_encoding_set(rb_io_t *fptr, VALUE v1, VALUE v2, VALUE opt)
08552 {
08553 rb_encoding *enc, *enc2;
08554 int ecflags = fptr->encs.ecflags;
08555 VALUE ecopts, tmp;
08556
08557 if (!NIL_P(v2)) {
08558 enc2 = rb_to_encoding(v1);
08559 tmp = rb_check_string_type(v2);
08560 if (!NIL_P(tmp)) {
08561 if (RSTRING_LEN(tmp) == 1 && RSTRING_PTR(tmp)[0] == '-') {
08562
08563 enc = enc2;
08564 enc2 = NULL;
08565 }
08566 else
08567 enc = rb_to_encoding(v2);
08568 if (enc == enc2) {
08569
08570 enc2 = NULL;
08571 }
08572 }
08573 else
08574 enc = rb_to_encoding(v2);
08575 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
08576 ecflags = rb_econv_prepare_options(opt, &ecopts, ecflags);
08577 }
08578 else {
08579 if (NIL_P(v1)) {
08580
08581 rb_io_ext_int_to_encs(NULL, NULL, &enc, &enc2);
08582 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
08583 ecopts = Qnil;
08584 }
08585 else {
08586 tmp = rb_check_string_type(v1);
08587 if (!NIL_P(tmp) && rb_enc_asciicompat(rb_enc_get(tmp))) {
08588 parse_mode_enc(RSTRING_PTR(tmp), &enc, &enc2, NULL);
08589 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
08590 ecflags = rb_econv_prepare_options(opt, &ecopts, ecflags);
08591 }
08592 else {
08593 rb_io_ext_int_to_encs(rb_to_encoding(v1), NULL, &enc, &enc2);
08594 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
08595 ecopts = Qnil;
08596 }
08597 }
08598 }
08599 validate_enc_binmode(&fptr->mode, ecflags, enc, enc2);
08600 fptr->encs.enc = enc;
08601 fptr->encs.enc2 = enc2;
08602 fptr->encs.ecflags = ecflags;
08603 fptr->encs.ecopts = ecopts;
08604 clear_codeconv(fptr);
08605
08606 }
08607
08608 static VALUE
08609 pipe_pair_close(VALUE rw)
08610 {
08611 VALUE *rwp = (VALUE *)rw;
08612 return rb_ensure(io_close, rwp[0], io_close, rwp[1]);
08613 }
08614
08615
08616
08617
08618
08619
08620
08621
08622
08623
08624
08625
08626
08627
08628
08629
08630
08631
08632
08633
08634
08635
08636
08637
08638
08639
08640
08641
08642
08643
08644
08645
08646
08647
08648
08649
08650
08651
08652
08653
08654
08655
08656
08657
08658
08659
08660
08661
08662
08663
08664
08665
08666
08667
08668
08669
08670
08671
08672
08673
08674
08675 static VALUE
08676 rb_io_s_pipe(int argc, VALUE *argv, VALUE klass)
08677 {
08678 int pipes[2], state;
08679 VALUE r, w, args[3], v1, v2;
08680 VALUE opt;
08681 rb_io_t *fptr, *fptr2;
08682 int fmode = 0;
08683 VALUE ret;
08684
08685 argc = rb_scan_args(argc, argv, "02:", &v1, &v2, &opt);
08686 if (rb_pipe(pipes) == -1)
08687 rb_sys_fail(0);
08688
08689 args[0] = klass;
08690 args[1] = INT2NUM(pipes[0]);
08691 args[2] = INT2FIX(O_RDONLY);
08692 r = rb_protect(io_new_instance, (VALUE)args, &state);
08693 if (state) {
08694 close(pipes[0]);
08695 close(pipes[1]);
08696 rb_jump_tag(state);
08697 }
08698 GetOpenFile(r, fptr);
08699 io_encoding_set(fptr, v1, v2, opt);
08700 args[1] = INT2NUM(pipes[1]);
08701 args[2] = INT2FIX(O_WRONLY);
08702 w = rb_protect(io_new_instance, (VALUE)args, &state);
08703 if (state) {
08704 close(pipes[1]);
08705 if (!NIL_P(r)) rb_io_close(r);
08706 rb_jump_tag(state);
08707 }
08708 GetOpenFile(w, fptr2);
08709 rb_io_synchronized(fptr2);
08710
08711 extract_binmode(opt, &fmode);
08712 #if DEFAULT_TEXTMODE
08713 if ((fptr->mode & FMODE_TEXTMODE) && (fmode & FMODE_BINMODE)) {
08714 fptr->mode &= ~FMODE_TEXTMODE;
08715 setmode(fptr->fd, O_BINARY);
08716 }
08717 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
08718 if (fptr->encs.ecflags & ECONV_DEFAULT_NEWLINE_DECORATOR) {
08719 fptr->encs.ecflags |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;
08720 }
08721 #endif
08722 #endif
08723 fptr->mode |= fmode;
08724 #if DEFAULT_TEXTMODE
08725 if ((fptr2->mode & FMODE_TEXTMODE) && (fmode & FMODE_BINMODE)) {
08726 fptr2->mode &= ~FMODE_TEXTMODE;
08727 setmode(fptr2->fd, O_BINARY);
08728 }
08729 #endif
08730 fptr2->mode |= fmode;
08731
08732 ret = rb_assoc_new(r, w);
08733 if (rb_block_given_p()) {
08734 VALUE rw[2];
08735 rw[0] = r;
08736 rw[1] = w;
08737 return rb_ensure(rb_yield, ret, pipe_pair_close, (VALUE)rw);
08738 }
08739 return ret;
08740 }
08741
08742 struct foreach_arg {
08743 int argc;
08744 VALUE *argv;
08745 VALUE io;
08746 };
08747
08748 static void
08749 open_key_args(int argc, VALUE *argv, VALUE opt, struct foreach_arg *arg)
08750 {
08751 VALUE path, v;
08752
08753 path = *argv++;
08754 argc--;
08755 FilePathValue(path);
08756 arg->io = 0;
08757 arg->argc = argc;
08758 arg->argv = argv;
08759 if (NIL_P(opt)) {
08760 arg->io = rb_io_open(path, INT2NUM(O_RDONLY), INT2FIX(0666), Qnil);
08761 return;
08762 }
08763 v = rb_hash_aref(opt, sym_open_args);
08764 if (!NIL_P(v)) {
08765 VALUE args;
08766 long n;
08767
08768 v = rb_convert_type(v, T_ARRAY, "Array", "to_ary");
08769 n = RARRAY_LEN(v) + 1;
08770 #if SIZEOF_LONG > SIZEOF_INT
08771 if (n > INT_MAX) {
08772 rb_raise(rb_eArgError, "too many arguments");
08773 }
08774 #endif
08775 args = rb_ary_tmp_new(n);
08776 rb_ary_push(args, path);
08777 rb_ary_concat(args, v);
08778 arg->io = rb_io_open_with_args((int)n, RARRAY_PTR(args));
08779 rb_ary_clear(args);
08780 return;
08781 }
08782 arg->io = rb_io_open(path, Qnil, Qnil, opt);
08783 }
08784
08785 static VALUE
08786 io_s_foreach(struct foreach_arg *arg)
08787 {
08788 VALUE str;
08789
08790 while (!NIL_P(str = rb_io_gets_m(arg->argc, arg->argv, arg->io))) {
08791 rb_yield(str);
08792 }
08793 return Qnil;
08794 }
08795
08796
08797
08798
08799
08800
08801
08802
08803
08804
08805
08806
08807
08808
08809
08810
08811
08812
08813
08814
08815
08816
08817
08818
08819
08820
08821
08822 static VALUE
08823 rb_io_s_foreach(int argc, VALUE *argv, VALUE self)
08824 {
08825 VALUE opt;
08826 int orig_argc = argc;
08827 struct foreach_arg arg;
08828
08829 argc = rb_scan_args(argc, argv, "13:", NULL, NULL, NULL, NULL, &opt);
08830 RETURN_ENUMERATOR(self, orig_argc, argv);
08831 open_key_args(argc, argv, opt, &arg);
08832 if (NIL_P(arg.io)) return Qnil;
08833 return rb_ensure(io_s_foreach, (VALUE)&arg, rb_io_close, arg.io);
08834 }
08835
08836 static VALUE
08837 io_s_readlines(struct foreach_arg *arg)
08838 {
08839 return rb_io_readlines(arg->argc, arg->argv, arg->io);
08840 }
08841
08842
08843
08844
08845
08846
08847
08848
08849
08850
08851
08852
08853
08854
08855
08856
08857
08858
08859
08860 static VALUE
08861 rb_io_s_readlines(int argc, VALUE *argv, VALUE io)
08862 {
08863 VALUE opt;
08864 struct foreach_arg arg;
08865
08866 argc = rb_scan_args(argc, argv, "13:", NULL, NULL, NULL, NULL, &opt);
08867 open_key_args(argc, argv, opt, &arg);
08868 if (NIL_P(arg.io)) return Qnil;
08869 return rb_ensure(io_s_readlines, (VALUE)&arg, rb_io_close, arg.io);
08870 }
08871
08872 static VALUE
08873 io_s_read(struct foreach_arg *arg)
08874 {
08875 return io_read(arg->argc, arg->argv, arg->io);
08876 }
08877
08878 struct seek_arg {
08879 VALUE io;
08880 VALUE offset;
08881 int mode;
08882 };
08883
08884 static VALUE
08885 seek_before_access(VALUE argp)
08886 {
08887 struct seek_arg *arg = (struct seek_arg *)argp;
08888 rb_io_binmode(arg->io);
08889 return rb_io_seek(arg->io, arg->offset, arg->mode);
08890 }
08891
08892
08893
08894
08895
08896
08897
08898
08899
08900
08901
08902
08903
08904
08905
08906
08907
08908
08909
08910
08911
08912
08913
08914
08915
08916
08917
08918
08919
08920
08921
08922
08923
08924 static VALUE
08925 rb_io_s_read(int argc, VALUE *argv, VALUE io)
08926 {
08927 VALUE opt, offset;
08928 struct foreach_arg arg;
08929
08930 argc = rb_scan_args(argc, argv, "13:", NULL, NULL, &offset, NULL, &opt);
08931 open_key_args(argc, argv, opt, &arg);
08932 if (NIL_P(arg.io)) return Qnil;
08933 if (!NIL_P(offset)) {
08934 struct seek_arg sarg;
08935 int state = 0;
08936 sarg.io = arg.io;
08937 sarg.offset = offset;
08938 sarg.mode = SEEK_SET;
08939 rb_protect(seek_before_access, (VALUE)&sarg, &state);
08940 if (state) {
08941 rb_io_close(arg.io);
08942 rb_jump_tag(state);
08943 }
08944 if (arg.argc == 2) arg.argc = 1;
08945 }
08946 return rb_ensure(io_s_read, (VALUE)&arg, rb_io_close, arg.io);
08947 }
08948
08949
08950
08951
08952
08953
08954
08955
08956
08957
08958
08959
08960
08961
08962
08963 static VALUE
08964 rb_io_s_binread(int argc, VALUE *argv, VALUE io)
08965 {
08966 VALUE offset;
08967 struct foreach_arg arg;
08968
08969 rb_scan_args(argc, argv, "12", NULL, NULL, &offset);
08970 FilePathValue(argv[0]);
08971 arg.io = rb_io_open(argv[0], rb_str_new_cstr("rb:ASCII-8BIT"), Qnil, Qnil);
08972 if (NIL_P(arg.io)) return Qnil;
08973 arg.argv = argv+1;
08974 arg.argc = (argc > 1) ? 1 : 0;
08975 if (!NIL_P(offset)) {
08976 rb_io_seek(arg.io, offset, SEEK_SET);
08977 }
08978 return rb_ensure(io_s_read, (VALUE)&arg, rb_io_close, arg.io);
08979 }
08980
08981 static VALUE
08982 io_s_write0(struct write_arg *arg)
08983 {
08984 return io_write(arg->io,arg->str,arg->nosync);
08985 }
08986
08987 static VALUE
08988 io_s_write(int argc, VALUE *argv, int binary)
08989 {
08990 VALUE string, offset, opt;
08991 struct foreach_arg arg;
08992 struct write_arg warg;
08993
08994 rb_scan_args(argc, argv, "21:", NULL, &string, &offset, &opt);
08995
08996 if (NIL_P(opt)) opt = rb_hash_new();
08997 else opt = rb_hash_dup(opt);
08998
08999
09000 if (NIL_P(rb_hash_aref(opt,sym_mode))) {
09001 int mode = O_WRONLY|O_CREAT;
09002 #ifdef O_BINARY
09003 if (binary) mode |= O_BINARY;
09004 #endif
09005 if (NIL_P(offset)) mode |= O_TRUNC;
09006 rb_hash_aset(opt,sym_mode,INT2NUM(mode));
09007 }
09008 open_key_args(argc,argv,opt,&arg);
09009
09010 #ifndef O_BINARY
09011 if (binary) rb_io_binmode_m(arg.io);
09012 #endif
09013
09014 if (NIL_P(arg.io)) return Qnil;
09015 if (!NIL_P(offset)) {
09016 struct seek_arg sarg;
09017 int state = 0;
09018 sarg.io = arg.io;
09019 sarg.offset = offset;
09020 sarg.mode = SEEK_SET;
09021 rb_protect(seek_before_access, (VALUE)&sarg, &state);
09022 if (state) {
09023 rb_io_close(arg.io);
09024 rb_jump_tag(state);
09025 }
09026 }
09027
09028 warg.io = arg.io;
09029 warg.str = string;
09030 warg.nosync = 0;
09031
09032 return rb_ensure(io_s_write0, (VALUE)&warg, rb_io_close, arg.io);
09033 }
09034
09035
09036
09037
09038
09039
09040
09041
09042
09043
09044
09045
09046
09047
09048
09049
09050
09051
09052
09053
09054
09055
09056
09057
09058
09059
09060
09061
09062
09063
09064
09065
09066
09067
09068
09069
09070
09071
09072
09073
09074 static VALUE
09075 rb_io_s_write(int argc, VALUE *argv, VALUE io)
09076 {
09077 return io_s_write(argc, argv, 0);
09078 }
09079
09080
09081
09082
09083
09084
09085
09086
09087
09088
09089
09090
09091
09092
09093
09094
09095
09096
09097 static VALUE
09098 rb_io_s_binwrite(int argc, VALUE *argv, VALUE io)
09099 {
09100 return io_s_write(argc, argv, 1);
09101 }
09102
09103 struct copy_stream_struct {
09104 VALUE src;
09105 VALUE dst;
09106 off_t copy_length;
09107 off_t src_offset;
09108
09109 int src_fd;
09110 int dst_fd;
09111 int close_src;
09112 int close_dst;
09113 off_t total;
09114 const char *syserr;
09115 int error_no;
09116 const char *notimp;
09117 rb_fdset_t fds;
09118 VALUE th;
09119 };
09120
09121 static void *
09122 exec_interrupts(void *arg)
09123 {
09124 VALUE th = (VALUE)arg;
09125 rb_thread_execute_interrupts(th);
09126 return NULL;
09127 }
09128
09129
09130
09131
09132
09133
09134 static int
09135 maygvl_copy_stream_continue_p(int has_gvl, struct copy_stream_struct *stp)
09136 {
09137 switch (errno) {
09138 case EINTR:
09139 #if defined(ERESTART)
09140 case ERESTART:
09141 #endif
09142 if (rb_thread_interrupted(stp->th)) {
09143 if (has_gvl)
09144 rb_thread_execute_interrupts(stp->th);
09145 else
09146 rb_thread_call_with_gvl(exec_interrupts, (void *)stp->th);
09147 }
09148 return TRUE;
09149 }
09150 return FALSE;
09151 }
09152
09153 static int
09154 maygvl_select(int has_gvl, int n, rb_fdset_t *rfds, rb_fdset_t *wfds, rb_fdset_t *efds, struct timeval *timeout)
09155 {
09156 if (has_gvl)
09157 return rb_thread_fd_select(n, rfds, wfds, efds, timeout);
09158 else
09159 return rb_fd_select(n, rfds, wfds, efds, timeout);
09160 }
09161
09162 static int
09163 maygvl_copy_stream_wait_read(int has_gvl, struct copy_stream_struct *stp)
09164 {
09165 int ret;
09166
09167 do {
09168 rb_fd_zero(&stp->fds);
09169 rb_fd_set(stp->src_fd, &stp->fds);
09170 ret = maygvl_select(has_gvl, rb_fd_max(&stp->fds), &stp->fds, NULL, NULL, NULL);
09171 } while (ret == -1 && maygvl_copy_stream_continue_p(has_gvl, stp));
09172
09173 if (ret == -1) {
09174 stp->syserr = "select";
09175 stp->error_no = errno;
09176 return -1;
09177 }
09178 return 0;
09179 }
09180
09181 static int
09182 nogvl_copy_stream_wait_write(struct copy_stream_struct *stp)
09183 {
09184 int ret;
09185
09186 do {
09187 rb_fd_zero(&stp->fds);
09188 rb_fd_set(stp->dst_fd, &stp->fds);
09189 ret = rb_fd_select(rb_fd_max(&stp->fds), NULL, &stp->fds, NULL, NULL);
09190 } while (ret == -1 && maygvl_copy_stream_continue_p(0, stp));
09191
09192 if (ret == -1) {
09193 stp->syserr = "select";
09194 stp->error_no = errno;
09195 return -1;
09196 }
09197 return 0;
09198 }
09199
09200 #ifdef HAVE_SENDFILE
09201
09202 # ifdef __linux__
09203 # define USE_SENDFILE
09204
09205 # ifdef HAVE_SYS_SENDFILE_H
09206 # include <sys/sendfile.h>
09207 # endif
09208
09209 static ssize_t
09210 simple_sendfile(int out_fd, int in_fd, off_t *offset, off_t count)
09211 {
09212 return sendfile(out_fd, in_fd, offset, (size_t)count);
09213 }
09214
09215 # elif 0 || defined(__APPLE__)
09216
09217
09218
09219 # define USE_SENDFILE
09220
09221 # ifdef HAVE_SYS_UIO_H
09222 # include <sys/uio.h>
09223 # endif
09224
09225 static ssize_t
09226 simple_sendfile(int out_fd, int in_fd, off_t *offset, off_t count)
09227 {
09228 int r;
09229 off_t pos = offset ? *offset : lseek(in_fd, 0, SEEK_CUR);
09230 off_t sbytes;
09231 # ifdef __APPLE__
09232 r = sendfile(in_fd, out_fd, pos, &count, NULL, 0);
09233 sbytes = count;
09234 # else
09235 r = sendfile(in_fd, out_fd, pos, (size_t)count, NULL, &sbytes, 0);
09236 # endif
09237 if (r != 0 && sbytes == 0) return -1;
09238 if (offset) {
09239 *offset += sbytes;
09240 }
09241 else {
09242 lseek(in_fd, sbytes, SEEK_CUR);
09243 }
09244 return (ssize_t)sbytes;
09245 }
09246
09247 # endif
09248
09249 #endif
09250
09251 #ifdef USE_SENDFILE
09252 static int
09253 nogvl_copy_stream_sendfile(struct copy_stream_struct *stp)
09254 {
09255 struct stat src_stat, dst_stat;
09256 ssize_t ss;
09257 int ret;
09258
09259 off_t copy_length;
09260 off_t src_offset;
09261 int use_pread;
09262
09263 ret = fstat(stp->src_fd, &src_stat);
09264 if (ret == -1) {
09265 stp->syserr = "fstat";
09266 stp->error_no = errno;
09267 return -1;
09268 }
09269 if (!S_ISREG(src_stat.st_mode))
09270 return 0;
09271
09272 ret = fstat(stp->dst_fd, &dst_stat);
09273 if (ret == -1) {
09274 stp->syserr = "fstat";
09275 stp->error_no = errno;
09276 return -1;
09277 }
09278 if ((dst_stat.st_mode & S_IFMT) != S_IFSOCK)
09279 return 0;
09280
09281 src_offset = stp->src_offset;
09282 use_pread = src_offset != (off_t)-1;
09283
09284 copy_length = stp->copy_length;
09285 if (copy_length == (off_t)-1) {
09286 if (use_pread)
09287 copy_length = src_stat.st_size - src_offset;
09288 else {
09289 off_t cur;
09290 errno = 0;
09291 cur = lseek(stp->src_fd, 0, SEEK_CUR);
09292 if (cur == (off_t)-1 && errno) {
09293 stp->syserr = "lseek";
09294 stp->error_no = errno;
09295 return -1;
09296 }
09297 copy_length = src_stat.st_size - cur;
09298 }
09299 }
09300
09301 retry_sendfile:
09302 # if SIZEOF_OFF_T > SIZEOF_SIZE_T
09303
09304 ss = (copy_length > (off_t)SSIZE_MAX) ? SSIZE_MAX : (ssize_t)copy_length;
09305 # else
09306 ss = (ssize_t)copy_length;
09307 # endif
09308 if (use_pread) {
09309 ss = simple_sendfile(stp->dst_fd, stp->src_fd, &src_offset, ss);
09310 }
09311 else {
09312 ss = simple_sendfile(stp->dst_fd, stp->src_fd, NULL, ss);
09313 }
09314 if (0 < ss) {
09315 stp->total += ss;
09316 copy_length -= ss;
09317 if (0 < copy_length) {
09318 goto retry_sendfile;
09319 }
09320 }
09321 if (ss == -1) {
09322 if (maygvl_copy_stream_continue_p(0, stp))
09323 goto retry_sendfile;
09324 switch (errno) {
09325 case EINVAL:
09326 #ifdef ENOSYS
09327 case ENOSYS:
09328 #endif
09329 return 0;
09330 case EAGAIN:
09331 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
09332 case EWOULDBLOCK:
09333 #endif
09334 #ifndef linux
09335
09336
09337
09338
09339
09340
09341
09342 if (maygvl_copy_stream_wait_read(0, stp) == -1)
09343 return -1;
09344 #endif
09345 if (nogvl_copy_stream_wait_write(stp) == -1)
09346 return -1;
09347 goto retry_sendfile;
09348 }
09349 stp->syserr = "sendfile";
09350 stp->error_no = errno;
09351 return -1;
09352 }
09353 return 1;
09354 }
09355 #endif
09356
09357 static ssize_t
09358 maygvl_read(int has_gvl, int fd, void *buf, size_t count)
09359 {
09360 if (has_gvl)
09361 return rb_read_internal(fd, buf, count);
09362 else
09363 return read(fd, buf, count);
09364 }
09365
09366 static ssize_t
09367 maygvl_copy_stream_read(int has_gvl, struct copy_stream_struct *stp, char *buf, size_t len, off_t offset)
09368 {
09369 ssize_t ss;
09370 retry_read:
09371 if (offset == (off_t)-1) {
09372 ss = maygvl_read(has_gvl, stp->src_fd, buf, len);
09373 }
09374 else {
09375 #ifdef HAVE_PREAD
09376 ss = pread(stp->src_fd, buf, len, offset);
09377 #else
09378 stp->notimp = "pread";
09379 return -1;
09380 #endif
09381 }
09382 if (ss == 0) {
09383 return 0;
09384 }
09385 if (ss == -1) {
09386 if (maygvl_copy_stream_continue_p(has_gvl, stp))
09387 goto retry_read;
09388 switch (errno) {
09389 case EAGAIN:
09390 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
09391 case EWOULDBLOCK:
09392 #endif
09393 if (maygvl_copy_stream_wait_read(has_gvl, stp) == -1)
09394 return -1;
09395 goto retry_read;
09396 #ifdef ENOSYS
09397 case ENOSYS:
09398 #endif
09399 stp->notimp = "pread";
09400 return -1;
09401 }
09402 stp->syserr = offset == (off_t)-1 ? "read" : "pread";
09403 stp->error_no = errno;
09404 return -1;
09405 }
09406 return ss;
09407 }
09408
09409 static int
09410 nogvl_copy_stream_write(struct copy_stream_struct *stp, char *buf, size_t len)
09411 {
09412 ssize_t ss;
09413 int off = 0;
09414 while (len) {
09415 ss = write(stp->dst_fd, buf+off, len);
09416 if (ss == -1) {
09417 if (maygvl_copy_stream_continue_p(0, stp))
09418 continue;
09419 if (errno == EAGAIN || errno == EWOULDBLOCK) {
09420 if (nogvl_copy_stream_wait_write(stp) == -1)
09421 return -1;
09422 continue;
09423 }
09424 stp->syserr = "write";
09425 stp->error_no = errno;
09426 return -1;
09427 }
09428 off += (int)ss;
09429 len -= (int)ss;
09430 stp->total += ss;
09431 }
09432 return 0;
09433 }
09434
09435 static void
09436 nogvl_copy_stream_read_write(struct copy_stream_struct *stp)
09437 {
09438 char buf[1024*16];
09439 size_t len;
09440 ssize_t ss;
09441 int ret;
09442 off_t copy_length;
09443 int use_eof;
09444 off_t src_offset;
09445 int use_pread;
09446
09447 copy_length = stp->copy_length;
09448 use_eof = copy_length == (off_t)-1;
09449 src_offset = stp->src_offset;
09450 use_pread = src_offset != (off_t)-1;
09451
09452 if (use_pread && stp->close_src) {
09453 off_t r;
09454 errno = 0;
09455 r = lseek(stp->src_fd, src_offset, SEEK_SET);
09456 if (r == (off_t)-1 && errno) {
09457 stp->syserr = "lseek";
09458 stp->error_no = errno;
09459 return;
09460 }
09461 src_offset = (off_t)-1;
09462 use_pread = 0;
09463 }
09464
09465 while (use_eof || 0 < copy_length) {
09466 if (!use_eof && copy_length < (off_t)sizeof(buf)) {
09467 len = (size_t)copy_length;
09468 }
09469 else {
09470 len = sizeof(buf);
09471 }
09472 if (use_pread) {
09473 ss = maygvl_copy_stream_read(0, stp, buf, len, src_offset);
09474 if (0 < ss)
09475 src_offset += ss;
09476 }
09477 else {
09478 ss = maygvl_copy_stream_read(0, stp, buf, len, (off_t)-1);
09479 }
09480 if (ss <= 0)
09481 return;
09482
09483 ret = nogvl_copy_stream_write(stp, buf, ss);
09484 if (ret < 0)
09485 return;
09486
09487 if (!use_eof)
09488 copy_length -= ss;
09489 }
09490 }
09491
09492 static VALUE
09493 nogvl_copy_stream_func(void *arg)
09494 {
09495 struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
09496 #ifdef USE_SENDFILE
09497 int ret;
09498 #endif
09499
09500 #ifdef USE_SENDFILE
09501 ret = nogvl_copy_stream_sendfile(stp);
09502 if (ret != 0)
09503 goto finish;
09504 #endif
09505
09506 nogvl_copy_stream_read_write(stp);
09507
09508 #ifdef USE_SENDFILE
09509 finish:
09510 #endif
09511 return Qnil;
09512 }
09513
09514 static VALUE
09515 copy_stream_fallback_body(VALUE arg)
09516 {
09517 struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
09518 const int buflen = 16*1024;
09519 VALUE n;
09520 VALUE buf = rb_str_buf_new(buflen);
09521 off_t rest = stp->copy_length;
09522 off_t off = stp->src_offset;
09523 ID read_method = id_readpartial;
09524
09525 if (stp->src_fd == -1) {
09526 if (!rb_respond_to(stp->src, read_method)) {
09527 read_method = id_read;
09528 }
09529 }
09530
09531 while (1) {
09532 long numwrote;
09533 long l;
09534 if (stp->copy_length == (off_t)-1) {
09535 l = buflen;
09536 }
09537 else {
09538 if (rest == 0)
09539 break;
09540 l = buflen < rest ? buflen : (long)rest;
09541 }
09542 if (stp->src_fd == -1) {
09543 rb_funcall(stp->src, read_method, 2, INT2FIX(l), buf);
09544 }
09545 else {
09546 ssize_t ss;
09547 rb_thread_wait_fd(stp->src_fd);
09548 rb_str_resize(buf, buflen);
09549 ss = maygvl_copy_stream_read(1, stp, RSTRING_PTR(buf), l, off);
09550 if (ss == -1)
09551 return Qnil;
09552 if (ss == 0)
09553 rb_eof_error();
09554 rb_str_resize(buf, ss);
09555 if (off != (off_t)-1)
09556 off += ss;
09557 }
09558 n = rb_io_write(stp->dst, buf);
09559 numwrote = NUM2LONG(n);
09560 stp->total += numwrote;
09561 rest -= numwrote;
09562 if (read_method == id_read && RSTRING_LEN(buf) == 0) {
09563 break;
09564 }
09565 }
09566
09567 return Qnil;
09568 }
09569
09570 static VALUE
09571 copy_stream_fallback(struct copy_stream_struct *stp)
09572 {
09573 if (stp->src_fd == -1 && stp->src_offset != (off_t)-1) {
09574 rb_raise(rb_eArgError, "cannot specify src_offset for non-IO");
09575 }
09576 rb_rescue2(copy_stream_fallback_body, (VALUE)stp,
09577 (VALUE (*) (ANYARGS))0, (VALUE)0,
09578 rb_eEOFError, (VALUE)0);
09579 return Qnil;
09580 }
09581
09582 static VALUE
09583 copy_stream_body(VALUE arg)
09584 {
09585 struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
09586 VALUE src_io, dst_io;
09587 rb_io_t *src_fptr = 0, *dst_fptr = 0;
09588 int src_fd, dst_fd;
09589
09590 stp->th = rb_thread_current();
09591
09592 stp->total = 0;
09593
09594 if (stp->src == argf ||
09595 !(TYPE(stp->src) == T_FILE ||
09596 TYPE(stp->src) == T_STRING ||
09597 rb_respond_to(stp->src, rb_intern("to_path")))) {
09598 src_fd = -1;
09599 }
09600 else {
09601 src_io = TYPE(stp->src) == T_FILE ? stp->src : Qnil;
09602 if (NIL_P(src_io)) {
09603 VALUE args[2];
09604 int oflags = O_RDONLY;
09605 #ifdef O_NOCTTY
09606 oflags |= O_NOCTTY;
09607 #endif
09608 FilePathValue(stp->src);
09609 args[0] = stp->src;
09610 args[1] = INT2NUM(oflags);
09611 src_io = rb_class_new_instance(2, args, rb_cFile);
09612 stp->src = src_io;
09613 stp->close_src = 1;
09614 }
09615 GetOpenFile(src_io, src_fptr);
09616 rb_io_check_byte_readable(src_fptr);
09617 src_fd = src_fptr->fd;
09618 }
09619 stp->src_fd = src_fd;
09620
09621 if (stp->dst == argf ||
09622 !(TYPE(stp->dst) == T_FILE ||
09623 TYPE(stp->dst) == T_STRING ||
09624 rb_respond_to(stp->dst, rb_intern("to_path")))) {
09625 dst_fd = -1;
09626 }
09627 else {
09628 dst_io = TYPE(stp->dst) == T_FILE ? stp->dst : Qnil;
09629 if (NIL_P(dst_io)) {
09630 VALUE args[3];
09631 int oflags = O_WRONLY|O_CREAT|O_TRUNC;
09632 #ifdef O_NOCTTY
09633 oflags |= O_NOCTTY;
09634 #endif
09635 FilePathValue(stp->dst);
09636 args[0] = stp->dst;
09637 args[1] = INT2NUM(oflags);
09638 args[2] = INT2FIX(0600);
09639 dst_io = rb_class_new_instance(3, args, rb_cFile);
09640 stp->dst = dst_io;
09641 stp->close_dst = 1;
09642 }
09643 else {
09644 dst_io = GetWriteIO(dst_io);
09645 stp->dst = dst_io;
09646 }
09647 GetOpenFile(dst_io, dst_fptr);
09648 rb_io_check_writable(dst_fptr);
09649 dst_fd = dst_fptr->fd;
09650 }
09651 stp->dst_fd = dst_fd;
09652
09653 #ifdef O_BINARY
09654 if (src_fptr)
09655 SET_BINARY_MODE_WITH_SEEK_CUR(src_fptr);
09656 if (dst_fptr)
09657 setmode(dst_fd, O_BINARY);
09658 #endif
09659
09660 if (stp->src_offset == (off_t)-1 && src_fptr && src_fptr->rbuf.len) {
09661 size_t len = src_fptr->rbuf.len;
09662 VALUE str;
09663 if (stp->copy_length != (off_t)-1 && stp->copy_length < (off_t)len) {
09664 len = (size_t)stp->copy_length;
09665 }
09666 str = rb_str_buf_new(len);
09667 rb_str_resize(str,len);
09668 read_buffered_data(RSTRING_PTR(str), len, src_fptr);
09669 if (dst_fptr) {
09670 if (io_binwrite(str, RSTRING_PTR(str), RSTRING_LEN(str), dst_fptr, 0) < 0)
09671 rb_sys_fail(0);
09672 }
09673 else
09674 rb_io_write(stp->dst, str);
09675 stp->total += len;
09676 if (stp->copy_length != (off_t)-1)
09677 stp->copy_length -= len;
09678 }
09679
09680 if (dst_fptr && io_fflush(dst_fptr) < 0) {
09681 rb_raise(rb_eIOError, "flush failed");
09682 }
09683
09684 if (stp->copy_length == 0)
09685 return Qnil;
09686
09687 if (src_fd == -1 || dst_fd == -1) {
09688 return copy_stream_fallback(stp);
09689 }
09690
09691 rb_fd_set(src_fd, &stp->fds);
09692 rb_fd_set(dst_fd, &stp->fds);
09693
09694 return rb_thread_blocking_region(nogvl_copy_stream_func, (void*)stp, RUBY_UBF_IO, 0);
09695 }
09696
09697 static VALUE
09698 copy_stream_finalize(VALUE arg)
09699 {
09700 struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
09701 if (stp->close_src) {
09702 rb_io_close_m(stp->src);
09703 }
09704 if (stp->close_dst) {
09705 rb_io_close_m(stp->dst);
09706 }
09707 rb_fd_term(&stp->fds);
09708 if (stp->syserr) {
09709 errno = stp->error_no;
09710 rb_sys_fail(stp->syserr);
09711 }
09712 if (stp->notimp) {
09713 rb_raise(rb_eNotImpError, "%s() not implemented", stp->notimp);
09714 }
09715 return Qnil;
09716 }
09717
09718
09719
09720
09721
09722
09723
09724
09725
09726
09727
09728
09729
09730
09731
09732
09733
09734
09735
09736
09737
09738
09739
09740
09741
09742
09743
09744
09745
09746 static VALUE
09747 rb_io_s_copy_stream(int argc, VALUE *argv, VALUE io)
09748 {
09749 VALUE src, dst, length, src_offset;
09750 struct copy_stream_struct st;
09751
09752 MEMZERO(&st, struct copy_stream_struct, 1);
09753
09754 rb_scan_args(argc, argv, "22", &src, &dst, &length, &src_offset);
09755
09756 st.src = src;
09757 st.dst = dst;
09758
09759 if (NIL_P(length))
09760 st.copy_length = (off_t)-1;
09761 else
09762 st.copy_length = NUM2OFFT(length);
09763
09764 if (NIL_P(src_offset))
09765 st.src_offset = (off_t)-1;
09766 else
09767 st.src_offset = NUM2OFFT(src_offset);
09768
09769 rb_fd_init(&st.fds);
09770 rb_ensure(copy_stream_body, (VALUE)&st, copy_stream_finalize, (VALUE)&st);
09771
09772 return OFFT2NUM(st.total);
09773 }
09774
09775
09776
09777
09778
09779
09780
09781
09782
09783 static VALUE
09784 rb_io_external_encoding(VALUE io)
09785 {
09786 rb_io_t *fptr;
09787
09788 GetOpenFile(io, fptr);
09789 if (fptr->encs.enc2) {
09790 return rb_enc_from_encoding(fptr->encs.enc2);
09791 }
09792 if (fptr->mode & FMODE_WRITABLE) {
09793 if (fptr->encs.enc)
09794 return rb_enc_from_encoding(fptr->encs.enc);
09795 return Qnil;
09796 }
09797 return rb_enc_from_encoding(io_read_encoding(fptr));
09798 }
09799
09800
09801
09802
09803
09804
09805
09806
09807
09808 static VALUE
09809 rb_io_internal_encoding(VALUE io)
09810 {
09811 rb_io_t *fptr;
09812
09813 GetOpenFile(io, fptr);
09814 if (!fptr->encs.enc2) return Qnil;
09815 return rb_enc_from_encoding(io_read_encoding(fptr));
09816 }
09817
09818
09819
09820
09821
09822
09823
09824
09825
09826
09827
09828
09829
09830
09831
09832
09833
09834
09835
09836
09837 static VALUE
09838 rb_io_set_encoding(int argc, VALUE *argv, VALUE io)
09839 {
09840 rb_io_t *fptr;
09841 VALUE v1, v2, opt;
09842
09843 if (TYPE(io) != T_FILE) {
09844 return rb_funcall2(io, id_set_encoding, argc, argv);
09845 }
09846
09847 argc = rb_scan_args(argc, argv, "11:", &v1, &v2, &opt);
09848 GetOpenFile(io, fptr);
09849 io_encoding_set(fptr, v1, v2, opt);
09850 return io;
09851 }
09852
09853 void
09854 rb_stdio_set_default_encoding(void)
09855 {
09856 extern VALUE rb_stdin, rb_stdout, rb_stderr;
09857 VALUE val = Qnil;
09858
09859 rb_io_set_encoding(1, &val, rb_stdin);
09860 rb_io_set_encoding(1, &val, rb_stdout);
09861 rb_io_set_encoding(1, &val, rb_stderr);
09862 }
09863
09864
09865
09866
09867
09868
09869
09870
09871
09872
09873
09874
09875
09876
09877
09878
09879
09880 static VALUE
09881 argf_external_encoding(VALUE argf)
09882 {
09883 if (!RTEST(ARGF.current_file)) {
09884 return rb_enc_from_encoding(rb_default_external_encoding());
09885 }
09886 return rb_io_external_encoding(rb_io_check_io(ARGF.current_file));
09887 }
09888
09889
09890
09891
09892
09893
09894
09895
09896
09897
09898
09899
09900
09901
09902 static VALUE
09903 argf_internal_encoding(VALUE argf)
09904 {
09905 if (!RTEST(ARGF.current_file)) {
09906 return rb_enc_from_encoding(rb_default_external_encoding());
09907 }
09908 return rb_io_internal_encoding(rb_io_check_io(ARGF.current_file));
09909 }
09910
09911
09912
09913
09914
09915
09916
09917
09918
09919
09920
09921
09922
09923
09924
09925
09926
09927
09928
09929
09930
09931
09932
09933
09934
09935
09936
09937
09938
09939
09940
09941
09942 static VALUE
09943 argf_set_encoding(int argc, VALUE *argv, VALUE argf)
09944 {
09945 rb_io_t *fptr;
09946
09947 if (!next_argv()) {
09948 rb_raise(rb_eArgError, "no stream to set encoding");
09949 }
09950 rb_io_set_encoding(argc, argv, ARGF.current_file);
09951 GetOpenFile(ARGF.current_file, fptr);
09952 ARGF.encs = fptr->encs;
09953 return argf;
09954 }
09955
09956
09957
09958
09959
09960
09961
09962
09963
09964
09965
09966
09967
09968 static VALUE
09969 argf_tell(VALUE argf)
09970 {
09971 if (!next_argv()) {
09972 rb_raise(rb_eArgError, "no stream to tell");
09973 }
09974 ARGF_FORWARD(0, 0);
09975 return rb_io_tell(ARGF.current_file);
09976 }
09977
09978
09979
09980
09981
09982
09983
09984
09985 static VALUE
09986 argf_seek_m(int argc, VALUE *argv, VALUE argf)
09987 {
09988 if (!next_argv()) {
09989 rb_raise(rb_eArgError, "no stream to seek");
09990 }
09991 ARGF_FORWARD(argc, argv);
09992 return rb_io_seek_m(argc, argv, ARGF.current_file);
09993 }
09994
09995
09996
09997
09998
09999
10000
10001
10002
10003
10004
10005
10006 static VALUE
10007 argf_set_pos(VALUE argf, VALUE offset)
10008 {
10009 if (!next_argv()) {
10010 rb_raise(rb_eArgError, "no stream to set position");
10011 }
10012 ARGF_FORWARD(1, &offset);
10013 return rb_io_set_pos(ARGF.current_file, offset);
10014 }
10015
10016
10017
10018
10019
10020
10021
10022
10023
10024
10025
10026
10027
10028 static VALUE
10029 argf_rewind(VALUE argf)
10030 {
10031 if (!next_argv()) {
10032 rb_raise(rb_eArgError, "no stream to rewind");
10033 }
10034 ARGF_FORWARD(0, 0);
10035 return rb_io_rewind(ARGF.current_file);
10036 }
10037
10038
10039
10040
10041
10042
10043
10044
10045
10046
10047
10048 static VALUE
10049 argf_fileno(VALUE argf)
10050 {
10051 if (!next_argv()) {
10052 rb_raise(rb_eArgError, "no stream");
10053 }
10054 ARGF_FORWARD(0, 0);
10055 return rb_io_fileno(ARGF.current_file);
10056 }
10057
10058
10059
10060
10061
10062
10063
10064
10065
10066
10067
10068
10069
10070 static VALUE
10071 argf_to_io(VALUE argf)
10072 {
10073 next_argv();
10074 ARGF_FORWARD(0, 0);
10075 return ARGF.current_file;
10076 }
10077
10078
10079
10080
10081
10082
10083
10084
10085
10086
10087
10088
10089
10090
10091
10092
10093
10094
10095
10096 static VALUE
10097 argf_eof(VALUE argf)
10098 {
10099 next_argv();
10100 if (RTEST(ARGF.current_file)) {
10101 if (ARGF.init_p == 0) return Qtrue;
10102 next_argv();
10103 ARGF_FORWARD(0, 0);
10104 if (rb_io_eof(ARGF.current_file)) {
10105 return Qtrue;
10106 }
10107 }
10108 return Qfalse;
10109 }
10110
10111
10112
10113
10114
10115
10116
10117
10118
10119
10120
10121
10122
10123
10124
10125
10126
10127
10128
10129
10130
10131
10132
10133
10134
10135
10136
10137
10138
10139
10140
10141
10142
10143
10144
10145
10146
10147
10148 static VALUE
10149 argf_read(int argc, VALUE *argv, VALUE argf)
10150 {
10151 VALUE tmp, str, length;
10152 long len = 0;
10153
10154 rb_scan_args(argc, argv, "02", &length, &str);
10155 if (!NIL_P(length)) {
10156 len = NUM2LONG(argv[0]);
10157 }
10158 if (!NIL_P(str)) {
10159 StringValue(str);
10160 rb_str_resize(str,0);
10161 argv[1] = Qnil;
10162 }
10163
10164 retry:
10165 if (!next_argv()) {
10166 return str;
10167 }
10168 if (ARGF_GENERIC_INPUT_P()) {
10169 tmp = argf_forward(argc, argv, argf);
10170 }
10171 else {
10172 tmp = io_read(argc, argv, ARGF.current_file);
10173 }
10174 if (NIL_P(str)) str = tmp;
10175 else if (!NIL_P(tmp)) rb_str_append(str, tmp);
10176 if (NIL_P(tmp) || NIL_P(length)) {
10177 if (ARGF.next_p != -1) {
10178 argf_close(ARGF.current_file);
10179 ARGF.next_p = 1;
10180 goto retry;
10181 }
10182 }
10183 else if (argc >= 1) {
10184 if (RSTRING_LEN(str) < len) {
10185 len -= RSTRING_LEN(str);
10186 argv[0] = INT2NUM(len);
10187 goto retry;
10188 }
10189 }
10190 return str;
10191 }
10192
10193 struct argf_call_arg {
10194 int argc;
10195 VALUE *argv;
10196 VALUE argf;
10197 };
10198
10199 static VALUE
10200 argf_forward_call(VALUE arg)
10201 {
10202 struct argf_call_arg *p = (struct argf_call_arg *)arg;
10203 argf_forward(p->argc, p->argv, p->argf);
10204 return Qnil;
10205 }
10206
10207 static VALUE argf_getpartial(int argc, VALUE *argv, VALUE argf, int nonblock);
10208
10209
10210
10211
10212
10213
10214
10215
10216
10217
10218
10219
10220
10221
10222
10223
10224
10225
10226
10227
10228
10229
10230
10231
10232
10233
10234
10235
10236
10237 static VALUE
10238 argf_readpartial(int argc, VALUE *argv, VALUE argf)
10239 {
10240 return argf_getpartial(argc, argv, argf, 0);
10241 }
10242
10243
10244
10245
10246
10247
10248
10249
10250
10251 static VALUE
10252 argf_read_nonblock(int argc, VALUE *argv, VALUE argf)
10253 {
10254 return argf_getpartial(argc, argv, argf, 1);
10255 }
10256
10257 static VALUE
10258 argf_getpartial(int argc, VALUE *argv, VALUE argf, int nonblock)
10259 {
10260 VALUE tmp, str, length;
10261
10262 rb_scan_args(argc, argv, "11", &length, &str);
10263 if (!NIL_P(str)) {
10264 StringValue(str);
10265 argv[1] = str;
10266 }
10267
10268 if (!next_argv()) {
10269 rb_str_resize(str, 0);
10270 rb_eof_error();
10271 }
10272 if (ARGF_GENERIC_INPUT_P()) {
10273 struct argf_call_arg arg;
10274 arg.argc = argc;
10275 arg.argv = argv;
10276 arg.argf = argf;
10277 tmp = rb_rescue2(argf_forward_call, (VALUE)&arg,
10278 RUBY_METHOD_FUNC(0), Qnil, rb_eEOFError, (VALUE)0);
10279 }
10280 else {
10281 tmp = io_getpartial(argc, argv, ARGF.current_file, nonblock);
10282 }
10283 if (NIL_P(tmp)) {
10284 if (ARGF.next_p == -1) {
10285 rb_eof_error();
10286 }
10287 argf_close(ARGF.current_file);
10288 ARGF.next_p = 1;
10289 if (RARRAY_LEN(ARGF.argv) == 0)
10290 rb_eof_error();
10291 if (NIL_P(str))
10292 str = rb_str_new(NULL, 0);
10293 return str;
10294 }
10295 return tmp;
10296 }
10297
10298
10299
10300
10301
10302
10303
10304
10305
10306
10307
10308
10309
10310
10311
10312
10313
10314
10315
10316
10317
10318
10319
10320
10321 static VALUE
10322 argf_getc(VALUE argf)
10323 {
10324 VALUE ch;
10325
10326 retry:
10327 if (!next_argv()) return Qnil;
10328 if (ARGF_GENERIC_INPUT_P()) {
10329 ch = rb_funcall3(ARGF.current_file, rb_intern("getc"), 0, 0);
10330 }
10331 else {
10332 ch = rb_io_getc(ARGF.current_file);
10333 }
10334 if (NIL_P(ch) && ARGF.next_p != -1) {
10335 argf_close(ARGF.current_file);
10336 ARGF.next_p = 1;
10337 goto retry;
10338 }
10339
10340 return ch;
10341 }
10342
10343
10344
10345
10346
10347
10348
10349
10350
10351
10352
10353
10354
10355
10356
10357
10358
10359
10360
10361 static VALUE
10362 argf_getbyte(VALUE argf)
10363 {
10364 VALUE ch;
10365
10366 retry:
10367 if (!next_argv()) return Qnil;
10368 if (TYPE(ARGF.current_file) != T_FILE) {
10369 ch = rb_funcall3(ARGF.current_file, rb_intern("getbyte"), 0, 0);
10370 }
10371 else {
10372 ch = rb_io_getbyte(ARGF.current_file);
10373 }
10374 if (NIL_P(ch) && ARGF.next_p != -1) {
10375 argf_close(ARGF.current_file);
10376 ARGF.next_p = 1;
10377 goto retry;
10378 }
10379
10380 return ch;
10381 }
10382
10383
10384
10385
10386
10387
10388
10389
10390
10391
10392
10393
10394
10395
10396
10397
10398
10399
10400
10401 static VALUE
10402 argf_readchar(VALUE argf)
10403 {
10404 VALUE ch;
10405
10406 retry:
10407 if (!next_argv()) rb_eof_error();
10408 if (TYPE(ARGF.current_file) != T_FILE) {
10409 ch = rb_funcall3(ARGF.current_file, rb_intern("getc"), 0, 0);
10410 }
10411 else {
10412 ch = rb_io_getc(ARGF.current_file);
10413 }
10414 if (NIL_P(ch) && ARGF.next_p != -1) {
10415 argf_close(ARGF.current_file);
10416 ARGF.next_p = 1;
10417 goto retry;
10418 }
10419
10420 return ch;
10421 }
10422
10423
10424
10425
10426
10427
10428
10429
10430
10431
10432
10433
10434
10435
10436
10437
10438
10439
10440
10441 static VALUE
10442 argf_readbyte(VALUE argf)
10443 {
10444 VALUE c;
10445
10446 NEXT_ARGF_FORWARD(0, 0);
10447 c = argf_getbyte(argf);
10448 if (NIL_P(c)) {
10449 rb_eof_error();
10450 }
10451 return c;
10452 }
10453
10454
10455
10456
10457
10458
10459
10460
10461
10462
10463
10464
10465
10466
10467
10468
10469
10470
10471
10472
10473
10474
10475
10476
10477
10478
10479
10480
10481
10482
10483
10484
10485
10486
10487
10488
10489
10490 static VALUE
10491 argf_each_line(int argc, VALUE *argv, VALUE argf)
10492 {
10493 RETURN_ENUMERATOR(argf, argc, argv);
10494 for (;;) {
10495 if (!next_argv()) return argf;
10496 rb_block_call(ARGF.current_file, rb_intern("each_line"), argc, argv, 0, 0);
10497 ARGF.next_p = 1;
10498 }
10499 }
10500
10501
10502
10503
10504
10505
10506
10507
10508
10509
10510
10511
10512
10513
10514
10515
10516
10517
10518
10519
10520
10521
10522
10523
10524
10525 static VALUE
10526 argf_each_byte(VALUE argf)
10527 {
10528 RETURN_ENUMERATOR(argf, 0, 0);
10529 for (;;) {
10530 if (!next_argv()) return argf;
10531 rb_block_call(ARGF.current_file, rb_intern("each_byte"), 0, 0, 0, 0);
10532 ARGF.next_p = 1;
10533 }
10534 }
10535
10536
10537
10538
10539
10540
10541
10542
10543
10544
10545
10546
10547
10548
10549
10550
10551
10552
10553
10554
10555 static VALUE
10556 argf_each_char(VALUE argf)
10557 {
10558 RETURN_ENUMERATOR(argf, 0, 0);
10559 for (;;) {
10560 if (!next_argv()) return argf;
10561 rb_block_call(ARGF.current_file, rb_intern("each_char"), 0, 0, 0, 0);
10562 ARGF.next_p = 1;
10563 }
10564 }
10565
10566
10567
10568
10569
10570
10571
10572
10573
10574
10575
10576
10577
10578
10579
10580
10581
10582
10583
10584
10585
10586
10587
10588 static VALUE
10589 argf_filename(VALUE argf)
10590 {
10591 next_argv();
10592 return ARGF.filename;
10593 }
10594
10595 static VALUE
10596 argf_filename_getter(ID id, VALUE *var)
10597 {
10598 return argf_filename(*var);
10599 }
10600
10601
10602
10603
10604
10605
10606
10607
10608
10609
10610
10611
10612
10613
10614
10615
10616
10617
10618
10619 static VALUE
10620 argf_file(VALUE argf)
10621 {
10622 next_argv();
10623 return ARGF.current_file;
10624 }
10625
10626
10627
10628
10629
10630
10631
10632
10633
10634
10635
10636
10637 static VALUE
10638 argf_binmode_m(VALUE argf)
10639 {
10640 ARGF.binmode = 1;
10641 next_argv();
10642 ARGF_FORWARD(0, 0);
10643 rb_io_ascii8bit_binmode(ARGF.current_file);
10644 return argf;
10645 }
10646
10647
10648
10649
10650
10651
10652
10653
10654
10655
10656
10657
10658
10659
10660 static VALUE
10661 argf_binmode_p(VALUE argf)
10662 {
10663 return ARGF.binmode ? Qtrue : Qfalse;
10664 }
10665
10666
10667
10668
10669
10670
10671
10672
10673
10674
10675
10676
10677
10678
10679
10680 static VALUE
10681 argf_skip(VALUE argf)
10682 {
10683 if (ARGF.init_p && ARGF.next_p == 0) {
10684 argf_close(ARGF.current_file);
10685 ARGF.next_p = 1;
10686 }
10687 return argf;
10688 }
10689
10690
10691
10692
10693
10694
10695
10696
10697
10698
10699
10700
10701
10702
10703
10704
10705
10706
10707
10708 static VALUE
10709 argf_close_m(VALUE argf)
10710 {
10711 next_argv();
10712 argf_close(ARGF.current_file);
10713 if (ARGF.next_p != -1) {
10714 ARGF.next_p = 1;
10715 }
10716 ARGF.lineno = 0;
10717 return argf;
10718 }
10719
10720
10721
10722
10723
10724
10725
10726
10727 static VALUE
10728 argf_closed(VALUE argf)
10729 {
10730 next_argv();
10731 ARGF_FORWARD(0, 0);
10732 return rb_io_closed(ARGF.current_file);
10733 }
10734
10735
10736
10737
10738
10739
10740
10741 static VALUE
10742 argf_to_s(VALUE argf)
10743 {
10744 return rb_str_new2("ARGF");
10745 }
10746
10747
10748
10749
10750
10751
10752
10753
10754
10755 static VALUE
10756 argf_inplace_mode_get(VALUE argf)
10757 {
10758 if (!ARGF.inplace) return Qnil;
10759 return rb_str_new2(ARGF.inplace);
10760 }
10761
10762 static VALUE
10763 opt_i_get(ID id, VALUE *var)
10764 {
10765 return argf_inplace_mode_get(*var);
10766 }
10767
10768
10769
10770
10771
10772
10773
10774
10775
10776
10777
10778
10779
10780
10781
10782
10783
10784
10785
10786
10787
10788 static VALUE
10789 argf_inplace_mode_set(VALUE argf, VALUE val)
10790 {
10791 if (rb_safe_level() >= 1 && OBJ_TAINTED(val))
10792 rb_insecure_operation();
10793
10794 if (!RTEST(val)) {
10795 if (ARGF.inplace) free(ARGF.inplace);
10796 ARGF.inplace = 0;
10797 }
10798 else {
10799 StringValue(val);
10800 if (ARGF.inplace) free(ARGF.inplace);
10801 ARGF.inplace = 0;
10802 ARGF.inplace = strdup(RSTRING_PTR(val));
10803 }
10804 return argf;
10805 }
10806
10807 static void
10808 opt_i_set(VALUE val, ID id, VALUE *var)
10809 {
10810 argf_inplace_mode_set(*var, val);
10811 }
10812
10813 const char *
10814 ruby_get_inplace_mode(void)
10815 {
10816 return ARGF.inplace;
10817 }
10818
10819 void
10820 ruby_set_inplace_mode(const char *suffix)
10821 {
10822 if (ARGF.inplace) free(ARGF.inplace);
10823 ARGF.inplace = 0;
10824 if (suffix) ARGF.inplace = strdup(suffix);
10825 }
10826
10827
10828
10829
10830
10831
10832
10833
10834
10835
10836
10837
10838
10839
10840
10841 static VALUE
10842 argf_argv(VALUE argf)
10843 {
10844 return ARGF.argv;
10845 }
10846
10847 static VALUE
10848 argf_argv_getter(ID id, VALUE *var)
10849 {
10850 return argf_argv(*var);
10851 }
10852
10853 VALUE
10854 rb_get_argv(void)
10855 {
10856 return ARGF.argv;
10857 }
10858
10859
10860
10861
10862
10863
10864
10865
10866 static VALUE
10867 argf_write_io(VALUE argf)
10868 {
10869 if (!RTEST(ARGF.current_file)) {
10870 rb_raise(rb_eIOError, "not opened for writing");
10871 }
10872 return GetWriteIO(ARGF.current_file);
10873 }
10874
10875
10876
10877
10878
10879
10880
10881 static VALUE
10882 argf_write(VALUE argf, VALUE str)
10883 {
10884 return rb_io_write(argf_write_io(argf), str);
10885 }
10886
10887
10888
10889
10890
10891
10892
10893
10894
10895
10896
10897
10898
10899
10900
10901
10902
10903
10904
10905
10906
10907
10908
10909
10910
10911
10912
10913
10914
10915
10916
10917
10918
10919
10920
10921
10922
10923
10924
10925
10926
10927
10928
10929
10930
10931
10932
10933
10934
10935
10936
10937
10938
10939
10940
10941
10942
10943
10944
10945
10946
10947
10948
10949
10950
10951
10952
10953
10954
10955
10956
10957
10958
10959
10960
10961
10962
10963
10964
10965
10966
10967
10968
10969
10970
10971
10972
10973
10974
10975
10976
10977
10978
10979
10980
10981
10982
10983
10984
10985
10986
10987
10988
10989
10990
10991
10992
10993
10994
10995
10996
10997
10998
10999
11000
11001
11002
11003
11004
11005
11006
11007
11008
11009
11010
11011
11012
11013
11014
11015
11016
11017
11018
11019
11020
11021
11022
11023
11024
11025
11026
11027
11028
11029
11030
11031
11032
11033
11034
11035
11036
11037
11038
11039
11040
11041
11042
11043
11044
11045
11046
11047
11048
11049
11050
11051
11052
11053
11054
11055
11056
11057
11058
11059
11060
11061
11062
11063
11064
11065
11066
11067
11068
11069
11070
11071
11072
11073
11074 void
11075 Init_IO(void)
11076 {
11077 #undef rb_intern
11078 #define rb_intern(str) rb_intern_const(str)
11079
11080 VALUE rb_cARGF;
11081 #ifdef __CYGWIN__
11082 #include <sys/cygwin.h>
11083 static struct __cygwin_perfile pf[] =
11084 {
11085 {"", O_RDONLY | O_BINARY},
11086 {"", O_WRONLY | O_BINARY},
11087 {"", O_RDWR | O_BINARY},
11088 {"", O_APPEND | O_BINARY},
11089 {NULL, 0}
11090 };
11091 cygwin_internal(CW_PERFILE, pf);
11092 #endif
11093
11094 rb_eIOError = rb_define_class("IOError", rb_eStandardError);
11095 rb_eEOFError = rb_define_class("EOFError", rb_eIOError);
11096
11097 id_write = rb_intern("write");
11098 id_read = rb_intern("read");
11099 id_getc = rb_intern("getc");
11100 id_flush = rb_intern("flush");
11101 id_readpartial = rb_intern("readpartial");
11102 id_set_encoding = rb_intern("set_encoding");
11103
11104 rb_define_global_function("syscall", rb_f_syscall, -1);
11105
11106 rb_define_global_function("open", rb_f_open, -1);
11107 rb_define_global_function("printf", rb_f_printf, -1);
11108 rb_define_global_function("print", rb_f_print, -1);
11109 rb_define_global_function("putc", rb_f_putc, 1);
11110 rb_define_global_function("puts", rb_f_puts, -1);
11111 rb_define_global_function("gets", rb_f_gets, -1);
11112 rb_define_global_function("readline", rb_f_readline, -1);
11113 rb_define_global_function("select", rb_f_select, -1);
11114
11115 rb_define_global_function("readlines", rb_f_readlines, -1);
11116
11117 rb_define_global_function("`", rb_f_backquote, 1);
11118
11119 rb_define_global_function("p", rb_f_p, -1);
11120 rb_define_method(rb_mKernel, "display", rb_obj_display, -1);
11121
11122 rb_cIO = rb_define_class("IO", rb_cObject);
11123 rb_include_module(rb_cIO, rb_mEnumerable);
11124
11125 rb_mWaitReadable = rb_define_module_under(rb_cIO, "WaitReadable");
11126 rb_mWaitWritable = rb_define_module_under(rb_cIO, "WaitWritable");
11127
11128 #if 0
11129
11130 rb_define_singleton_method(rb_cFile, "open", rb_io_s_open, -1);
11131 #endif
11132
11133 rb_define_alloc_func(rb_cIO, io_alloc);
11134 rb_define_singleton_method(rb_cIO, "new", rb_io_s_new, -1);
11135 rb_define_singleton_method(rb_cIO, "open", rb_io_s_open, -1);
11136 rb_define_singleton_method(rb_cIO, "sysopen", rb_io_s_sysopen, -1);
11137 rb_define_singleton_method(rb_cIO, "for_fd", rb_io_s_for_fd, -1);
11138 rb_define_singleton_method(rb_cIO, "popen", rb_io_s_popen, -1);
11139 rb_define_singleton_method(rb_cIO, "foreach", rb_io_s_foreach, -1);
11140 rb_define_singleton_method(rb_cIO, "readlines", rb_io_s_readlines, -1);
11141 rb_define_singleton_method(rb_cIO, "read", rb_io_s_read, -1);
11142 rb_define_singleton_method(rb_cIO, "binread", rb_io_s_binread, -1);
11143 rb_define_singleton_method(rb_cIO, "write", rb_io_s_write, -1);
11144 rb_define_singleton_method(rb_cIO, "binwrite", rb_io_s_binwrite, -1);
11145 rb_define_singleton_method(rb_cIO, "select", rb_f_select, -1);
11146 rb_define_singleton_method(rb_cIO, "pipe", rb_io_s_pipe, -1);
11147 rb_define_singleton_method(rb_cIO, "try_convert", rb_io_s_try_convert, 1);
11148 rb_define_singleton_method(rb_cIO, "copy_stream", rb_io_s_copy_stream, -1);
11149
11150 rb_define_method(rb_cIO, "initialize", rb_io_initialize, -1);
11151
11152 rb_output_fs = Qnil;
11153 rb_define_hooked_variable("$,", &rb_output_fs, 0, rb_str_setter);
11154
11155 rb_rs = rb_default_rs = rb_usascii_str_new2("\n");
11156 rb_gc_register_mark_object(rb_default_rs);
11157 rb_output_rs = Qnil;
11158 OBJ_FREEZE(rb_default_rs);
11159 rb_define_hooked_variable("$/", &rb_rs, 0, rb_str_setter);
11160 rb_define_hooked_variable("$-0", &rb_rs, 0, rb_str_setter);
11161 rb_define_hooked_variable("$\\", &rb_output_rs, 0, rb_str_setter);
11162
11163 rb_define_virtual_variable("$_", rb_lastline_get, rb_lastline_set);
11164
11165 rb_define_method(rb_cIO, "initialize_copy", rb_io_init_copy, 1);
11166 rb_define_method(rb_cIO, "reopen", rb_io_reopen, -1);
11167
11168 rb_define_method(rb_cIO, "print", rb_io_print, -1);
11169 rb_define_method(rb_cIO, "putc", rb_io_putc, 1);
11170 rb_define_method(rb_cIO, "puts", rb_io_puts, -1);
11171 rb_define_method(rb_cIO, "printf", rb_io_printf, -1);
11172
11173 rb_define_method(rb_cIO, "each", rb_io_each_line, -1);
11174 rb_define_method(rb_cIO, "each_line", rb_io_each_line, -1);
11175 rb_define_method(rb_cIO, "each_byte", rb_io_each_byte, 0);
11176 rb_define_method(rb_cIO, "each_char", rb_io_each_char, 0);
11177 rb_define_method(rb_cIO, "each_codepoint", rb_io_each_codepoint, 0);
11178 rb_define_method(rb_cIO, "lines", rb_io_each_line, -1);
11179 rb_define_method(rb_cIO, "bytes", rb_io_each_byte, 0);
11180 rb_define_method(rb_cIO, "chars", rb_io_each_char, 0);
11181 rb_define_method(rb_cIO, "codepoints", rb_io_each_codepoint, 0);
11182
11183 rb_define_method(rb_cIO, "syswrite", rb_io_syswrite, 1);
11184 rb_define_method(rb_cIO, "sysread", rb_io_sysread, -1);
11185
11186 rb_define_method(rb_cIO, "fileno", rb_io_fileno, 0);
11187 rb_define_alias(rb_cIO, "to_i", "fileno");
11188 rb_define_method(rb_cIO, "to_io", rb_io_to_io, 0);
11189
11190 rb_define_method(rb_cIO, "fsync", rb_io_fsync, 0);
11191 rb_define_method(rb_cIO, "fdatasync", rb_io_fdatasync, 0);
11192 rb_define_method(rb_cIO, "sync", rb_io_sync, 0);
11193 rb_define_method(rb_cIO, "sync=", rb_io_set_sync, 1);
11194
11195 rb_define_method(rb_cIO, "lineno", rb_io_lineno, 0);
11196 rb_define_method(rb_cIO, "lineno=", rb_io_set_lineno, 1);
11197
11198 rb_define_method(rb_cIO, "readlines", rb_io_readlines, -1);
11199
11200 rb_define_method(rb_cIO, "read_nonblock", io_read_nonblock, -1);
11201 rb_define_method(rb_cIO, "write_nonblock", rb_io_write_nonblock, 1);
11202 rb_define_method(rb_cIO, "readpartial", io_readpartial, -1);
11203 rb_define_method(rb_cIO, "read", io_read, -1);
11204 rb_define_method(rb_cIO, "write", io_write_m, 1);
11205 rb_define_method(rb_cIO, "gets", rb_io_gets_m, -1);
11206 rb_define_method(rb_cIO, "readline", rb_io_readline, -1);
11207 rb_define_method(rb_cIO, "getc", rb_io_getc, 0);
11208 rb_define_method(rb_cIO, "getbyte", rb_io_getbyte, 0);
11209 rb_define_method(rb_cIO, "readchar", rb_io_readchar, 0);
11210 rb_define_method(rb_cIO, "readbyte", rb_io_readbyte, 0);
11211 rb_define_method(rb_cIO, "ungetbyte",rb_io_ungetbyte, 1);
11212 rb_define_method(rb_cIO, "ungetc",rb_io_ungetc, 1);
11213 rb_define_method(rb_cIO, "<<", rb_io_addstr, 1);
11214 rb_define_method(rb_cIO, "flush", rb_io_flush, 0);
11215 rb_define_method(rb_cIO, "tell", rb_io_tell, 0);
11216 rb_define_method(rb_cIO, "seek", rb_io_seek_m, -1);
11217 rb_define_const(rb_cIO, "SEEK_SET", INT2FIX(SEEK_SET));
11218 rb_define_const(rb_cIO, "SEEK_CUR", INT2FIX(SEEK_CUR));
11219 rb_define_const(rb_cIO, "SEEK_END", INT2FIX(SEEK_END));
11220 rb_define_method(rb_cIO, "rewind", rb_io_rewind, 0);
11221 rb_define_method(rb_cIO, "pos", rb_io_tell, 0);
11222 rb_define_method(rb_cIO, "pos=", rb_io_set_pos, 1);
11223 rb_define_method(rb_cIO, "eof", rb_io_eof, 0);
11224 rb_define_method(rb_cIO, "eof?", rb_io_eof, 0);
11225
11226 rb_define_method(rb_cIO, "close_on_exec?", rb_io_close_on_exec_p, 0);
11227 rb_define_method(rb_cIO, "close_on_exec=", rb_io_set_close_on_exec, 1);
11228
11229 rb_define_method(rb_cIO, "close", rb_io_close_m, 0);
11230 rb_define_method(rb_cIO, "closed?", rb_io_closed, 0);
11231 rb_define_method(rb_cIO, "close_read", rb_io_close_read, 0);
11232 rb_define_method(rb_cIO, "close_write", rb_io_close_write, 0);
11233
11234 rb_define_method(rb_cIO, "isatty", rb_io_isatty, 0);
11235 rb_define_method(rb_cIO, "tty?", rb_io_isatty, 0);
11236 rb_define_method(rb_cIO, "binmode", rb_io_binmode_m, 0);
11237 rb_define_method(rb_cIO, "binmode?", rb_io_binmode_p, 0);
11238 rb_define_method(rb_cIO, "sysseek", rb_io_sysseek, -1);
11239 rb_define_method(rb_cIO, "advise", rb_io_advise, -1);
11240
11241 rb_define_method(rb_cIO, "ioctl", rb_io_ioctl, -1);
11242 rb_define_method(rb_cIO, "fcntl", rb_io_fcntl, -1);
11243 rb_define_method(rb_cIO, "pid", rb_io_pid, 0);
11244 rb_define_method(rb_cIO, "inspect", rb_io_inspect, 0);
11245
11246 rb_define_method(rb_cIO, "external_encoding", rb_io_external_encoding, 0);
11247 rb_define_method(rb_cIO, "internal_encoding", rb_io_internal_encoding, 0);
11248 rb_define_method(rb_cIO, "set_encoding", rb_io_set_encoding, -1);
11249
11250 rb_define_method(rb_cIO, "autoclose?", rb_io_autoclose_p, 0);
11251 rb_define_method(rb_cIO, "autoclose=", rb_io_set_autoclose, 1);
11252
11253 rb_define_variable("$stdin", &rb_stdin);
11254 rb_stdin = prep_stdio(stdin, FMODE_READABLE, rb_cIO, "<STDIN>");
11255 rb_define_hooked_variable("$stdout", &rb_stdout, 0, stdout_setter);
11256 rb_stdout = prep_stdio(stdout, FMODE_WRITABLE, rb_cIO, "<STDOUT>");
11257 rb_define_hooked_variable("$stderr", &rb_stderr, 0, stdout_setter);
11258 rb_stderr = prep_stdio(stderr, FMODE_WRITABLE|FMODE_SYNC, rb_cIO, "<STDERR>");
11259 rb_define_hooked_variable("$>", &rb_stdout, 0, stdout_setter);
11260 orig_stdout = rb_stdout;
11261 rb_deferr = orig_stderr = rb_stderr;
11262
11263
11264 rb_define_global_const("STDIN", rb_stdin);
11265
11266 rb_define_global_const("STDOUT", rb_stdout);
11267
11268 rb_define_global_const("STDERR", rb_stderr);
11269
11270 #if 0
11271
11272 rb_cARGF = rb_define_class("ARGF", rb_cObject);
11273 #endif
11274
11275 rb_cARGF = rb_class_new(rb_cObject);
11276 rb_set_class_path(rb_cARGF, rb_cObject, "ARGF.class");
11277 rb_define_alloc_func(rb_cARGF, argf_alloc);
11278
11279 rb_include_module(rb_cARGF, rb_mEnumerable);
11280
11281 rb_define_method(rb_cARGF, "initialize", argf_initialize, -2);
11282 rb_define_method(rb_cARGF, "initialize_copy", argf_initialize_copy, 1);
11283 rb_define_method(rb_cARGF, "to_s", argf_to_s, 0);
11284 rb_define_method(rb_cARGF, "argv", argf_argv, 0);
11285
11286 rb_define_method(rb_cARGF, "fileno", argf_fileno, 0);
11287 rb_define_method(rb_cARGF, "to_i", argf_fileno, 0);
11288 rb_define_method(rb_cARGF, "to_io", argf_to_io, 0);
11289 rb_define_method(rb_cARGF, "to_write_io", argf_write_io, 0);
11290 rb_define_method(rb_cARGF, "each", argf_each_line, -1);
11291 rb_define_method(rb_cARGF, "each_line", argf_each_line, -1);
11292 rb_define_method(rb_cARGF, "each_byte", argf_each_byte, 0);
11293 rb_define_method(rb_cARGF, "each_char", argf_each_char, 0);
11294 rb_define_method(rb_cARGF, "lines", argf_each_line, -1);
11295 rb_define_method(rb_cARGF, "bytes", argf_each_byte, 0);
11296 rb_define_method(rb_cARGF, "chars", argf_each_char, 0);
11297
11298 rb_define_method(rb_cARGF, "read", argf_read, -1);
11299 rb_define_method(rb_cARGF, "readpartial", argf_readpartial, -1);
11300 rb_define_method(rb_cARGF, "read_nonblock", argf_read_nonblock, -1);
11301 rb_define_method(rb_cARGF, "readlines", argf_readlines, -1);
11302 rb_define_method(rb_cARGF, "to_a", argf_readlines, -1);
11303 rb_define_method(rb_cARGF, "gets", argf_gets, -1);
11304 rb_define_method(rb_cARGF, "readline", argf_readline, -1);
11305 rb_define_method(rb_cARGF, "getc", argf_getc, 0);
11306 rb_define_method(rb_cARGF, "getbyte", argf_getbyte, 0);
11307 rb_define_method(rb_cARGF, "readchar", argf_readchar, 0);
11308 rb_define_method(rb_cARGF, "readbyte", argf_readbyte, 0);
11309 rb_define_method(rb_cARGF, "tell", argf_tell, 0);
11310 rb_define_method(rb_cARGF, "seek", argf_seek_m, -1);
11311 rb_define_method(rb_cARGF, "rewind", argf_rewind, 0);
11312 rb_define_method(rb_cARGF, "pos", argf_tell, 0);
11313 rb_define_method(rb_cARGF, "pos=", argf_set_pos, 1);
11314 rb_define_method(rb_cARGF, "eof", argf_eof, 0);
11315 rb_define_method(rb_cARGF, "eof?", argf_eof, 0);
11316 rb_define_method(rb_cARGF, "binmode", argf_binmode_m, 0);
11317 rb_define_method(rb_cARGF, "binmode?", argf_binmode_p, 0);
11318
11319 rb_define_method(rb_cARGF, "write", argf_write, 1);
11320 rb_define_method(rb_cARGF, "print", rb_io_print, -1);
11321 rb_define_method(rb_cARGF, "putc", rb_io_putc, 1);
11322 rb_define_method(rb_cARGF, "puts", rb_io_puts, -1);
11323 rb_define_method(rb_cARGF, "printf", rb_io_printf, -1);
11324
11325 rb_define_method(rb_cARGF, "filename", argf_filename, 0);
11326 rb_define_method(rb_cARGF, "path", argf_filename, 0);
11327 rb_define_method(rb_cARGF, "file", argf_file, 0);
11328 rb_define_method(rb_cARGF, "skip", argf_skip, 0);
11329 rb_define_method(rb_cARGF, "close", argf_close_m, 0);
11330 rb_define_method(rb_cARGF, "closed?", argf_closed, 0);
11331
11332 rb_define_method(rb_cARGF, "lineno", argf_lineno, 0);
11333 rb_define_method(rb_cARGF, "lineno=", argf_set_lineno, 1);
11334
11335 rb_define_method(rb_cARGF, "inplace_mode", argf_inplace_mode_get, 0);
11336 rb_define_method(rb_cARGF, "inplace_mode=", argf_inplace_mode_set, 1);
11337
11338 rb_define_method(rb_cARGF, "external_encoding", argf_external_encoding, 0);
11339 rb_define_method(rb_cARGF, "internal_encoding", argf_internal_encoding, 0);
11340 rb_define_method(rb_cARGF, "set_encoding", argf_set_encoding, -1);
11341
11342 argf = rb_class_new_instance(0, 0, rb_cARGF);
11343
11344 rb_define_readonly_variable("$<", &argf);
11345
11346
11347
11348
11349
11350
11351 rb_define_global_const("ARGF", argf);
11352
11353 rb_define_hooked_variable("$.", &argf, argf_lineno_getter, argf_lineno_setter);
11354 rb_define_hooked_variable("$FILENAME", &argf, argf_filename_getter, rb_gvar_readonly_setter);
11355 ARGF.filename = rb_str_new2("-");
11356
11357 rb_define_hooked_variable("$-i", &argf, opt_i_get, opt_i_set);
11358 rb_define_hooked_variable("$*", &argf, argf_argv_getter, rb_gvar_readonly_setter);
11359
11360 #if defined (_WIN32) || defined(__CYGWIN__)
11361 atexit(pipe_atexit);
11362 #endif
11363
11364 Init_File();
11365
11366 rb_define_method(rb_cFile, "initialize", rb_file_initialize, -1);
11367
11368
11369 rb_file_const("RDONLY", INT2FIX(O_RDONLY));
11370
11371 rb_file_const("WRONLY", INT2FIX(O_WRONLY));
11372
11373 rb_file_const("RDWR", INT2FIX(O_RDWR));
11374
11375 rb_file_const("APPEND", INT2FIX(O_APPEND));
11376
11377 rb_file_const("CREAT", INT2FIX(O_CREAT));
11378
11379 rb_file_const("EXCL", INT2FIX(O_EXCL));
11380 #if defined(O_NDELAY) || defined(O_NONBLOCK)
11381 # ifndef O_NONBLOCK
11382 # define O_NONBLOCK O_NDELAY
11383 # endif
11384
11385 rb_file_const("NONBLOCK", INT2FIX(O_NONBLOCK));
11386 #endif
11387
11388 rb_file_const("TRUNC", INT2FIX(O_TRUNC));
11389 #ifdef O_NOCTTY
11390
11391 rb_file_const("NOCTTY", INT2FIX(O_NOCTTY));
11392 #endif
11393 #ifndef O_BINARY
11394 # define O_BINARY 0
11395 #endif
11396
11397 rb_file_const("BINARY", INT2FIX(O_BINARY));
11398 #ifdef O_SYNC
11399 rb_file_const("SYNC", INT2FIX(O_SYNC));
11400 #endif
11401 #ifdef O_DSYNC
11402 rb_file_const("DSYNC", INT2FIX(O_DSYNC));
11403 #endif
11404 #ifdef O_RSYNC
11405 rb_file_const("RSYNC", INT2FIX(O_RSYNC));
11406 #endif
11407 #ifdef O_NOFOLLOW
11408
11409 rb_file_const("NOFOLLOW", INT2FIX(O_NOFOLLOW));
11410 #endif
11411 #ifdef O_NOATIME
11412
11413 rb_file_const("NOATIME", INT2FIX(O_NOATIME));
11414 #endif
11415 #ifdef O_DIRECT
11416
11417 rb_file_const("DIRECT", INT2FIX(O_DIRECT));
11418 #endif
11419
11420 sym_mode = ID2SYM(rb_intern("mode"));
11421 sym_perm = ID2SYM(rb_intern("perm"));
11422 sym_extenc = ID2SYM(rb_intern("external_encoding"));
11423 sym_intenc = ID2SYM(rb_intern("internal_encoding"));
11424 sym_encoding = ID2SYM(rb_intern("encoding"));
11425 sym_open_args = ID2SYM(rb_intern("open_args"));
11426 sym_textmode = ID2SYM(rb_intern("textmode"));
11427 sym_binmode = ID2SYM(rb_intern("binmode"));
11428 sym_autoclose = ID2SYM(rb_intern("autoclose"));
11429 sym_normal = ID2SYM(rb_intern("normal"));
11430 sym_sequential = ID2SYM(rb_intern("sequential"));
11431 sym_random = ID2SYM(rb_intern("random"));
11432 sym_willneed = ID2SYM(rb_intern("willneed"));
11433 sym_dontneed = ID2SYM(rb_intern("dontneed"));
11434 sym_noreuse = ID2SYM(rb_intern("noreuse"));
11435 }
11436