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