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