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