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