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