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