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