|
Ruby
1.9.3p286(2012-10-12revision37165)
|
00001 /********************************************************************** 00002 00003 io.c - 00004 00005 $Author: usa $ 00006 created at: Fri Oct 15 18:08:59 JST 1993 00007 00008 Copyright (C) 1993-2007 Yukihiro Matsumoto 00009 Copyright (C) 2000 Network Applied Communication Laboratory, Inc. 00010 Copyright (C) 2000 Information-technology Promotion Agency, Japan 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 /* EMX has sys/param.h, but.. */ 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 /* is this ok? */ 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 /* define system APIs */ 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; /* rescue VIM plugin */ 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 /* MinGW don't have F_GETFD and FD_CLOEXEC. [ruby-core:40281] */ 00168 #ifdef F_GETFD 00169 int flags, flags2, ret; 00170 flags = fcntl(fd, F_GETFD); /* should not fail except EBADF. */ 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; /* Clear CLOEXEC for standard file descriptors: 0, 1, 2. */ 00176 else 00177 flags2 = flags | FD_CLOEXEC; /* Set CLOEXEC for non-standard file descriptors: 3, 4, 5, ... */ 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 /* F_DUPFD_CLOEXEC is available since Linux 2.6.24. Linux 2.6.18 fails with EINVAL */ 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 /* GNU libc */ 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 /* Windows */ 00290 # define DEFAULT_TEXTMODE FMODE_TEXTMODE 00291 # define TEXTMODE_NEWLINE_DECORATOR_ON_WRITE ECONV_CRLF_NEWLINE_DECORATOR 00292 /* 00293 * CRLF newline is set as default newline decorator. 00294 * If only CRLF newline conversion is needed, we use binary IO process 00295 * with OS's text mode for IO performance improvement. 00296 * If encoding conversion is needed or a user sets text mode, we use encoding 00297 * conversion IO process and universal newline decorator by default. 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 * IO unread with taking care of removed '\r' in text mode. 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 /* add extra offset for removed '\r' in rbuf */ 00362 extra_max = (long)(pos - fptr->rbuf.len); 00363 p = fptr->rbuf.ptr + fptr->rbuf.off; 00364 00365 /* if the end of rbuf is '\r', rbuf doesn't have '\r' within rbuf.len */ 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 * We use io_seek to back cursor position when changing mode from text to binary, 00405 * but stdin and pipe cannot seek back. Stdin and pipe read should use encoding 00406 * conversion for working properly with mode change. 00407 * 00408 * Return previous translation mode. 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 /* Unix */ 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 * call-seq: 00528 * IO.try_convert(obj) -> io or nil 00529 * 00530 * Try to convert <i>obj</i> into an IO, using to_io method. 00531 * Returns converted IO or nil if <i>obj</i> cannot be converted 00532 * for any reason. 00533 * 00534 * IO.try_convert(STDOUT) #=> STDOUT 00535 * IO.try_convert("STDOUT") #=> nil 00536 * 00537 * require 'zlib' 00538 * f = open("/tmp/zz.gz") #=> #<File:/tmp/zz.gz> 00539 * z = Zlib::GzipReader.open(f) #=> #<Zlib::GzipReader:0x81d8744> 00540 * IO.try_convert(z) #=> #<File:/tmp/zz.gz> 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 /* xxx: target position may be negative if buffer is filled by ungetc */ 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 /* This function is used for bytes and chars. Confusing. */ 00695 if (READ_CHAR_PENDING(fptr)) 00696 return 1; /* should raise? */ 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 /* no encoding conversion */ 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 /* single conversion */ 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 /* double conversion */ 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 /* writing functions */ 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 /* xxx: use writev to avoid double write if available */ 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 /* avoid context switch between "a" and "\n" in STDERR.puts "a". 01049 [ruby-dev:25080] */ 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 /* xxx: other threads may modify given string. */ 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 /* port is not IO, call write method for it. */ 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 * call-seq: 01200 * ios.write(string) -> integer 01201 * 01202 * Writes the given string to <em>ios</em>. The stream must be opened 01203 * for writing. If the argument is not a string, it will be converted 01204 * to a string using <code>to_s</code>. Returns the number of bytes 01205 * written. 01206 * 01207 * count = $stdout.write("This is a test\n") 01208 * puts "That was #{count} bytes of data" 01209 * 01210 * <em>produces:</em> 01211 * 01212 * This is a test 01213 * That was 15 bytes of data 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 * call-seq: 01230 * ios << obj -> ios 01231 * 01232 * String Output---Writes <i>obj</i> to <em>ios</em>. 01233 * <i>obj</i> will be converted to a string using 01234 * <code>to_s</code>. 01235 * 01236 * $stdout << "Hello " << "world!\n" 01237 * 01238 * <em>produces:</em> 01239 * 01240 * Hello world! 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 * call-seq: 01253 * ios.flush -> ios 01254 * 01255 * Flushes any buffered data within <em>ios</em> to the underlying 01256 * operating system (note that this is Ruby internal buffering only; 01257 * the OS may buffer the data as well). 01258 * 01259 * $stdout.print "no newline" 01260 * $stdout.flush 01261 * 01262 * <em>produces:</em> 01263 * 01264 * no newline 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 * call-seq: 01297 * ios.pos -> integer 01298 * ios.tell -> integer 01299 * 01300 * Returns the current offset (in bytes) of <em>ios</em>. 01301 * 01302 * f = File.new("testfile") 01303 * f.pos #=> 0 01304 * f.gets #=> "This is line one\n" 01305 * f.pos #=> 17 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 * call-seq: 01337 * ios.seek(amount, whence=IO::SEEK_SET) -> 0 01338 * 01339 * Seeks to a given offset <i>anInteger</i> in the stream according to 01340 * the value of <i>whence</i>: 01341 * 01342 * IO::SEEK_CUR | Seeks to _amount_ plus current position 01343 * --------------+---------------------------------------------------- 01344 * IO::SEEK_END | Seeks to _amount_ plus end of stream (you probably 01345 * | want a negative value for _amount_) 01346 * --------------+---------------------------------------------------- 01347 * IO::SEEK_SET | Seeks to the absolute location given by _amount_ 01348 * 01349 * Example: 01350 * 01351 * f = File.new("testfile") 01352 * f.seek(-13, IO::SEEK_END) #=> 0 01353 * f.readline #=> "And so on...\n" 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 * call-seq: 01371 * ios.pos = integer -> integer 01372 * 01373 * Seeks to the given position (in bytes) in <em>ios</em>. 01374 * 01375 * f = File.new("testfile") 01376 * f.pos = 17 01377 * f.gets #=> "This is line two\n" 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 * call-seq: 01398 * ios.rewind -> 0 01399 * 01400 * Positions <em>ios</em> to the beginning of input, resetting 01401 * <code>lineno</code> to zero. 01402 * 01403 * f = File.new("testfile") 01404 * f.readline #=> "This is line one\n" 01405 * f.rewind #=> 0 01406 * f.lineno #=> 0 01407 * f.readline #=> "This is line one\n" 01408 * 01409 * Note that it cannot be used with streams such as pipes, ttys, and sockets. 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; /* r should be <= rbuf_capa */ 01461 if (r == 0) 01462 return -1; /* EOF */ 01463 } 01464 return 0; 01465 } 01466 01467 /* 01468 * call-seq: 01469 * ios.eof -> true or false 01470 * ios.eof? -> true or false 01471 * 01472 * Returns true if <em>ios</em> is at end of file that means 01473 * there are no more data to read. 01474 * The stream must be opened for reading or an <code>IOError</code> will be 01475 * raised. 01476 * 01477 * f = File.new("testfile") 01478 * dummy = f.readlines 01479 * f.eof #=> true 01480 * 01481 * If <em>ios</em> is a stream such as pipe or socket, <code>IO#eof?</code> 01482 * blocks until the other end sends some data or closes it. 01483 * 01484 * r, w = IO.pipe 01485 * Thread.new { sleep 1; w.close } 01486 * r.eof? #=> true after 1 second blocking 01487 * 01488 * r, w = IO.pipe 01489 * Thread.new { sleep 1; w.puts "a" } 01490 * r.eof? #=> false after 1 second blocking 01491 * 01492 * r, w = IO.pipe 01493 * r.eof? # blocks forever 01494 * 01495 * Note that <code>IO#eof?</code> reads data to the input byte buffer. 01496 * So <code>IO#sysread</code> may not behave as you intend with 01497 * <code>IO#eof?</code>, unless you call <code>IO#rewind</code> 01498 * first (which is not available for some streams). 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 * call-seq: 01525 * ios.sync -> true or false 01526 * 01527 * Returns the current ``sync mode'' of <em>ios</em>. When sync mode is 01528 * true, all output is immediately flushed to the underlying operating 01529 * system and is not buffered by Ruby internally. See also 01530 * <code>IO#fsync</code>. 01531 * 01532 * f = File.new("testfile") 01533 * f.sync #=> false 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 * call-seq: 01548 * ios.sync = boolean -> boolean 01549 * 01550 * Sets the ``sync mode'' to <code>true</code> or <code>false</code>. 01551 * When sync mode is true, all output is immediately flushed to the 01552 * underlying operating system and is not buffered internally. Returns 01553 * the new state. See also <code>IO#fsync</code>. 01554 * 01555 * f = File.new("testfile") 01556 * f.sync = true 01557 * 01558 * <em>(produces no output)</em> 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 * call-seq: 01587 * ios.fsync -> 0 or nil 01588 * 01589 * Immediately writes all buffered data in <em>ios</em> to disk. 01590 * Note that <code>fsync</code> differs from 01591 * using <code>IO#sync=</code>. The latter ensures that data is flushed 01592 * from Ruby's buffers, but doesn't not guarantee that the underlying 01593 * operating system actually writes it to disk. 01594 * 01595 * <code>NotImplementedError</code> is raised 01596 * if the underlying operating system does not support <em>fsync(2)</em>. 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 /* already called in io_fflush() */ 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 * call-seq: 01629 * ios.fdatasync -> 0 or nil 01630 * 01631 * Immediately writes all buffered data in <em>ios</em> to disk. 01632 * 01633 * If the underlying operating system does not support <em>fdatasync(2)</em>, 01634 * <code>IO#fsync</code> is called instead (which might raise a 01635 * <code>NotImplementedError</code>). 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 /* fall back */ 01653 return rb_io_fsync(io); 01654 } 01655 #else 01656 #define rb_io_fdatasync rb_io_fsync 01657 #endif 01658 01659 /* 01660 * call-seq: 01661 * ios.fileno -> fixnum 01662 * ios.to_i -> fixnum 01663 * 01664 * Returns an integer representing the numeric file descriptor for 01665 * <em>ios</em>. 01666 * 01667 * $stdin.fileno #=> 0 01668 * $stdout.fileno #=> 1 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 * call-seq: 01685 * ios.pid -> fixnum 01686 * 01687 * Returns the process ID of a child process associated with 01688 * <em>ios</em>. This will be set by <code>IO.popen</code>. 01689 * 01690 * pipe = IO.popen("-") 01691 * if pipe 01692 * $stderr.puts "In parent, child pid is #{pipe.pid}" 01693 * else 01694 * $stderr.puts "In child, pid is #{$$}" 01695 * end 01696 * 01697 * <em>produces:</em> 01698 * 01699 * In child, pid is 26209 01700 * In parent, child pid is 26209 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 * call-seq: 01717 * ios.inspect -> string 01718 * 01719 * Return a string describing this IO object. 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 * call-seq: 01753 * ios.to_io -> ios 01754 * 01755 * Returns <em>ios</em>. 01756 */ 01757 01758 static VALUE 01759 rb_io_to_io(VALUE io) 01760 { 01761 return io; 01762 } 01763 01764 /* reading functions */ 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; /* cbuf full */ 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 /* xxx: set coderange */ 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 * call-seq: 02177 * ios.readpartial(maxlen) -> string 02178 * ios.readpartial(maxlen, outbuf) -> outbuf 02179 * 02180 * Reads at most <i>maxlen</i> bytes from the I/O stream. 02181 * It blocks only if <em>ios</em> has no data immediately available. 02182 * It doesn't block if some data available. 02183 * If the optional <i>outbuf</i> argument is present, 02184 * it must reference a String, which will receive the data. 02185 * It raises <code>EOFError</code> on end of file. 02186 * 02187 * readpartial is designed for streams such as pipe, socket, tty, etc. 02188 * It blocks only when no data immediately available. 02189 * This means that it blocks only when following all conditions hold. 02190 * * the byte buffer in the IO object is empty. 02191 * * the content of the stream is empty. 02192 * * the stream is not reached to EOF. 02193 * 02194 * When readpartial blocks, it waits data or EOF on the stream. 02195 * If some data is reached, readpartial returns with the data. 02196 * If EOF is reached, readpartial raises EOFError. 02197 * 02198 * When readpartial doesn't blocks, it returns or raises immediately. 02199 * If the byte buffer is not empty, it returns the data in the buffer. 02200 * Otherwise if the stream has some content, 02201 * it returns the data in the stream. 02202 * Otherwise if the stream is reached to EOF, it raises EOFError. 02203 * 02204 * r, w = IO.pipe # buffer pipe content 02205 * w << "abc" # "" "abc". 02206 * r.readpartial(4096) #=> "abc" "" "" 02207 * r.readpartial(4096) # blocks because buffer and pipe is empty. 02208 * 02209 * r, w = IO.pipe # buffer pipe content 02210 * w << "abc" # "" "abc" 02211 * w.close # "" "abc" EOF 02212 * r.readpartial(4096) #=> "abc" "" EOF 02213 * r.readpartial(4096) # raises EOFError 02214 * 02215 * r, w = IO.pipe # buffer pipe content 02216 * w << "abc\ndef\n" # "" "abc\ndef\n" 02217 * r.gets #=> "abc\n" "def\n" "" 02218 * w << "ghi\n" # "def\n" "ghi\n" 02219 * r.readpartial(4096) #=> "def\n" "" "ghi\n" 02220 * r.readpartial(4096) #=> "ghi\n" "" "" 02221 * 02222 * Note that readpartial behaves similar to sysread. 02223 * The differences are: 02224 * * If the byte buffer is not empty, read from the byte buffer instead of "sysread for buffered IO (IOError)". 02225 * * It doesn't cause Errno::EWOULDBLOCK and Errno::EINTR. When readpartial meets EWOULDBLOCK and EINTR by read system call, readpartial retry the system call. 02226 * 02227 * The later means that readpartial is nonblocking-flag insensitive. 02228 * It blocks on the situation IO#sysread causes Errno::EWOULDBLOCK as if the fd is blocking mode. 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 * call-seq: 02246 * ios.read_nonblock(maxlen) -> string 02247 * ios.read_nonblock(maxlen, outbuf) -> outbuf 02248 * 02249 * Reads at most <i>maxlen</i> bytes from <em>ios</em> using 02250 * the read(2) system call after O_NONBLOCK is set for 02251 * the underlying file descriptor. 02252 * 02253 * If the optional <i>outbuf</i> argument is present, 02254 * it must reference a String, which will receive the data. 02255 * 02256 * read_nonblock just calls the read(2) system call. 02257 * It causes all errors the read(2) system call causes: Errno::EWOULDBLOCK, Errno::EINTR, etc. 02258 * The caller should care such errors. 02259 * 02260 * If the exception is Errno::EWOULDBLOCK or Errno::AGAIN, 02261 * it is extended by IO::WaitReadable. 02262 * So IO::WaitReadable can be used to rescue the exceptions for retrying read_nonblock. 02263 * 02264 * read_nonblock causes EOFError on EOF. 02265 * 02266 * If the read byte buffer is not empty, 02267 * read_nonblock reads from the buffer like readpartial. 02268 * In this case, the read(2) system call is not called. 02269 * 02270 * When read_nonblock raises an exception kind of IO::WaitReadable, 02271 * read_nonblock should not be called 02272 * until io is readable for avoiding busy loop. 02273 * This can be done as follows. 02274 * 02275 * # emulates blocking read (readpartial). 02276 * begin 02277 * result = io.read_nonblock(maxlen) 02278 * rescue IO::WaitReadable 02279 * IO.select([io]) 02280 * retry 02281 * end 02282 * 02283 * Although IO#read_nonblock doesn't raise IO::WaitWritable. 02284 * OpenSSL::Buffering#read_nonblock can raise IO::WaitWritable. 02285 * If IO and SSL should be used polymorphically, 02286 * IO::WaitWritable should be rescued too. 02287 * See the document of OpenSSL::Buffering#read_nonblock for sample code. 02288 * 02289 * Note that this method is identical to readpartial 02290 * except the non-blocking flag is set. 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 * call-seq: 02307 * ios.write_nonblock(string) -> integer 02308 * 02309 * Writes the given string to <em>ios</em> using 02310 * the write(2) system call after O_NONBLOCK is set for 02311 * the underlying file descriptor. 02312 * 02313 * It returns the number of bytes written. 02314 * 02315 * write_nonblock just calls the write(2) system call. 02316 * It causes all errors the write(2) system call causes: Errno::EWOULDBLOCK, Errno::EINTR, etc. 02317 * The result may also be smaller than string.length (partial write). 02318 * The caller should care such errors and partial write. 02319 * 02320 * If the exception is Errno::EWOULDBLOCK or Errno::AGAIN, 02321 * it is extended by IO::WaitWritable. 02322 * So IO::WaitWritable can be used to rescue the exceptions for retrying write_nonblock. 02323 * 02324 * # Creates a pipe. 02325 * r, w = IO.pipe 02326 * 02327 * # write_nonblock writes only 65536 bytes and return 65536. 02328 * # (The pipe size is 65536 bytes on this environment.) 02329 * s = "a" * 100000 02330 * p w.write_nonblock(s) #=> 65536 02331 * 02332 * # write_nonblock cannot write a byte and raise EWOULDBLOCK (EAGAIN). 02333 * p w.write_nonblock("b") # Resource temporarily unavailable (Errno::EAGAIN) 02334 * 02335 * If the write buffer is not empty, it is flushed at first. 02336 * 02337 * When write_nonblock raises an exception kind of IO::WaitWritable, 02338 * write_nonblock should not be called 02339 * until io is writable for avoiding busy loop. 02340 * This can be done as follows. 02341 * 02342 * begin 02343 * result = io.write_nonblock(string) 02344 * rescue IO::WaitWritable, Errno::EINTR 02345 * IO.select(nil, [io]) 02346 * retry 02347 * end 02348 * 02349 * Note that this doesn't guarantee to write all data in string. 02350 * The length written is reported as result and it should be checked later. 02351 * 02352 * On some platforms such as Windows, write_nonblock is not supported 02353 * according to the kind of the IO object. 02354 * In such cases, write_nonblock raises <code>Errno::EBADF</code>. 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 * call-seq: 02389 * ios.read([length [, buffer]]) -> string, buffer, or nil 02390 * 02391 * Reads <i>length</i> bytes from the I/O stream. 02392 * 02393 * <i>length</i> must be a non-negative integer or <code>nil</code>. 02394 * 02395 * If <i>length</i> is a positive integer, 02396 * it try to read <i>length</i> bytes without any conversion (binary mode). 02397 * It returns <code>nil</code> or a string whose length is 1 to <i>length</i> bytes. 02398 * <code>nil</code> means it met EOF at beginning. 02399 * The 1 to <i>length</i>-1 bytes string means it met EOF after reading the result. 02400 * The <i>length</i> bytes string means it doesn't meet EOF. 02401 * The resulted string is always ASCII-8BIT encoding. 02402 * 02403 * If <i>length</i> is omitted or is <code>nil</code>, 02404 * it reads until EOF and the encoding conversion is applied. 02405 * It returns a string even if EOF is met at beginning. 02406 * 02407 * If <i>length</i> is zero, it returns <code>""</code>. 02408 * 02409 * If the optional <i>buffer</i> argument is present, it must reference 02410 * a String, which will receive the data. 02411 * 02412 * At end of file, it returns <code>nil</code> or <code>""</code> 02413 * depend on <i>length</i>. 02414 * <code><i>ios</i>.read()</code> and 02415 * <code><i>ios</i>.read(nil)</code> returns <code>""</code>. 02416 * <code><i>ios</i>.read(<i>positive-integer</i>)</code> returns <code>nil</code>. 02417 * 02418 * f = File.new("testfile") 02419 * f.read(16) #=> "This is line one" 02420 * 02421 * # reads whole file 02422 * open("file") {|f| 02423 * data = f.read # This returns a string even if the file is empty. 02424 * ... 02425 * } 02426 * 02427 * # iterate over fixed length records. 02428 * open("fixed-record-file") {|f| 02429 * while record = f.read(256) 02430 * ... 02431 * end 02432 * } 02433 * 02434 * # iterate over variable length records. 02435 * # record is prefixed by 32-bit length. 02436 * open("variable-record-file") {|f| 02437 * while len = f.read(4) 02438 * len = len.unpack("N")[0] # 32-bit length 02439 * record = f.read(len) # This returns a string even if len is 0. 02440 * end 02441 * } 02442 * 02443 * Note that this method behaves like fread() function in C. 02444 * If you need the behavior like read(2) system call, 02445 * consider readpartial, read_nonblock and sysread. 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); /* must not fail */ 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)) /* must not fail */ 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 /* MS - Optimisation */ 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 /* relax the limit while incomplete character. 02811 * extra_limit limits the relax length */ 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 * call-seq: 02865 * ios.gets(sep=$/) -> string or nil 02866 * ios.gets(limit) -> string or nil 02867 * ios.gets(sep, limit) -> string or nil 02868 * 02869 * Reads the next ``line'' from the I/O stream; lines are separated by 02870 * <i>sep</i>. A separator of <code>nil</code> reads the entire 02871 * contents, and a zero-length separator reads the input a paragraph at 02872 * a time (two successive newlines in the input separate paragraphs). 02873 * The stream must be opened for reading or an <code>IOError</code> 02874 * will be raised. The line read in will be returned and also assigned 02875 * to <code>$_</code>. Returns <code>nil</code> if called at end of 02876 * file. If the first argument is an integer, or optional second 02877 * argument is given, the returning string would not be longer than the 02878 * given value in bytes. 02879 * 02880 * File.new("testfile").gets #=> "This is line one\n" 02881 * $_ #=> "This is line one\n" 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 * call-seq: 02897 * ios.lineno -> integer 02898 * 02899 * Returns the current line number in <em>ios</em>. The stream must be 02900 * opened for reading. <code>lineno</code> counts the number of times 02901 * #gets is called rather than the number of newlines encountered. The two 02902 * values will differ if #gets is called with a separator other than newline. 02903 * 02904 * Methods that use <code>$/</code> like #each, #lines and #readline will 02905 * also increment <code>lineno</code>. 02906 * 02907 * See also the <code>$.</code> variable. 02908 * 02909 * f = File.new("testfile") 02910 * f.lineno #=> 0 02911 * f.gets #=> "This is line one\n" 02912 * f.lineno #=> 1 02913 * f.gets #=> "This is line two\n" 02914 * f.lineno #=> 2 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 * call-seq: 02929 * ios.lineno = integer -> integer 02930 * 02931 * Manually sets the current line number to the given value. 02932 * <code>$.</code> is updated only on the next read. 02933 * 02934 * f = File.new("testfile") 02935 * f.gets #=> "This is line one\n" 02936 * $. #=> 1 02937 * f.lineno = 1000 02938 * f.lineno #=> 1000 02939 * $. #=> 1 # lineno of last read 02940 * f.gets #=> "This is line two\n" 02941 * $. #=> 1001 # lineno of last read 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 * call-seq: 02957 * ios.readline(sep=$/) -> string 02958 * ios.readline(limit) -> string 02959 * ios.readline(sep, limit) -> string 02960 * 02961 * Reads a line as with <code>IO#gets</code>, but raises an 02962 * <code>EOFError</code> on end of file. 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 * call-seq: 02978 * ios.readlines(sep=$/) -> array 02979 * ios.readlines(limit) -> array 02980 * ios.readlines(sep, limit) -> array 02981 * 02982 * Reads all of the lines in <em>ios</em>, and returns them in 02983 * <i>anArray</i>. Lines are separated by the optional <i>sep</i>. If 02984 * <i>sep</i> is <code>nil</code>, the rest of the stream is returned 02985 * as a single record. If the first argument is an integer, or 02986 * optional second argument is given, the returning string would not be 02987 * longer than the given value in bytes. The stream must be opened for 02988 * reading or an <code>IOError</code> will be raised. 02989 * 02990 * f = File.new("testfile") 02991 * f.readlines[0] #=> "This is line one\n" 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 * call-seq: 03012 * ios.each(sep=$/) {|line| block } -> ios 03013 * ios.each(limit) {|line| block } -> ios 03014 * ios.each(sep,limit) {|line| block } -> ios 03015 * ios.each(...) -> an_enumerator 03016 * 03017 * ios.each_line(sep=$/) {|line| block } -> ios 03018 * ios.each_line(limit) {|line| block } -> ios 03019 * ios.each_line(sep,limit) {|line| block } -> ios 03020 * ios.each_line(...) -> an_enumerator 03021 * 03022 * ios.lines(sep=$/) {|line| block } -> ios 03023 * ios.lines(limit) {|line| block } -> ios 03024 * ios.lines(sep,limit) {|line| block } -> ios 03025 * ios.lines(...) -> an_enumerator 03026 * 03027 * Executes the block for every line in <em>ios</em>, where lines are 03028 * separated by <i>sep</i>. <em>ios</em> must be opened for 03029 * reading or an <code>IOError</code> will be raised. 03030 * 03031 * If no block is given, an enumerator is returned instead. 03032 * 03033 * f = File.new("testfile") 03034 * f.each {|line| puts "#{f.lineno}: #{line}" } 03035 * 03036 * <em>produces:</em> 03037 * 03038 * 1: This is line one 03039 * 2: This is line two 03040 * 3: This is line three 03041 * 4: And so on... 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 * call-seq: 03062 * ios.bytes {|byte| block } -> ios 03063 * ios.bytes -> an_enumerator 03064 * 03065 * ios.each_byte {|byte| block } -> ios 03066 * ios.each_byte -> an_enumerator 03067 * 03068 * Calls the given block once for each byte (0..255) in <em>ios</em>, 03069 * passing the byte as an argument. The stream must be opened for 03070 * reading or an <code>IOError</code> will be raised. 03071 * 03072 * If no block is given, an enumerator is returned instead. 03073 * 03074 * f = File.new("testfile") 03075 * checksum = 0 03076 * f.each_byte {|x| checksum ^= x } #=> #<File:testfile> 03077 * checksum #=> 12 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 /* return an unit of an incomplete character just before EOF */ 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 * call-seq: 03210 * ios.chars {|c| block } -> ios 03211 * ios.chars -> an_enumerator 03212 * 03213 * ios.each_char {|c| block } -> ios 03214 * ios.each_char -> an_enumerator 03215 * 03216 * Calls the given block once for each character in <em>ios</em>, 03217 * passing the character as an argument. The stream must be opened for 03218 * reading or an <code>IOError</code> will be raised. 03219 * 03220 * If no block is given, an enumerator is returned instead. 03221 * 03222 * f = File.new("testfile") 03223 * f.each_char {|c| print c, ' ' } #=> #<File:testfile> 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 * call-seq: 03248 * ios.each_codepoint {|c| block } -> ios 03249 * ios.codepoints {|c| block } -> ios 03250 * ios.each_codepoint -> an_enumerator 03251 * ios.codepoints -> an_enumerator 03252 * 03253 * Passes the <code>Integer</code> ordinal of each character in <i>ios</i>, 03254 * passing the codepoint as an argument. The stream must be opened for 03255 * reading or an <code>IOError</code> will be raised. 03256 * 03257 * If no block is given, an enumerator is returned instead. 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 /* ignore an incomplete character before EOF */ 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 * call-seq: 03346 * ios.getc -> string or nil 03347 * 03348 * Reads a one-character string from <em>ios</em>. Returns 03349 * <code>nil</code> if called at end of file. 03350 * 03351 * f = File.new("testfile") 03352 * f.getc #=> "h" 03353 * f.getc #=> "e" 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 * call-seq: 03372 * ios.readchar -> string 03373 * 03374 * Reads a one-character string from <em>ios</em>. Raises an 03375 * <code>EOFError</code> on end of file. 03376 * 03377 * f = File.new("testfile") 03378 * f.readchar #=> "h" 03379 * f.readchar #=> "e" 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 * call-seq: 03395 * ios.getbyte -> fixnum or nil 03396 * 03397 * Gets the next 8-bit byte (0..255) from <em>ios</em>. Returns 03398 * <code>nil</code> if called at end of file. 03399 * 03400 * f = File.new("testfile") 03401 * f.getbyte #=> 84 03402 * f.getbyte #=> 104 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 * call-seq: 03432 * ios.readbyte -> fixnum 03433 * 03434 * Reads a byte as with <code>IO#getbyte</code>, but raises an 03435 * <code>EOFError</code> on end of file. 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 * call-seq: 03451 * ios.ungetbyte(string) -> nil 03452 * ios.ungetbyte(integer) -> nil 03453 * 03454 * Pushes back bytes (passed as a parameter) onto <em>ios</em>, 03455 * such that a subsequent buffered read will return it. Only one byte 03456 * may be pushed back before a subsequent read operation (that is, 03457 * you will be able to read only the last of several bytes that have been pushed 03458 * back). Has no effect with unbuffered reads (such as <code>IO#sysread</code>). 03459 * 03460 * f = File.new("testfile") #=> #<File:testfile> 03461 * b = f.getbyte #=> 0x38 03462 * f.ungetbyte(b) #=> nil 03463 * f.getbyte #=> 0x38 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 * call-seq: 03487 * ios.ungetc(string) -> nil 03488 * 03489 * Pushes back one character (passed as a parameter) onto <em>ios</em>, 03490 * such that a subsequent buffered character read will return it. Only one character 03491 * may be pushed back before a subsequent read operation (that is, 03492 * you will be able to read only the last of several characters that have been pushed 03493 * back). Has no effect with unbuffered reads (such as <code>IO#sysread</code>). 03494 * 03495 * f = File.new("testfile") #=> #<File:testfile> 03496 * c = f.getc #=> "8" 03497 * f.ungetc(c) #=> nil 03498 * f.getc #=> "8" 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 * call-seq: 03548 * ios.isatty -> true or false 03549 * ios.tty? -> true or false 03550 * 03551 * Returns <code>true</code> if <em>ios</em> is associated with a 03552 * terminal device (tty), <code>false</code> otherwise. 03553 * 03554 * File.new("testfile").isatty #=> false 03555 * File.new("/dev/tty").isatty #=> true 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 * call-seq: 03572 * ios.close_on_exec? -> true or false 03573 * 03574 * Returns <code>true</code> if <em>ios</em> will be closed on exec. 03575 * 03576 * f = open("/dev/null") 03577 * f.close_on_exec? #=> false 03578 * f.close_on_exec = true 03579 * f.close_on_exec? #=> true 03580 * f.close_on_exec = false 03581 * f.close_on_exec? #=> false 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 * call-seq: 03614 * ios.close_on_exec = bool -> true or false 03615 * 03616 * Sets a close-on-exec flag. 03617 * 03618 * f = open("/dev/null") 03619 * f.close_on_exec = true 03620 * system("cat", "/proc/self/fd/#{f.fileno}") # cat: /proc/self/fd/3: No such file or directory 03621 * f.closed? #=> false 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 /* fptr->stdio_file is deallocated anyway 03767 * even if fclose failed. */ 03768 if (fclose(fptr->stdio_file) < 0 && NIL_P(err)) 03769 err = noraise ? Qtrue : INT2NUM(errno); 03770 } 03771 else if (0 <= fptr->fd) { 03772 /* fptr->fd may be closed even if close fails. 03773 * POSIX doesn't specify it. 03774 * We assumes it is closed. */ 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 /* close(2) on a fd which is being read by another thread causes 03896 * deadlock on Mac OS X 10.5 */ 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 * call-seq: 03912 * ios.close -> nil 03913 * 03914 * Closes <em>ios</em> and flushes any pending writes to the operating 03915 * system. The stream is unavailable for any further data operations; 03916 * an <code>IOError</code> is raised if such an attempt is made. I/O 03917 * streams are automatically closed when they are claimed by the 03918 * garbage collector. 03919 * 03920 * If <em>ios</em> is opened by <code>IO.popen</code>, 03921 * <code>close</code> sets <code>$?</code>. 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 * call-seq: 03949 * ios.closed? -> true or false 03950 * 03951 * Returns <code>true</code> if <em>ios</em> is completely closed (for 03952 * duplex streams, both reader and writer), <code>false</code> 03953 * otherwise. 03954 * 03955 * f = File.new("testfile") 03956 * f.close #=> nil 03957 * f.closed? #=> true 03958 * f = IO.popen("/bin/sh","r+") 03959 * f.close_write #=> nil 03960 * f.closed? #=> false 03961 * f.close_read #=> nil 03962 * f.closed? #=> true 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 * call-seq: 03988 * ios.close_read -> nil 03989 * 03990 * Closes the read end of a duplex I/O stream (i.e., one that contains 03991 * both a read and a write stream, such as a pipe). Will raise an 03992 * <code>IOError</code> if the stream is not duplexed. 03993 * 03994 * f = IO.popen("/bin/sh","r+") 03995 * f.close_read 03996 * f.readlines 03997 * 03998 * <em>produces:</em> 03999 * 04000 * prog.rb:3:in `readlines': not opened for reading (IOError) 04001 * from prog.rb:3 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 * call-seq: 04045 * ios.close_write -> nil 04046 * 04047 * Closes the write end of a duplex I/O stream (i.e., one that contains 04048 * both a read and a write stream, such as a pipe). Will raise an 04049 * <code>IOError</code> if the stream is not duplexed. 04050 * 04051 * f = IO.popen("/bin/sh","r+") 04052 * f.close_write 04053 * f.print "nowhere" 04054 * 04055 * <em>produces:</em> 04056 * 04057 * prog.rb:3:in `write': not opened for writing (IOError) 04058 * from prog.rb:3:in `print' 04059 * from prog.rb:3 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 * call-seq: 04100 * ios.sysseek(offset, whence=IO::SEEK_SET) -> integer 04101 * 04102 * Seeks to a given <i>offset</i> in the stream according to the value 04103 * of <i>whence</i> (see <code>IO#seek</code> for values of 04104 * <i>whence</i>). Returns the new offset into the file. 04105 * 04106 * f = File.new("testfile") 04107 * f.sysseek(-13, IO::SEEK_END) #=> 53 04108 * f.sysread(10) #=> "And so on." 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 * call-seq: 04140 * ios.syswrite(string) -> integer 04141 * 04142 * Writes the given string to <em>ios</em> using a low-level write. 04143 * Returns the number of bytes written. Do not mix with other methods 04144 * that write to <em>ios</em> or you may get unpredictable results. 04145 * Raises <code>SystemCallError</code> on error. 04146 * 04147 * f = File.new("out", "w") 04148 * f.syswrite("ABCDEF") #=> 6 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 * call-seq: 04181 * ios.sysread(maxlen[, outbuf]) -> string 04182 * 04183 * Reads <i>maxlen</i> bytes from <em>ios</em> using a low-level 04184 * read and returns them as a string. Do not mix with other methods 04185 * that read from <em>ios</em> or you may get unpredictable results. 04186 * If the optional <i>outbuf</i> argument is present, it must reference 04187 * a String, which will receive the data. 04188 * Raises <code>SystemCallError</code> on error and 04189 * <code>EOFError</code> at end of file. 04190 * 04191 * f = File.new("testfile") 04192 * f.sysread(16) #=> "This is line one" 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 * call-seq: 04289 * ios.binmode -> ios 04290 * 04291 * Puts <em>ios</em> into binary mode. 04292 * Once a stream is in binary mode, it cannot be reset to nonbinary mode. 04293 * 04294 * - newline conversion disabled 04295 * - encoding conversion disabled 04296 * - content is treated as ASCII-8BIT 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 * call-seq: 04315 * ios.binmode? -> true or false 04316 * 04317 * Returns <code>true</code> if <em>ios</em> is binmode. 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; /* not reached */ 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; /* not reached */ 04515 } 04516 04517 /* 04518 * Convert external/internal encodings to enc/enc2 04519 * NULL => use default encoding 04520 * Qnil => no encoding specified (internal only) 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 /* If external is ASCII-8BIT, no default transcoding */ 04533 intern = rb_default_internal_encoding(); 04534 if (intern == NULL || intern == (rb_encoding *)Qnil || intern == ext) { 04535 /* No internal encoding => use external + no transcoding */ 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 /* parse estr as "enc" or "enc2:enc" or "enc:-" */ 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 /* Special case - "-" => no transcoding */ 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 /* internal_encoding: nil => no transcoding */ 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 /* Special case - "-" => no transcoding */ 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 /* Set to defaults */ 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 /* perm no use, just ignore */ 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 /* xxx: should be _IONBF? A buffer in FILE may have trouble. */ 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 /* Set to default encodings */ 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 /* Set to default encodings */ 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 /* fork : IO.popen("-") */ 05316 argc = 0; 05317 argv = 0; 05318 } 05319 else if (eargp->argc) { 05320 /* no shell : IO.popen([prog, arg0], arg1, ...) */ 05321 argc = eargp->argc; 05322 argv = eargp->argv; 05323 } 05324 else { 05325 /* with shell : IO.popen(prog) */ 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); /* is it really needed? */ 05372 pid = rb_fork(&status, 0, 0, Qnil); 05373 if (pid == 0) { /* child */ 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 /* parent */ 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 /* exec failed */ 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 * call-seq: 05595 * IO.popen(cmd, mode="r" [, opt]) -> io 05596 * IO.popen(cmd, mode="r" [, opt]) {|io| block } -> obj 05597 * 05598 * Runs the specified command as a subprocess; the subprocess's 05599 * standard input and output will be connected to the returned 05600 * <code>IO</code> object. 05601 * 05602 * The PID of the started process can be obtained by IO#pid method. 05603 * 05604 * _cmd_ is a string or an array as follows. 05605 * 05606 * cmd: 05607 * "-" : fork 05608 * commandline : command line string which is passed to a shell 05609 * [env, cmdname, arg1, ..., opts] : command name and zero or more arguments (no shell) 05610 * [env, [cmdname, argv0], arg1, ..., opts] : command name, argv[0] and zero or more arguments (no shell) 05611 * (env and opts are optional.) 05612 * 05613 * If _cmd_ is a +String+ ``<code>-</code>'', 05614 * then a new instance of Ruby is started as the subprocess. 05615 * 05616 * If <i>cmd</i> is an +Array+ of +String+, 05617 * then it will be used as the subprocess's +argv+ bypassing a shell. 05618 * The array can contains a hash at first for environments and 05619 * a hash at last for options similar to <code>spawn</code>. 05620 * 05621 * The default mode for the new file object is ``r'', 05622 * but <i>mode</i> may be set to any of the modes listed in the description for class IO. 05623 * The last argument <i>opt</i> qualifies <i>mode</i>. 05624 * 05625 * # set IO encoding 05626 * IO.popen("nkf -e filename", :external_encoding=>"EUC-JP") {|nkf_io| 05627 * euc_jp_string = nkf_io.read 05628 * } 05629 * 05630 * # merge standard output and standard error using 05631 * # spawn option. See the document of Kernel.spawn. 05632 * IO.popen(["ls", "/", :err=>[:child, :out]]) {|ls_io| 05633 * ls_result_with_error = ls_io.read 05634 * } 05635 * 05636 * Raises exceptions which <code>IO.pipe</code> and 05637 * <code>Kernel.spawn</code> raise. 05638 * 05639 * If a block is given, Ruby will run the command as a child connected 05640 * to Ruby with a pipe. Ruby's end of the pipe will be passed as a 05641 * parameter to the block. 05642 * At the end of block, Ruby close the pipe and sets <code>$?</code>. 05643 * In this case <code>IO.popen</code> returns 05644 * the value of the block. 05645 * 05646 * If a block is given with a _cmd_ of ``<code>-</code>'', 05647 * the block will be run in two separate processes: once in the parent, 05648 * and once in a child. The parent process will be passed the pipe 05649 * object as a parameter to the block, the child version of the block 05650 * will be passed <code>nil</code>, and the child's standard in and 05651 * standard out will be connected to the parent through the pipe. Not 05652 * available on all platforms. 05653 * 05654 * f = IO.popen("uname") 05655 * p f.readlines 05656 * f.close 05657 * puts "Parent is #{Process.pid}" 05658 * IO.popen("date") { |f| puts f.gets } 05659 * IO.popen("-") {|f| $stderr.puts "#{Process.pid} is here, f is #{f.inspect}"} 05660 * p $? 05661 * IO.popen(%w"sed -e s|^|<foo>| -e s&$&;zot;&", "r+") {|f| 05662 * f.puts "bar"; f.close_write; puts f.gets 05663 * } 05664 * 05665 * <em>produces:</em> 05666 * 05667 * ["Linux\n"] 05668 * Parent is 21346 05669 * Thu Jan 15 22:41:19 JST 2009 05670 * 21346 is here, f is #<IO:fd 3> 05671 * 21352 is here, f is nil 05672 * #<Process::Status: pid 21352 exit 0> 05673 * <foo>bar;zot; 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 /* child */ 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 * Document-method: File::open 05762 * 05763 * call-seq: 05764 * File.open(filename, mode="r" [, opt]) -> file 05765 * File.open(filename [, mode [, perm]] [, opt]) -> file 05766 * File.open(filename, mode="r" [, opt]) {|file| block } -> obj 05767 * File.open(filename [, mode [, perm]] [, opt]) {|file| block } -> obj 05768 * 05769 * With no associated block, <code>File.open</code> is a synonym for 05770 * File.new. If the optional code block is given, it will 05771 * be passed the opened +file+ as an argument, and the File object will 05772 * automatically be closed when the block terminates. In this instance, 05773 * <code>File.open</code> returns the value of the block. 05774 * 05775 * See IO.new for a list of values for the +opt+ parameter. 05776 */ 05777 05778 /* 05779 * Document-method: IO::open 05780 * 05781 * call-seq: 05782 * IO.open(fd, mode_string="r" [, opt]) -> io 05783 * IO.open(fd, mode_string="r" [, opt]) {|io| block } -> obj 05784 * 05785 * With no associated block, <code>IO.open</code> is a synonym for IO.new. If 05786 * the optional code block is given, it will be passed +io+ as an 05787 * argument, and the IO object will automatically be closed when the block 05788 * terminates. In this instance, IO.open returns the value of the block. 05789 * 05790 * See IO.new for a description of values for the +opt+ parameter. 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 * call-seq: 05808 * IO.sysopen(path, [mode, [perm]]) -> fixnum 05809 * 05810 * Opens the given path, returning the underlying file descriptor as a 05811 * <code>Fixnum</code>. 05812 * 05813 * IO.sysopen("testfile") #=> 3 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 * call-seq: 05862 * open(path [, mode_enc [, perm]] [, opt]) -> io or nil 05863 * open(path [, mode_enc [, perm]] [, opt]) {|io| block } -> obj 05864 * 05865 * Creates an <code>IO</code> object connected to the given stream, 05866 * file, or subprocess. 05867 * 05868 * If <i>path</i> does not start with a pipe character 05869 * (``<code>|</code>''), treat it as the name of a file to open using 05870 * the specified mode (defaulting to ``<code>r</code>''). 05871 * 05872 * The mode_enc is 05873 * either a string or an integer. If it is an integer, it must be 05874 * bitwise-or of open(2) flags, such as File::RDWR or File::EXCL. 05875 * If it is a string, it is either "mode", "mode:ext_enc", or 05876 * "mode:ext_enc:int_enc". 05877 * The mode is one of the following: 05878 * 05879 * r: read (default) 05880 * w: write 05881 * a: append 05882 * 05883 * The mode can be followed by "b" (means binary-mode), or "+" 05884 * (means both reading and writing allowed) or both. 05885 * If ext_enc (external encoding) is specified, 05886 * read string will be tagged by the encoding in reading, 05887 * and output string will be converted 05888 * to the specified encoding in writing. 05889 * If ext_enc starts with 'BOM|', check whether the input has a BOM. If 05890 * there is a BOM, strip it and set external encoding as 05891 * what the BOM tells. If there is no BOM, use ext_enc without 'BOM|'. 05892 * If two encoding names, 05893 * ext_enc and int_enc (external encoding and internal encoding), 05894 * are specified, the read string is converted from ext_enc 05895 * to int_enc then tagged with the int_enc in read mode, 05896 * and in write mode, the output string will be 05897 * converted from int_enc to ext_enc before writing. 05898 * 05899 * If a file is being created, its initial permissions may be 05900 * set using the integer third parameter. 05901 * 05902 * If a block is specified, it will be invoked with the 05903 * <code>File</code> object as a parameter, and the file will be 05904 * automatically closed when the block terminates. The call 05905 * returns the value of the block. 05906 * 05907 * If <i>path</i> starts with a pipe character, a subprocess is 05908 * created, connected to the caller by a pair of pipes. The returned 05909 * <code>IO</code> object may be used to write to the standard input 05910 * and read from the standard output of this subprocess. If the command 05911 * following the ``<code>|</code>'' is a single minus sign, Ruby forks, 05912 * and this subprocess is connected to the parent. In the subprocess, 05913 * the <code>open</code> call returns <code>nil</code>. If the command 05914 * is not ``<code>-</code>'', the subprocess runs the command. If a 05915 * block is associated with an <code>open("|-")</code> call, that block 05916 * will be run twice---once in the parent and once in the child. The 05917 * block parameter will be an <code>IO</code> object in the parent and 05918 * <code>nil</code> in the child. The parent's <code>IO</code> object 05919 * will be connected to the child's <code>$stdin</code> and 05920 * <code>$stdout</code>. The subprocess will be terminated at the end 05921 * of the block. 05922 * 05923 * open("testfile") do |f| 05924 * print f.gets 05925 * end 05926 * 05927 * <em>produces:</em> 05928 * 05929 * This is line one 05930 * 05931 * Open a subprocess and read its output: 05932 * 05933 * cmd = open("|date") 05934 * print cmd.gets 05935 * cmd.close 05936 * 05937 * <em>produces:</em> 05938 * 05939 * Wed Apr 9 08:56:31 CDT 2003 05940 * 05941 * Open a subprocess running the same Ruby program: 05942 * 05943 * f = open("|-", "w+") 05944 * if f == nil 05945 * puts "in Child" 05946 * exit 05947 * else 05948 * puts "Got: #{f.gets}" 05949 * end 05950 * 05951 * <em>produces:</em> 05952 * 05953 * Got: in Child 05954 * 05955 * Open a subprocess using a block to receive the I/O object: 05956 * 05957 * open("|-") do |f| 05958 * if f == nil 05959 * puts "in Child" 05960 * else 05961 * puts "Got: #{f.gets}" 05962 * end 05963 * end 05964 * 05965 * <em>produces:</em> 05966 * 05967 * Got: in Child 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 /* copy rb_io_t structure */ 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 /* need to keep FILE objects of stdin, stdout and stderr */ 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 * call-seq: 06129 * ios.reopen(other_IO) -> ios 06130 * ios.reopen(path, mode_str) -> ios 06131 * 06132 * Reassociates <em>ios</em> with the I/O stream given in 06133 * <i>other_IO</i> or to a new stream opened on <i>path</i>. This may 06134 * dynamically change the actual class of this stream. 06135 * 06136 * f1 = File.new("testfile") 06137 * f2 = File.new("testfile") 06138 * f2.readlines[0] #=> "This is line one\n" 06139 * f2.reopen(f1) #=> #<File:testfile> 06140 * f2.readlines[0] #=> "This is line one\n" 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 /* :nodoc: */ 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 /* copy rb_io_t structure */ 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 * call-seq: 06265 * ios.printf(format_string [, obj, ...]) -> nil 06266 * 06267 * Formats and writes to <em>ios</em>, converting parameters under 06268 * control of the format string. See <code>Kernel#sprintf</code> 06269 * for details. 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 * call-seq: 06281 * printf(io, string [, obj ... ]) -> nil 06282 * printf(string [, obj ... ]) -> nil 06283 * 06284 * Equivalent to: 06285 * io.write(sprintf(string, obj, ...) 06286 * or 06287 * $stdout.write(sprintf(string, obj, ...) 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 * call-seq: 06311 * ios.print() -> nil 06312 * ios.print(obj, ...) -> nil 06313 * 06314 * Writes the given object(s) to <em>ios</em>. The stream must be 06315 * opened for writing. If the output field separator (<code>$,</code>) 06316 * is not <code>nil</code>, it will be inserted between each object. 06317 * If the output record separator (<code>$\</code>) 06318 * is not <code>nil</code>, it will be appended to the output. If no 06319 * arguments are given, prints <code>$_</code>. Objects that aren't 06320 * strings will be converted by calling their <code>to_s</code> method. 06321 * With no argument, prints the contents of the variable <code>$_</code>. 06322 * Returns <code>nil</code>. 06323 * 06324 * $stdout.print("This is ", 100, " percent.\n") 06325 * 06326 * <em>produces:</em> 06327 * 06328 * This is 100 percent. 06329 */ 06330 06331 VALUE 06332 rb_io_print(int argc, VALUE *argv, VALUE out) 06333 { 06334 int i; 06335 VALUE line; 06336 06337 /* if no argument given, print `$_' */ 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 * call-seq: 06358 * print(obj, ...) -> nil 06359 * 06360 * Prints each object in turn to <code>$stdout</code>. If the output 06361 * field separator (<code>$,</code>) is not +nil+, its 06362 * contents will appear between each field. If the output record 06363 * separator (<code>$\</code>) is not +nil+, it will be 06364 * appended to the output. If no arguments are given, prints 06365 * <code>$_</code>. Objects that aren't strings will be converted by 06366 * calling their <code>to_s</code> method. 06367 * 06368 * print "cat", [1,2,3], 99, "\n" 06369 * $, = ", " 06370 * $\ = "\n" 06371 * print "cat", [1,2,3], 99 06372 * 06373 * <em>produces:</em> 06374 * 06375 * cat12399 06376 * cat, 1, 2, 3, 99 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 * call-seq: 06388 * ios.putc(obj) -> obj 06389 * 06390 * If <i>obj</i> is <code>Numeric</code>, write the character whose code is 06391 * the least-significant byte of <i>obj</i>, otherwise write the first byte 06392 * of the string representation of <i>obj</i> to <em>ios</em>. Note: This 06393 * method is not safe for use with multi-byte characters as it will truncate 06394 * them. 06395 * 06396 * $stdout.putc "A" 06397 * $stdout.putc 65 06398 * 06399 * <em>produces:</em> 06400 * 06401 * AA 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 * call-seq: 06421 * putc(int) -> int 06422 * 06423 * Equivalent to: 06424 * 06425 * $stdout.putc(int) 06426 * 06427 * Refer to the documentation for IO#putc for important information regarding 06428 * multi-byte characters. 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 * call-seq: 06476 * ios.puts(obj, ...) -> nil 06477 * 06478 * Writes the given objects to <em>ios</em> as with 06479 * <code>IO#print</code>. Writes a record separator (typically a 06480 * newline) after any that do not already end with a newline sequence. 06481 * If called with an array argument, writes each element on a new line. 06482 * If called without arguments, outputs a single record separator. 06483 * 06484 * $stdout.puts("this", "is", "a", "test") 06485 * 06486 * <em>produces:</em> 06487 * 06488 * this 06489 * is 06490 * a 06491 * test 06492 */ 06493 06494 VALUE 06495 rb_io_puts(int argc, VALUE *argv, VALUE out) 06496 { 06497 int i; 06498 VALUE line; 06499 06500 /* if no argument given, print newline. */ 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 * call-seq: 06529 * puts(obj, ...) -> nil 06530 * 06531 * Equivalent to 06532 * 06533 * $stdout.puts(obj, ...) 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) /* for debug print within C code */ 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 * call-seq: 06562 * p(obj) -> obj 06563 * p(obj1, obj2, ...) -> [obj, ...] 06564 * p() -> nil 06565 * 06566 * For each object, directly writes _obj_.+inspect+ followed by a 06567 * newline to the program's standard output. 06568 * 06569 * S = Struct.new(:name, :state) 06570 * s = S['dave', 'TX'] 06571 * p s 06572 * 06573 * <em>produces:</em> 06574 * 06575 * #<S name="dave", state="TX"> 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 * call-seq: 06601 * obj.display(port=$>) -> nil 06602 * 06603 * Prints <i>obj</i> on the given port (default <code>$></code>). 06604 * Equivalent to: 06605 * 06606 * def display(port=$>) 06607 * port.write self 06608 * end 06609 * 06610 * For example: 06611 * 06612 * 1.display 06613 * "cat".display 06614 * [ 4, 5, 6 ].display 06615 * puts 06616 * 06617 * <em>produces:</em> 06618 * 06619 * 1cat456 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 * call-seq: 06734 * IO.new(fd [, mode] [, opt]) -> io 06735 * 06736 * Returns a new IO object (a stream) for the given IO object or integer file 06737 * descriptor and mode string. See also IO.sysopen and IO.for_fd. 06738 * 06739 * === Parameters 06740 * 06741 * fd:: numeric file descriptor or IO object 06742 * mode:: file mode. a string or an integer 06743 * opt:: hash for specifying +mode+ by name. 06744 * 06745 * ==== Mode 06746 * 06747 * When mode is an integer it must be combination of the modes defined in 06748 * File::Constants. 06749 * 06750 * When mode is a string it must be in one of the following forms: 06751 * - "fmode", 06752 * - "fmode:extern", 06753 * - "fmode:extern:intern". 06754 * <code>extern</code> is the external encoding name for the IO. 06755 * <code>intern</code> is the internal encoding. 06756 * <code>fmode</code> must be a file open mode string. See the description of 06757 * class IO for mode string directives. 06758 * 06759 * When the mode of original IO is read only, the mode cannot be changed to 06760 * be writable. Similarly, the mode cannot be changed from write only to 06761 * readable. 06762 * 06763 * When such a change is attempted the error is raised in different locations 06764 * according to the platform. 06765 * 06766 * ==== Options 06767 * +opt+ can have the following keys 06768 * :mode :: 06769 * Same as +mode+ parameter 06770 * :external_encoding :: 06771 * External encoding for the IO. "-" is a synonym for the default external 06772 * encoding. 06773 * :internal_encoding :: 06774 * Internal encoding for the IO. "-" is a synonym for the default internal 06775 * encoding. 06776 * 06777 * If the value is nil no conversion occurs. 06778 * :encoding :: 06779 * Specifies external and internal encodings as "extern:intern". 06780 * :textmode :: 06781 * If the value is truth value, same as "t" in argument +mode+. 06782 * :binmode :: 06783 * If the value is truth value, same as "b" in argument +mode+. 06784 * :autoclose :: 06785 * If the value is +false+, the +fd+ will be kept open after this IO 06786 * instance gets finalized. 06787 * 06788 * Also +opt+ can have same keys in String#encode for controlling conversion 06789 * between the external encoding and the internal encoding. 06790 * 06791 * === Example 1 06792 * 06793 * fd = IO.sysopen("/dev/tty", "w") 06794 * a = IO.new(fd,"w") 06795 * $stderr.puts "Hello" 06796 * a.puts "World" 06797 * 06798 * <em>produces:</em> 06799 * 06800 * Hello 06801 * World 06802 * 06803 * === Example 2 06804 * 06805 * require 'fcntl' 06806 * 06807 * fd = STDERR.fcntl(Fcntl::F_DUPFD) 06808 * io = IO.new(fd, mode: 'w:UTF-16LE', cr_newline: true) 06809 * io.puts "Hello, World!" 06810 * 06811 * fd = STDERR.fcntl(Fcntl::F_DUPFD) 06812 * io = IO.new(fd, mode: 'w', cr_newline: true, 06813 * external_encoding: Encoding::UTF_16LE) 06814 * io.puts "Hello, World!" 06815 * 06816 * Both of above print "Hello, World!" in UTF-16LE to standard error output 06817 * with converting EOL generated by <code>puts</code> to CR. 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 * call-seq: 06882 * File.new(filename, mode="r" [, opt]) -> file 06883 * File.new(filename [, mode [, perm]] [, opt]) -> file 06884 * 06885 * Opens the file named by +filename+ according to +mode+ (default is "r") 06886 * and returns a new <code>File</code> object. 06887 * 06888 * === Parameters 06889 * 06890 * See the description of class IO for a description of +mode+. The file 06891 * mode may optionally be specified as a Fixnum by +or+-ing together the 06892 * flags (O_RDONLY etc, again described under +IO+). 06893 * 06894 * Optional permission bits may be given in +perm+. These mode and 06895 * permission bits are platform dependent; on Unix systems, see 06896 * <code>open(2)</code> for details. 06897 * 06898 * Optional +opt+ parameter is same as in IO.open. 06899 * 06900 * === Examples 06901 * 06902 * f = File.new("testfile", "r") 06903 * f = File.new("newfile", "w+") 06904 * f = File.new("newfile", File::CREAT|File::TRUNC|File::RDWR, 0644) 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 /* :nodoc: */ 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 * call-seq: 06942 * IO.for_fd(fd, mode [, opt]) -> io 06943 * 06944 * Synonym for <code>IO.new</code>. 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 * call-seq: 06958 * ios.autoclose? -> true or false 06959 * 06960 * Returns +true+ if the underlying file descriptor of _ios_ will be 06961 * closed automatically at its finalization, otherwise +false+. 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 * call-seq: 06975 * io.autoclose = bool -> true or false 06976 * 06977 * Sets auto-close flag. 06978 * 06979 * f = open("/dev/null") 06980 * IO.for_fd(f.fileno) 06981 * # ... 06982 * f.gets # may cause IOError 06983 * 06984 * f = open("/dev/null") 06985 * IO.for_fd(f.fileno).autoclose = true 06986 * # ... 06987 * f.gets # won't cause IOError 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 /* :nodoc: */ 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 /* :nodoc: */ 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 * call-seq: 07068 * ARGF.lineno = number -> nil 07069 * 07070 * Sets the line number of +ARGF+ as a whole to the given +Integer+. 07071 * 07072 * +ARGF+ sets the line number automatically as you read data, so normally 07073 * you will not need to set it explicitly. To access the current line number 07074 * use +ARGF.lineno+. 07075 * 07076 * For example: 07077 * 07078 * ARGF.lineno #=> 0 07079 * ARGF.readline #=> "This is line 1\n" 07080 * ARGF.lineno #=> 1 07081 * ARGF.lineno = 0 #=> nil 07082 * ARGF.lineno #=> 0 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 * call-seq: 07094 * ARGF.lineno -> integer 07095 * 07096 * Returns the current line number of ARGF as a whole. This value 07097 * can be set manually with +ARGF.lineno=+. 07098 * 07099 * For example: 07100 * 07101 * ARGF.lineno #=> 0 07102 * ARGF.readline #=> "This is line 1\n" 07103 * ARGF.lineno #=> 1 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 * call-seq: 07354 * gets(sep=$/) -> string or nil 07355 * gets(limit) -> string or nil 07356 * gets(sep,limit) -> string or nil 07357 * 07358 * Returns (and assigns to <code>$_</code>) the next line from the list 07359 * of files in +ARGV+ (or <code>$*</code>), or from standard input if 07360 * no files are present on the command line. Returns +nil+ at end of 07361 * file. The optional argument specifies the record separator. The 07362 * separator is included with the contents of each record. A separator 07363 * of +nil+ reads the entire contents, and a zero-length separator 07364 * reads the input one paragraph at a time, where paragraphs are 07365 * divided by two consecutive newlines. If the first argument is an 07366 * integer, or optional second argument is given, the returning string 07367 * would not be longer than the given value in bytes. If multiple 07368 * filenames are present in +ARGV+, +gets(nil)+ will read the contents 07369 * one file at a time. 07370 * 07371 * ARGV << "testfile" 07372 * print while gets 07373 * 07374 * <em>produces:</em> 07375 * 07376 * This is line one 07377 * This is line two 07378 * This is line three 07379 * And so on... 07380 * 07381 * The style of programming using <code>$_</code> as an implicit 07382 * parameter is gradually losing favor in the Ruby community. 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 * call-seq: 07396 * ARGF.gets(sep=$/) -> string 07397 * ARGF.gets(limit) -> string 07398 * ARGF.gets(sep, limit) -> string 07399 * 07400 * Returns the next line from the current file in +ARGF+. 07401 * 07402 * By default lines are assumed to be separated by +$/+; to use a different 07403 * character as a separator, supply it as a +String+ for the _sep_ argument. 07404 * 07405 * The optional _limit_ argument specifies how many characters of each line 07406 * to return. By default all characters are returned. 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 * call-seq: 07450 * readline(sep=$/) -> string 07451 * readline(limit) -> string 07452 * readline(sep, limit) -> string 07453 * 07454 * Equivalent to <code>Kernel::gets</code>, except 07455 * +readline+ raises +EOFError+ at end of file. 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 * call-seq: 07470 * ARGF.readline(sep=$/) -> string 07471 * ARGF.readline(limit) -> string 07472 * ARGF.readline(sep, limit) -> string 07473 * 07474 * Returns the next line from the current file in +ARGF+. 07475 * 07476 * By default lines are assumed to be separated by +$/+; to use a different 07477 * character as a separator, supply it as a +String+ for the _sep_ argument. 07478 * 07479 * The optional _limit_ argument specifies how many characters of each line 07480 * to return. By default all characters are returned. 07481 * 07482 * An +EOFError+ is raised at the end of the file. 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 * call-seq: 07503 * readlines(sep=$/) -> array 07504 * readlines(limit) -> array 07505 * readlines(sep,limit) -> array 07506 * 07507 * Returns an array containing the lines returned by calling 07508 * <code>Kernel.gets(<i>sep</i>)</code> until the end of file. 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 * call-seq: 07522 * ARGF.readlines(sep=$/) -> array 07523 * ARGF.readlines(limit) -> array 07524 * ARGF.readlines(sep, limit) -> array 07525 * 07526 * ARGF.to_a(sep=$/) -> array 07527 * ARGF.to_a(limit) -> array 07528 * ARGF.to_a(sep, limit) -> array 07529 * 07530 * Reads +ARGF+'s current file in its entirety, returning an +Array+ of its 07531 * lines, one line per element. Lines are assumed to be separated by _sep_. 07532 * 07533 * lines = ARGF.readlines 07534 * lines[0] #=> "This is line one\n" 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 * call-seq: 07562 * `cmd` -> string 07563 * 07564 * Returns the standard output of running _cmd_ in a subshell. 07565 * The built-in syntax <code>%x{...}</code> uses 07566 * this method. Sets <code>$?</code> to the process status. 07567 * 07568 * `date` #=> "Wed Apr 9 08:56:30 CDT 2003\n" 07569 * `ls testdir`.split[1] #=> "main.rb" 07570 * `echo oops && exit 99` #=> "oops\n" 07571 * $?.exitstatus #=> 99 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)) { /* check for buffered data */ 07613 pending++; 07614 rb_fd_set(fptr->fd, &fds[3]); 07615 } 07616 if (max < fptr->fd) max = fptr->fd; 07617 } 07618 if (pending) { /* no blocking if there's buffered data */ 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; /* returns nil on timeout */ 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; /* returns an empty array on interrupt */ 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 * The platform doesn't support this hint. We don't raise exception, instead 07811 * silently ignore it. Because IO::advise is only hint. 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 /* posix_fadvise(2) doesn't set errno. On success it returns 0; otherwise 07824 it returns the error code. */ 07825 rb_syserr_fail(rv, RSTRING_PTR(fptr->pathv)); 07826 07827 return Qnil; 07828 } 07829 07830 #endif /* HAVE_POSIX_FADVISE */ 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 * call-seq: 07852 * ios.advise(advice, offset=0, len=0) -> nil 07853 * 07854 * Announce an intention to access data from the current file in a 07855 * specific pattern. On platforms that do not support the 07856 * <em>posix_fadvise(2)</em> system call, this method is a no-op. 07857 * 07858 * _advice_ is one of the following symbols: 07859 * 07860 * * :normal - No advice to give; the default assumption for an open file. 07861 * * :sequential - The data will be accessed sequentially: 07862 * with lower offsets read before higher ones. 07863 * * :random - The data will be accessed in random order. 07864 * * :willneed - The data will be accessed in the near future. 07865 * * :dontneed - The data will not be accessed in the near future. 07866 * * :noreuse - The data will only be accessed once. 07867 * 07868 * The semantics of a piece of advice are platform-dependent. See 07869 * <em>man 2 posix_fadvise</em> for details. 07870 * 07871 * "data" means the region of the current file that begins at 07872 * _offset_ and extends for _len_ bytes. If _len_ is 0, the region 07873 * ends at the last byte of the file. By default, both _offset_ and 07874 * _len_ are 0, meaning that the advice applies to the entire file. 07875 * 07876 * If an error occurs, one of the following exceptions will be raised: 07877 * 07878 * * <code>IOError</code> - The <code>IO</code> stream is closed. 07879 * * <code>Errno::EBADF</code> - The file descriptor of the current file is 07880 invalid. 07881 * * <code>Errno::EINVAL</code> - An invalid value for _advice_ was given. 07882 * * <code>Errno::ESPIPE</code> - The file descriptor of the current 07883 * * file refers to a FIFO or pipe. (Linux raises <code>Errno::EINVAL</code> 07884 * * in this case). 07885 * * <code>TypeError</code> - Either _advice_ was not a Symbol, or one of the 07886 other arguments was not an <code>Integer</code>. 07887 * * <code>RangeError</code> - One of the arguments given was too big/small. 07888 * 07889 * This list is not exhaustive; other Errno:: exceptions are also possible. 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 /* Ignore all hint */ 07911 return Qnil; 07912 #endif 07913 } 07914 07915 /* 07916 * call-seq: 07917 * IO.select(read_array 07918 * [, write_array 07919 * [, error_array 07920 * [, timeout]]]) -> array or nil 07921 * 07922 * Calls select(2) system call. 07923 * It monitors given arrays of <code>IO</code> objects, waits one or more 07924 * of <code>IO</code> objects ready for reading, are ready for writing, 07925 * and have pending exceptions respectably, and returns an array that 07926 * contains arrays of those IO objects. It will return <code>nil</code> 07927 * if optional <i>timeout</i> value is given and no <code>IO</code> object 07928 * is ready in <i>timeout</i> seconds. 07929 * 07930 * === Parameters 07931 * read_array:: an array of <code>IO</code> objects that wait until ready for read 07932 * write_array:: an array of <code>IO</code> objects that wait until ready for write 07933 * error_array:: an array of <code>IO</code> objects that wait for exceptions 07934 * timeout:: a numeric value in second 07935 * 07936 * === Example 07937 * 07938 * rp, wp = IO.pipe 07939 * mesg = "ping " 07940 * 100.times { 07941 * rs, ws, = IO.select([rp], [wp]) 07942 * if r = rs[0] 07943 * ret = r.read(5) 07944 * print ret 07945 * case ret 07946 * when /ping/ 07947 * mesg = "pong\n" 07948 * when /pong/ 07949 * mesg = "ping " 07950 * end 07951 * end 07952 * if w = ws[0] 07953 * w.write(mesg) 07954 * end 07955 * } 07956 * 07957 * <em>produces:</em> 07958 * 07959 * ping pong 07960 * ping pong 07961 * ping pong 07962 * (snipped) 07963 * ping 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 /* legacy and unstructured ioctl number. */ 08035 return DEFULT_IOCTL_NARG_LEN; 08036 } 08037 08038 len = _IOC_SIZE(cmd); 08039 08040 /* paranoia check for silly drivers which don't keep ioctl convention */ 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); /* on BSDish systems we're safe */ 08060 #elif defined(__linux__) 08061 len = linux_iocparm_len(cmd); 08062 #else 08063 /* otherwise guess at what's safe */ 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 /* posix */ 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 /* bsd specific */ 08090 case F_DUP2FD: 08091 len = sizeof(int); 08092 break; 08093 #endif 08094 #ifdef F_DUPFD_CLOEXEC /* linux specific */ 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 /* linux specific */ 08130 case F_GETOWN_EX: 08131 len = sizeof(struct f_owner_ex); 08132 break; 08133 #endif 08134 #ifdef F_SETOWN_EX /* linux specific */ 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 /* bsd specific */ 08155 case F_READAHEAD: 08156 len = sizeof(int); 08157 break; 08158 #endif 08159 #ifdef F_RDAHEAD /* Darwin specific */ 08160 case F_RDAHEAD: 08161 len = sizeof(int); 08162 break; 08163 #endif 08164 #ifdef F_GETSIG /* linux specific */ 08165 case F_GETSIG: 08166 len = 1; 08167 break; 08168 #endif 08169 #ifdef F_SETSIG /* linux specific */ 08170 case F_SETSIG: 08171 len = sizeof(fcntl_arg_t); 08172 break; 08173 #endif 08174 #ifdef F_GETLEASE /* linux specific */ 08175 case F_GETLEASE: 08176 len = 1; 08177 break; 08178 #endif 08179 #ifdef F_SETLEASE /* linux specific */ 08180 case F_SETLEASE: 08181 len = sizeof(fcntl_arg_t); 08182 break; 08183 #endif 08184 #ifdef F_NOTIFY /* linux specific */ 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 /* HAVE_FCNTL */ 08198 static long 08199 fcntl_narg_len(int cmd) 08200 { 08201 return 0; 08202 } 08203 #endif /* HAVE_FCNTL */ 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 /* expand for data + sentinel. */ 08237 if (RSTRING_LEN(arg) < len+1) { 08238 rb_str_resize(arg, len+1); 08239 } 08240 /* a little sanity check here */ 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 * call-seq: 08273 * ios.ioctl(integer_cmd, arg) -> integer 08274 * 08275 * Provides a mechanism for issuing low-level commands to control or 08276 * query I/O devices. Arguments and results are platform dependent. If 08277 * <i>arg</i> is a number, its value is passed directly. If it is a 08278 * string, it is interpreted as a binary sequence of bytes. On Unix 08279 * platforms, see <code>ioctl(2)</code> for details. Not implemented on 08280 * all platforms. 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 * call-seq: 08365 * ios.fcntl(integer_cmd, arg) -> integer 08366 * 08367 * Provides a mechanism for issuing low-level commands to control or 08368 * query file-oriented I/O streams. Arguments and results are platform 08369 * dependent. If <i>arg</i> is a number, its value is passed 08370 * directly. If it is a string, it is interpreted as a binary sequence 08371 * of bytes (<code>Array#pack</code> might be a useful way to build this 08372 * string). On Unix platforms, see <code>fcntl(2)</code> for details. 08373 * Not implemented on all platforms. 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 * call-seq: 08391 * syscall(num [, args...]) -> integer 08392 * 08393 * Calls the operating system function identified by _num_ and 08394 * returns the result of the function or raises SystemCallError if 08395 * it failed. 08396 * 08397 * Arguments for the function can follow _num_. They must be either 08398 * +String+ objects or +Integer+ objects. A +String+ object is passed 08399 * as a pointer to the byte sequence. An +Integer+ object is passed 08400 * as an integer whose bit size is same as a pointer. 08401 * Up to nine parameters may be passed (14 on the Atari-ST). 08402 * 08403 * The function identified by _num_ is system 08404 * dependent. On some Unix systems, the numbers may be obtained from a 08405 * header file called <code>syscall.h</code>. 08406 * 08407 * syscall 4, 1, "hello\n", 6 # '4' is write(2) on our box 08408 * 08409 * <em>produces:</em> 08410 * 08411 * hello 08412 * 08413 * 08414 * Calling +syscall+ on a platform which does not have any way to 08415 * an arbitrary system function just fails with NotImplementedError. 08416 * 08417 * Note:: 08418 * +syscall+ is essentially unsafe and unportable. Feel free to shoot your foot. 08419 * DL (Fiddle) library is preferred for safer and a bit more portable programming. 08420 */ 08421 08422 static VALUE 08423 rb_f_syscall(int argc, VALUE *argv) 08424 { 08425 #ifdef atarist 08426 VALUE arg[13]; /* yes, we really need that many ! */ 08427 #else 08428 VALUE arg[8]; 08429 #endif 08430 #if SIZEOF_VOIDP == 8 && defined(HAVE___SYSCALL) && SIZEOF_INT != 8 /* mainly *BSD */ 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 * Linux man page says, syscall(2) function prototype is below. 08447 * 08448 * int syscall(int number, ...); 08449 * 08450 * But, it's incorrect. Actual one takes and returned long. (see unistd.h) 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 /* Special case - "-" => no transcoding */ 08567 enc = enc2; 08568 enc2 = NULL; 08569 } 08570 else 08571 enc = rb_to_encoding(v2); 08572 if (enc == enc2) { 08573 /* Special case - "-" => no transcoding */ 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 /* Set to default encodings */ 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 * call-seq: 08621 * IO.pipe -> [read_io, write_io] 08622 * IO.pipe(ext_enc) -> [read_io, write_io] 08623 * IO.pipe("ext_enc:int_enc" [, opt]) -> [read_io, write_io] 08624 * IO.pipe(ext_enc, int_enc [, opt]) -> [read_io, write_io] 08625 * 08626 * IO.pipe(...) {|read_io, write_io| ... } 08627 * 08628 * Creates a pair of pipe endpoints (connected to each other) and 08629 * returns them as a two-element array of <code>IO</code> objects: 08630 * <code>[</code> <i>read_io</i>, <i>write_io</i> <code>]</code>. 08631 * 08632 * If a block is given, the block is called and 08633 * returns the value of the block. 08634 * <i>read_io</i> and <i>write_io</i> are sent to the block as arguments. 08635 * If read_io and write_io are not closed when the block exits, they are closed. 08636 * i.e. closing read_io and/or write_io doesn't cause an error. 08637 * 08638 * Not available on all platforms. 08639 * 08640 * If an encoding (encoding name or encoding object) is specified as an optional argument, 08641 * read string from pipe is tagged with the encoding specified. 08642 * If the argument is a colon separated two encoding names "A:B", 08643 * the read string is converted from encoding A (external encoding) 08644 * to encoding B (internal encoding), then tagged with B. 08645 * If two optional arguments are specified, those must be 08646 * encoding objects or encoding names, 08647 * and the first one is the external encoding, 08648 * and the second one is the internal encoding. 08649 * If the external encoding and the internal encoding is specified, 08650 * optional hash argument specify the conversion option. 08651 * 08652 * In the example below, the two processes close the ends of the pipe 08653 * that they are not using. This is not just a cosmetic nicety. The 08654 * read end of a pipe will not generate an end of file condition if 08655 * there are any writers with the pipe still open. In the case of the 08656 * parent process, the <code>rd.read</code> will never return if it 08657 * does not first issue a <code>wr.close</code>. 08658 * 08659 * rd, wr = IO.pipe 08660 * 08661 * if fork 08662 * wr.close 08663 * puts "Parent got: <#{rd.read}>" 08664 * rd.close 08665 * Process.wait 08666 * else 08667 * rd.close 08668 * puts "Sending message to parent" 08669 * wr.write "Hi Dad" 08670 * wr.close 08671 * end 08672 * 08673 * <em>produces:</em> 08674 * 08675 * Sending message to parent 08676 * Parent got: <Hi Dad> 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); /* prevent from GC */ 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 * call-seq: 08802 * IO.foreach(name, sep=$/ [, open_args]) {|line| block } -> nil 08803 * IO.foreach(name, limit [, open_args]) {|line| block } -> nil 08804 * IO.foreach(name, sep, limit [, open_args]) {|line| block } -> nil 08805 * IO.foreach(...) -> an_enumerator 08806 * 08807 * Executes the block for every line in the named I/O port, where lines 08808 * are separated by <em>sep</em>. 08809 * 08810 * If no block is given, an enumerator is returned instead. 08811 * 08812 * IO.foreach("testfile") {|x| print "GOT ", x } 08813 * 08814 * <em>produces:</em> 08815 * 08816 * GOT This is line one 08817 * GOT This is line two 08818 * GOT This is line three 08819 * GOT And so on... 08820 * 08821 * If the last argument is a hash, it's the keyword argument to open. 08822 * See <code>IO.read</code> for detail. 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 * call-seq: 08848 * IO.readlines(name, sep=$/ [, open_args]) -> array 08849 * IO.readlines(name, limit [, open_args]) -> array 08850 * IO.readlines(name, sep, limit [, open_args]) -> array 08851 * 08852 * Reads the entire file specified by <i>name</i> as individual 08853 * lines, and returns those lines in an array. Lines are separated by 08854 * <i>sep</i>. 08855 * 08856 * a = IO.readlines("testfile") 08857 * a[0] #=> "This is line one\n" 08858 * 08859 * If the last argument is a hash, it's the keyword argument to open. 08860 * See <code>IO.read</code> for detail. 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 * call-seq: 08898 * IO.read(name, [length [, offset]] ) -> string 08899 * IO.read(name, [length [, offset]], open_args) -> string 08900 * 08901 * Opens the file, optionally seeks to the given <i>offset</i>, then returns 08902 * <i>length</i> bytes (defaulting to the rest of the file). 08903 * <code>read</code> ensures the file is closed before returning. 08904 * 08905 * If the last argument is a hash, it specifies option for internal 08906 * open(). The key would be the following. open_args: is exclusive 08907 * to others. 08908 * 08909 * encoding: string or encoding 08910 * 08911 * specifies encoding of the read string. encoding will be ignored 08912 * if length is specified. 08913 * 08914 * mode: string 08915 * 08916 * specifies mode argument for open(). it should start with "r" 08917 * otherwise it would cause error. 08918 * 08919 * open_args: array of strings 08920 * 08921 * specifies arguments for open() as an array. 08922 * 08923 * IO.read("testfile") #=> "This is line one\nThis is line two\nThis is line three\nAnd so on...\n" 08924 * IO.read("testfile", 20) #=> "This is line one\nThi" 08925 * IO.read("testfile", 20, 10) #=> "ne one\nThis is line " 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 * call-seq: 08955 * IO.binread(name, [length [, offset]] ) -> string 08956 * 08957 * Opens the file, optionally seeks to the given <i>offset</i>, then returns 08958 * <i>length</i> bytes (defaulting to the rest of the file). 08959 * <code>binread</code> ensures the file is closed before returning. 08960 * The open mode would be "rb:ASCII-8BIT". 08961 * 08962 * IO.binread("testfile") #=> "This is line one\nThis is line two\nThis is line three\nAnd so on...\n" 08963 * IO.binread("testfile", 20) #=> "This is line one\nThi" 08964 * IO.binread("testfile", 20, 10) #=> "ne one\nThis is line " 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 * call-seq: 09041 * IO.write(name, string, [offset] ) => fixnum 09042 * IO.write(name, string, [offset], open_args ) => fixnum 09043 * 09044 * Opens the file, optionally seeks to the given <i>offset</i>, writes 09045 * <i>string</i>, then returns the length written. 09046 * <code>write</code> ensures the file is closed before returning. 09047 * If <i>offset</i> is not given, the file is truncated. Otherwise, 09048 * it is not truncated. 09049 * 09050 * If the last argument is a hash, it specifies option for internal 09051 * open(). The key would be the following. open_args: is exclusive 09052 * to others. 09053 * 09054 * encoding: string or encoding 09055 * 09056 * specifies encoding of the read string. encoding will be ignored 09057 * if length is specified. 09058 * 09059 * mode: string 09060 * 09061 * specifies mode argument for open(). it should start with "w" or "a" or "r+" 09062 * otherwise it would cause error. 09063 * 09064 * perm: fixnum 09065 * 09066 * specifies perm argument for open(). 09067 * 09068 * open_args: array 09069 * 09070 * specifies arguments for open() as an array. 09071 * 09072 * IO.write("testfile", "0123456789", 20) # => 10 09073 * # File could contain: "This is line one\nThi0123456789two\nThis is line three\nAnd so on...\n" 09074 * IO.write("testfile", "0123456789") #=> 10 09075 * # File would now read: "0123456789" 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 * call-seq: 09086 * IO.binwrite(name, string, [offset] ) => fixnum 09087 * 09088 * Opens the file, optionally seeks to the given <i>offset</i>, writes 09089 * <i>string</i> then returns the length written. 09090 * <code>binwrite</code> ensures the file is closed before returning. 09091 * The open mode would be "wb:ASCII-8BIT". 09092 * If <i>offset</i> is not given, the file is truncated. Otherwise, 09093 * it is not truncated. 09094 * 09095 * IO.binwrite("testfile", "0123456789", 20) # => 10 09096 * # File could contain: "This is line one\nThi0123456789two\nThis is line three\nAnd so on...\n" 09097 * IO.binwrite("testfile", "0123456789") #=> 10 09098 * # File would now read: "0123456789" 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; /* (off_t)-1 if not specified */ 09111 off_t src_offset; /* (off_t)-1 if not specified */ 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 * returns TRUE if the preceding system call was interrupted 09135 * so we can continue. If the thread was interrupted, we 09136 * reacquire the GVL to execute interrupts before continuing. 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(__FreeBSD__) || defined(__DragonFly__) */ || defined(__APPLE__) 09220 /* This runs on FreeBSD8.1 r30210, but sendfiles blocks its execution 09221 * without cpuset -l 0. 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 /* we are limited by the 32-bit ssize_t return value on 32-bit */ 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 * Linux requires stp->src_fd to be a mmap-able (regular) file, 09341 * select() reports regular files to always be "ready", so 09342 * there is no need to select() on it. 09343 * Other OSes may have the same limitation for sendfile() which 09344 * allow us to bypass maygvl_copy_stream_wait_read()... 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) /* EOF or error */ 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; /* error or success */ 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) { /* IO or filename */ 09674 if (io_binwrite(str, RSTRING_PTR(str), RSTRING_LEN(str), dst_fptr, 0) < 0) 09675 rb_sys_fail(0); 09676 } 09677 else /* others such as StringIO */ 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 * call-seq: 09724 * IO.copy_stream(src, dst) 09725 * IO.copy_stream(src, dst, copy_length) 09726 * IO.copy_stream(src, dst, copy_length, src_offset) 09727 * 09728 * IO.copy_stream copies <i>src</i> to <i>dst</i>. 09729 * <i>src</i> and <i>dst</i> is either a filename or an IO. 09730 * 09731 * This method returns the number of bytes copied. 09732 * 09733 * If optional arguments are not given, 09734 * the start position of the copy is 09735 * the beginning of the filename or 09736 * the current file offset of the IO. 09737 * The end position of the copy is the end of file. 09738 * 09739 * If <i>copy_length</i> is given, 09740 * No more than <i>copy_length</i> bytes are copied. 09741 * 09742 * If <i>src_offset</i> is given, 09743 * it specifies the start position of the copy. 09744 * 09745 * When <i>src_offset</i> is specified and 09746 * <i>src</i> is an IO, 09747 * IO.copy_stream doesn't move the current file offset. 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 * call-seq: 09781 * io.external_encoding -> encoding 09782 * 09783 * Returns the Encoding object that represents the encoding of the file. 09784 * If io is write mode and no encoding is specified, returns <code>nil</code>. 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 * call-seq: 09806 * io.internal_encoding -> encoding 09807 * 09808 * Returns the Encoding of the internal string if conversion is 09809 * specified. Otherwise returns nil. 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 * call-seq: 09824 * io.set_encoding(ext_enc) -> io 09825 * io.set_encoding("ext_enc:int_enc") -> io 09826 * io.set_encoding(ext_enc, int_enc) -> io 09827 * io.set_encoding("ext_enc:int_enc", opt) -> io 09828 * io.set_encoding(ext_enc, int_enc, opt) -> io 09829 * 09830 * If single argument is specified, read string from io is tagged 09831 * with the encoding specified. If encoding is a colon separated two 09832 * encoding names "A:B", the read string is converted from encoding A 09833 * (external encoding) to encoding B (internal encoding), then tagged 09834 * with B. If two arguments are specified, those must be encoding 09835 * objects or encoding names, and the first one is the external encoding, and the 09836 * second one is the internal encoding. 09837 * If the external encoding and the internal encoding is specified, 09838 * optional hash argument specify the conversion option. 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 * call-seq: 09870 * ARGF.external_encoding -> encoding 09871 * 09872 * Returns the external encoding for files read from +ARGF+ as an +Encoding+ 09873 * object. The external encoding is the encoding of the text as stored in a 09874 * file. Contrast with +ARGF.internal_encoding+, which is the encoding used 09875 * to represent this text within Ruby. 09876 * 09877 * To set the external encoding use +ARGF.set_encoding+. 09878 * 09879 * For example: 09880 * 09881 * ARGF.external_encoding #=> #<Encoding:UTF-8> 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 * call-seq: 09895 * ARGF.internal_encoding -> encoding 09896 * 09897 * Returns the internal encoding for strings read from +ARGF+ as an 09898 * +Encoding+ object. 09899 * 09900 * If +ARGF.set_encoding+ has been called with two encoding names, the second 09901 * is returned. Otherwise, if +Encoding.default_external+ has been set, that 09902 * value is returned. Failing that, if a default external encoding was 09903 * specified on the command-line, that value is used. If the encoding is 09904 * unknown, nil is returned. 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 * call-seq: 09917 * ARGF.set_encoding(ext_enc) -> ARGF 09918 * ARGF.set_encoding("ext_enc:int_enc") -> ARGF 09919 * ARGF.set_encoding(ext_enc, int_enc) -> ARGF 09920 * ARGF.set_encoding("ext_enc:int_enc", opt) -> ARGF 09921 * ARGF.set_encoding(ext_enc, int_enc, opt) -> ARGF 09922 * 09923 * If single argument is specified, strings read from ARGF are tagged with 09924 * the encoding specified. 09925 * 09926 * If two encoding names separated by a colon are given, e.g. "ascii:utf-8", 09927 * the read string is converted from the first encoding (external encoding) 09928 * to the second encoding (internal encoding), then tagged with the second 09929 * encoding. 09930 * 09931 * If two arguments are specified, they must be encoding objects or encoding 09932 * names. Again, the first specifies the external encoding; the second 09933 * specifies the internal encoding. 09934 * 09935 * If the external encoding and the internal encoding are specified, the 09936 * optional +Hash+ argument can be used to adjust the conversion process. The 09937 * structure of this hash is explained in the +String#encode+ documentation. 09938 * 09939 * For example: 09940 * 09941 * ARGF.set_encoding('ascii') # Tag the input as US-ASCII text 09942 * ARGF.set_encoding(Encoding::UTF_8) # Tag the input as UTF-8 text 09943 * ARGF.set_encoding('utf-8','ascii') # Transcode the input from US-ASCII 09944 * # to UTF-8. 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 * call-seq: 09962 * ARGF.tell -> Integer 09963 * ARGF.pos -> Integer 09964 * 09965 * Returns the current offset (in bytes) of the current file in +ARGF+. 09966 * 09967 * ARGF.pos #=> 0 09968 * ARGF.gets #=> "This is line one\n" 09969 * ARGF.pos #=> 17 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 * call-seq: 09984 * ARGF.seek(amount, whence=IO::SEEK_SET) -> 0 09985 * 09986 * Seeks to offset _amount_ (an +Integer+) in the +ARGF+ stream according to 09987 * the value of _whence_. See +IO#seek+ for further details. 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 * call-seq: 10001 * ARGF.pos = position -> Integer 10002 * 10003 * Seeks to the position given by _position_ (in bytes) in +ARGF+. 10004 * 10005 * For example: 10006 * 10007 * ARGF.pos = 17 10008 * ARGF.gets #=> "This is line two\n" 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 * call-seq: 10022 * ARGF.rewind -> 0 10023 * 10024 * Positions the current file to the beginning of input, resetting 10025 * +ARGF.lineno+ to zero. 10026 * 10027 * ARGF.readline #=> "This is line one\n" 10028 * ARGF.rewind #=> 0 10029 * ARGF.lineno #=> 0 10030 * ARGF.readline #=> "This is line one\n" 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 * call-seq: 10044 * ARGF.fileno -> fixnum 10045 * ARGF.to_i -> fixnum 10046 * 10047 * Returns an integer representing the numeric file descriptor for 10048 * the current file. Raises an +ArgumentError+ if there isn't a current file. 10049 * 10050 * ARGF.fileno #=> 3 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 * call-seq: 10064 * ARGF.to_io -> IO 10065 * 10066 * Returns an +IO+ object representing the current file. This will be a 10067 * +File+ object unless the current file is a stream such as STDIN. 10068 * 10069 * For example: 10070 * 10071 * ARGF.to_io #=> #<File:glark.txt> 10072 * ARGF.to_io #=> #<IO:<STDIN>> 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 * call-seq: 10084 * ARGF.eof? -> true or false 10085 * ARGF.eof -> true or false 10086 * 10087 * Returns true if the current file in +ARGF+ is at end of file, i.e. it has 10088 * no data to read. The stream must be opened for reading or an +IOError+ 10089 * will be raised. 10090 * 10091 * $ echo "eof" | ruby argf.rb 10092 * 10093 * ARGF.eof? #=> false 10094 * 3.times { ARGF.readchar } 10095 * ARGF.eof? #=> false 10096 * ARGF.readchar #=> "\n" 10097 * ARGF.eof? #=> true 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 * call-seq: 10117 * ARGF.read([length [, buffer]]) -> string, buffer, or nil 10118 * 10119 * Reads _length_ bytes from ARGF. The files named on the command line 10120 * are concatenated and treated as a single file by this method, so when 10121 * called without arguments the contents of this pseudo file are returned in 10122 * their entirety. 10123 * 10124 * _length_ must be a non-negative integer or nil. If it is a positive 10125 * integer, +read+ tries to read at most _length_ bytes. It returns nil 10126 * if an EOF was encountered before anything could be read. Fewer than 10127 * _length_ bytes may be returned if an EOF is encountered during the read. 10128 * 10129 * If _length_ is omitted or is _nil_, it reads until EOF. A String is 10130 * returned even if EOF is encountered before any data is read. 10131 * 10132 * If _length_ is zero, it returns _""_. 10133 * 10134 * If the optional _buffer_ argument is present, it must reference a String, 10135 * which will receive the data. 10136 * 10137 * For example: 10138 * 10139 * $ echo "small" > small.txt 10140 * $ echo "large" > large.txt 10141 * $ ./glark.rb small.txt large.txt 10142 * 10143 * ARGF.read #=> "small\nlarge" 10144 * ARGF.read(200) #=> "small\nlarge" 10145 * ARGF.read(2) #=> "sm" 10146 * ARGF.read(0) #=> "" 10147 * 10148 * Note that this method behaves like fread() function in C. If you need the 10149 * behavior like read(2) system call, consider +ARGF.readpartial+. 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 * call-seq: 10215 * ARGF.readpartial(maxlen) -> string 10216 * ARGF.readpartial(maxlen, outbuf) -> outbuf 10217 * 10218 * Reads at most _maxlen_ bytes from the ARGF stream. It blocks only if 10219 * +ARGF+ has no data immediately available. If the optional _outbuf_ 10220 * argument is present, it must reference a String, which will receive the 10221 * data. It raises <code>EOFError</code> on end of file. 10222 * 10223 * +readpartial+ is designed for streams such as pipes, sockets, and ttys. It 10224 * blocks only when no data is immediately available. This means that it 10225 * blocks only when following all conditions hold: 10226 * 10227 * * The byte buffer in the +IO+ object is empty. 10228 * * The content of the stream is empty. 10229 * * The stream has not reached EOF. 10230 * 10231 * When +readpartial+ blocks, it waits for data or EOF. If some data is read, 10232 * +readpartial+ returns with the data. If EOF is reached, readpartial raises 10233 * an +EOFError+. 10234 * 10235 * When +readpartial+ doesn't block, it returns or raises immediately. If 10236 * the byte buffer is not empty, it returns the data in the buffer. Otherwise, if 10237 * the stream has some content, it returns the data in the stream. If the 10238 * stream reaches EOF an +EOFError+ is raised. 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 * call-seq: 10249 * ARGF.read_nonblock(maxlen) -> string 10250 * ARGF.read_nonblock(maxlen, outbuf) -> outbuf 10251 * 10252 * Reads at most _maxlen_ bytes from the ARGF stream in non-blocking mode. 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 * call-seq: 10304 * ARGF.getc -> String or nil 10305 * 10306 * Reads the next character from +ARGF+ and returns it as a +String+. Returns 10307 * +nil+ at the end of the stream. 10308 * 10309 * +ARGF+ treats the files named on the command line as a single file created 10310 * by concatenating their contents. After returning the last character of the 10311 * first file, it returns the first character of the second file, and so on. 10312 * 10313 * For example: 10314 * 10315 * $ echo "foo" > file 10316 * $ ruby argf.rb file 10317 * 10318 * ARGF.getc #=> "f" 10319 * ARGF.getc #=> "o" 10320 * ARGF.getc #=> "o" 10321 * ARGF.getc #=> "\n" 10322 * ARGF.getc #=> nil 10323 * ARGF.getc #=> nil 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 * call-seq: 10349 * ARGF.getbyte -> Fixnum or nil 10350 * 10351 * Gets the next 8-bit byte (0..255) from +ARGF+. Returns +nil+ if called at 10352 * the end of the stream. 10353 * 10354 * For example: 10355 * 10356 * $ echo "foo" > file 10357 * $ ruby argf.rb file 10358 * 10359 * ARGF.getbyte #=> 102 10360 * ARGF.getbyte #=> 111 10361 * ARGF.getbyte #=> 111 10362 * ARGF.getbyte #=> 10 10363 * ARGF.getbyte #=> nil 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 * call-seq: 10389 * ARGF.readchar -> String or nil 10390 * 10391 * Reads the next character from +ARGF+ and returns it as a +String+. Raises 10392 * an +EOFError+ after the last character of the last file has been read. 10393 * 10394 * For example: 10395 * 10396 * $ echo "foo" > file 10397 * $ ruby argf.rb file 10398 * 10399 * ARGF.readchar #=> "f" 10400 * ARGF.readchar #=> "o" 10401 * ARGF.readchar #=> "o" 10402 * ARGF.readchar #=> "\n" 10403 * ARGF.readchar #=> end of file reached (EOFError) 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 * call-seq: 10429 * ARGF.readbyte -> Fixnum 10430 * 10431 * Reads the next 8-bit byte from ARGF and returns it as a +Fixnum+. Raises 10432 * an +EOFError+ after the last byte of the last file has been read. 10433 * 10434 * For example: 10435 * 10436 * $ echo "foo" > file 10437 * $ ruby argf.rb file 10438 * 10439 * ARGF.readbyte #=> 102 10440 * ARGF.readbyte #=> 111 10441 * ARGF.readbyte #=> 111 10442 * ARGF.readbyte #=> 10 10443 * ARGF.readbyte #=> end of file reached (EOFError) 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 * call-seq: 10460 * ARGF.each(sep=$/) {|line| block } -> ARGF 10461 * ARGF.each(sep=$/,limit) {|line| block } -> ARGF 10462 * ARGF.each(...) -> an_enumerator 10463 * 10464 * ARGF.each_line(sep=$/) {|line| block } -> ARGF 10465 * ARGF.each_line(sep=$/,limit) {|line| block } -> ARGF 10466 * ARGF.each_line(...) -> an_enumerator 10467 * 10468 * ARGF.lines(sep=$/) {|line| block } -> ARGF 10469 * ARGF.lines(sep=$/,limit) {|line| block } -> ARGF 10470 * ARGF.lines(...) -> an_enumerator 10471 * 10472 * Returns an enumerator which iterates over each line (separated by _sep_, 10473 * which defaults to your platform's newline character) of each file in 10474 * +ARGV+. If a block is supplied, each line in turn will be yielded to the 10475 * block, otherwise an enumerator is returned. 10476 * The optional _limit_ argument is a +Fixnum+ specifying the maximum 10477 * length of each line; longer lines will be split according to this limit. 10478 * 10479 * This method allows you to treat the files supplied on the command line as 10480 * a single file consisting of the concatenation of each named file. After 10481 * the last line of the first file has been returned, the first line of the 10482 * second file is returned. The +ARGF.filename+ and +ARGF.lineno+ methods can 10483 * be used to determine the filename and line number, respectively, of the 10484 * current line. 10485 * 10486 * For example, the following code prints out each line of each named file 10487 * prefixed with its line number, displaying the filename once per file: 10488 * 10489 * ARGF.lines do |line| 10490 * puts ARGF.filename if ARGF.lineno == 1 10491 * puts "#{ARGF.lineno}: #{line}" 10492 * end 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 * call-seq: 10507 * ARGF.bytes {|byte| block } -> ARGF 10508 * ARGF.bytes -> an_enumerator 10509 * 10510 * ARGF.each_byte {|byte| block } -> ARGF 10511 * ARGF.each_byte -> an_enumerator 10512 * 10513 * Iterates over each byte of each file in +ARGV+. 10514 * A byte is returned as a +Fixnum+ in the range 0..255. 10515 * 10516 * This method allows you to treat the files supplied on the command line as 10517 * a single file consisting of the concatenation of each named file. After 10518 * the last byte of the first file has been returned, the first byte of the 10519 * second file is returned. The +ARGF.filename+ method can be used to 10520 * determine the filename of the current byte. 10521 * 10522 * If no block is given, an enumerator is returned instead. 10523 * 10524 * For example: 10525 * 10526 * ARGF.bytes.to_a #=> [35, 32, ... 95, 10] 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 * call-seq: 10542 * ARGF.chars {|char| block } -> ARGF 10543 * ARGF.chars -> an_enumerator 10544 * 10545 * ARGF.each_char {|char| block } -> ARGF 10546 * ARGF.each_char -> an_enumerator 10547 * 10548 * Iterates over each character of each file in +ARGF+. 10549 * 10550 * This method allows you to treat the files supplied on the command line as 10551 * a single file consisting of the concatenation of each named file. After 10552 * the last character of the first file has been returned, the first 10553 * character of the second file is returned. The +ARGF.filename+ method can 10554 * be used to determine the name of the file in which the current character 10555 * appears. 10556 * 10557 * If no block is given, an enumerator is returned instead. 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 * call-seq: 10572 * ARGF.filename -> String 10573 * ARGF.path -> String 10574 * 10575 * Returns the current filename. "-" is returned when the current file is 10576 * STDIN. 10577 * 10578 * For example: 10579 * 10580 * $ echo "foo" > foo 10581 * $ echo "bar" > bar 10582 * $ echo "glark" > glark 10583 * 10584 * $ ruby argf.rb foo bar glark 10585 * 10586 * ARGF.filename #=> "foo" 10587 * ARGF.read(5) #=> "foo\nb" 10588 * ARGF.filename #=> "bar" 10589 * ARGF.skip 10590 * ARGF.filename #=> "glark" 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 * call-seq: 10607 * ARGF.file -> IO or File object 10608 * 10609 * Returns the current file as an +IO+ or +File+ object. #<IO:<STDIN>> is 10610 * returned when the current file is STDIN. 10611 * 10612 * For example: 10613 * 10614 * $ echo "foo" > foo 10615 * $ echo "bar" > bar 10616 * 10617 * $ ruby argf.rb foo bar 10618 * 10619 * ARGF.file #=> #<File:foo> 10620 * ARGF.read(5) #=> "foo\nb" 10621 * ARGF.file #=> #<File:bar> 10622 */ 10623 static VALUE 10624 argf_file(VALUE argf) 10625 { 10626 next_argv(); 10627 return ARGF.current_file; 10628 } 10629 10630 /* 10631 * call-seq: 10632 * ARGF.binmode -> ARGF 10633 * 10634 * Puts +ARGF+ into binary mode. Once a stream is in binary mode, it cannot 10635 * be reset to non-binary mode. This option has the following effects: 10636 * 10637 * * Newline conversion is disabled. 10638 * * Encoding conversion is disabled. 10639 * * Content is treated as ASCII-8BIT. 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 * call-seq: 10653 * ARGF.binmode? -> true or false 10654 * 10655 * Returns true if +ARGF+ is being read in binary mode; false otherwise. (To 10656 * enable binary mode use +ARGF.binmode+. 10657 * 10658 * For example: 10659 * 10660 * ARGF.binmode? #=> false 10661 * ARGF.binmode 10662 * ARGF.binmode? #=> true 10663 */ 10664 static VALUE 10665 argf_binmode_p(VALUE argf) 10666 { 10667 return ARGF.binmode ? Qtrue : Qfalse; 10668 } 10669 10670 /* 10671 * call-seq: 10672 * ARGF.skip -> ARGF 10673 * 10674 * Sets the current file to the next file in ARGV. If there aren't any more 10675 * files it has no effect. 10676 * 10677 * For example: 10678 * 10679 * $ ruby argf.rb foo bar 10680 * ARGF.filename #=> "foo" 10681 * ARGF.skip 10682 * ARGF.filename #=> "bar" 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 * call-seq: 10696 * ARGF.close -> ARGF 10697 * 10698 * Closes the current file and skips to the next in the stream. Trying to 10699 * close a file that has already been closed causes an +IOError+ to be 10700 * raised. 10701 * 10702 * For example: 10703 * 10704 * $ ruby argf.rb foo bar 10705 * 10706 * ARGF.filename #=> "foo" 10707 * ARGF.close 10708 * ARGF.filename #=> "bar" 10709 * ARGF.close 10710 * ARGF.close #=> closed stream (IOError) 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 * call-seq: 10726 * ARGF.closed? -> true or false 10727 * 10728 * Returns _true_ if the current file has been closed; _false_ otherwise. Use 10729 * +ARGF.close+ to actually close the current file. 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 * call-seq: 10741 * ARGF.to_s -> String 10742 * 10743 * Returns "ARGF". 10744 */ 10745 static VALUE 10746 argf_to_s(VALUE argf) 10747 { 10748 return rb_str_new2("ARGF"); 10749 } 10750 10751 /* 10752 * call-seq: 10753 * ARGF.inplace_mode -> String 10754 * 10755 * Returns the file extension appended to the names of modified files under 10756 * inplace-edit mode. This value can be set using +ARGF.inplace_mode=+ or 10757 * passing the +-i+ switch to the Ruby binary. 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 * call-seq: 10774 * ARGF.inplace_mode = ext -> ARGF 10775 * 10776 * Sets the filename extension for inplace editing mode to the given String. 10777 * Each file being edited has this value appended to its filename. The 10778 * modified file is saved under this new name. 10779 * 10780 * For example: 10781 * 10782 * $ ruby argf.rb file.txt 10783 * 10784 * ARGF.inplace_mode = '.bak' 10785 * ARGF.lines do |line| 10786 * print line.sub("foo","bar") 10787 * end 10788 * 10789 * Each line of _file.txt_ has the first occurrence of "foo" replaced with 10790 * "bar", then the new line is written out to _file.txt.bak_. 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 * call-seq: 10833 * ARGF.argv -> ARGV 10834 * 10835 * Returns the +ARGV+ array, which contains the arguments passed to your 10836 * script, one per element. 10837 * 10838 * For example: 10839 * 10840 * $ ruby argf.rb -v glark.txt 10841 * 10842 * ARGF.argv #=> ["-v", "glark.txt"] 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 * call-seq: 10865 * ARGF.to_write_io -> io 10866 * 10867 * Returns IO instance tied to _ARGF_ for writing if inplace mode is 10868 * enabled. 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 * call-seq: 10881 * ARGF.write(string) -> integer 10882 * 10883 * Writes _string_ if inplace mode. 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 * Document-class: IOError 10893 * 10894 * Raised when an IO operation fails. 10895 * 10896 * File.open("/etc/hosts") {|f| f << "example"} 10897 * #=> IOError: not opened for writing 10898 * 10899 * File.open("/etc/hosts") {|f| f.close; f.read } 10900 * #=> IOError: closed stream 10901 * 10902 * Note that some IO failures raise +SystemCallError+s and these are not 10903 * subclasses of IOError: 10904 * 10905 * File.open("does/not/exist") 10906 * #=> Errno::ENOENT: No such file or directory - does/not/exist 10907 */ 10908 10909 /* 10910 * Document-class: EOFError 10911 * 10912 * Raised by some IO operations when reaching the end of file. Many IO 10913 * methods exist in two forms, 10914 * 10915 * one that returns +nil+ when the end of file is reached, the other 10916 * raises EOFError +EOFError+. 10917 * 10918 * +EOFError+ is a subclass of +IOError+. 10919 * 10920 * file = File.open("/etc/hosts") 10921 * file.read 10922 * file.gets #=> nil 10923 * file.readline #=> EOFError: end of file reached 10924 */ 10925 10926 /* 10927 * Document-class: ARGF 10928 * 10929 * +ARGF+ is a stream designed for use in scripts that process files given as 10930 * command-line arguments or passed in via STDIN. 10931 * 10932 * The arguments passed to your script are stored in the +ARGV+ Array, one 10933 * argument per element. +ARGF+ assumes that any arguments that aren't 10934 * filenames have been removed from +ARGV+. For example: 10935 * 10936 * $ ruby argf.rb --verbose file1 file2 10937 * 10938 * ARGV #=> ["--verbose", "file1", "file2"] 10939 * option = ARGV.shift #=> "--verbose" 10940 * ARGV #=> ["file1", "file2"] 10941 * 10942 * You can now use +ARGF+ to work with a concatenation of each of these named 10943 * files. For instance, +ARGF.read+ will return the contents of _file1_ 10944 * followed by the contents of _file2_. 10945 * 10946 * After a file in +ARGV+ has been read +ARGF+ removes it from the Array. 10947 * Thus, after all files have been read +ARGV+ will be empty. 10948 * 10949 * You can manipulate +ARGV+ yourself to control what +ARGF+ operates on. If 10950 * you remove a file from +ARGV+, it is ignored by +ARGF+; if you add files to 10951 * +ARGV+, they are treated as if they were named on the command line. For 10952 * example: 10953 * 10954 * ARGV.replace ["file1"] 10955 * ARGF.readlines # Returns the contents of file1 as an Array 10956 * ARGV #=> [] 10957 * ARGV.replace ["file2", "file3"] 10958 * ARGF.read # Returns the contents of file2 and file3 10959 * 10960 * If +ARGV+ is empty, +ARGF+ acts as if it contained STDIN, i.e. the data 10961 * piped to your script. For example: 10962 * 10963 * $ echo "glark" | ruby -e 'p ARGF.read' 10964 * "glark\n" 10965 */ 10966 10967 /* 10968 * Class <code>IO</code> is the basis for all input and output in Ruby. 10969 * An I/O stream may be <em>duplexed</em> (that is, bidirectional), and 10970 * so may use more than one native operating system stream. 10971 * 10972 * Many of the examples in this section use class <code>File</code>, 10973 * the only standard subclass of <code>IO</code>. The two classes are 10974 * closely associated. 10975 * 10976 * As used in this section, <em>portname</em> may take any of the 10977 * following forms. 10978 * 10979 * * A plain string represents a filename suitable for the underlying 10980 * operating system. 10981 * 10982 * * A string starting with ``<code>|</code>'' indicates a subprocess. 10983 * The remainder of the string following the ``<code>|</code>'' is 10984 * invoked as a process with appropriate input/output channels 10985 * connected to it. 10986 * 10987 * * A string equal to ``<code>|-</code>'' will create another Ruby 10988 * instance as a subprocess. 10989 * 10990 * Ruby will convert pathnames between different operating system 10991 * conventions if possible. For instance, on a Windows system the 10992 * filename ``<code>/gumby/ruby/test.rb</code>'' will be opened as 10993 * ``<code>\gumby\ruby\test.rb</code>''. When specifying a 10994 * Windows-style filename in a Ruby string, remember to escape the 10995 * backslashes: 10996 * 10997 * "c:\\gumby\\ruby\\test.rb" 10998 * 10999 * Our examples here will use the Unix-style forward slashes; 11000 * <code>File::SEPARATOR</code> can be used to get the 11001 * platform-specific separator character. 11002 * 11003 * I/O ports may be opened in any one of several different modes, which 11004 * are shown in this section as <em>mode</em>. The mode may 11005 * either be a Fixnum or a String. If numeric, it should be 11006 * one of the operating system specific constants (O_RDONLY, 11007 * O_WRONLY, O_RDWR, O_APPEND and so on). See man open(2) for 11008 * more information. 11009 * 11010 * If the mode is given as a String, it must be one of the 11011 * values listed in the following table. 11012 * 11013 * Mode | Meaning 11014 * -----+-------------------------------------------------------- 11015 * "r" | Read-only, starts at beginning of file (default mode). 11016 * -----+-------------------------------------------------------- 11017 * "r+" | Read-write, starts at beginning of file. 11018 * -----+-------------------------------------------------------- 11019 * "w" | Write-only, truncates existing file 11020 * | to zero length or creates a new file for writing. 11021 * -----+-------------------------------------------------------- 11022 * "w+" | Read-write, truncates existing file to zero length 11023 * | or creates a new file for reading and writing. 11024 * -----+-------------------------------------------------------- 11025 * "a" | Write-only, starts at end of file if file exists, 11026 * | otherwise creates a new file for writing. 11027 * -----+-------------------------------------------------------- 11028 * "a+" | Read-write, starts at end of file if file exists, 11029 * | otherwise creates a new file for reading and 11030 * | writing. 11031 * -----+-------------------------------------------------------- 11032 * "b" | Binary file mode (may appear with 11033 * | any of the key letters listed above). 11034 * | Suppresses EOL <-> CRLF conversion on Windows. And 11035 * | sets external encoding to ASCII-8BIT unless explicitly 11036 * | specified. 11037 * -----+-------------------------------------------------------- 11038 * "t" | Text file mode (may appear with 11039 * | any of the key letters listed above except "b"). 11040 * 11041 * 11042 * The global constant ARGF (also accessible as $<) provides an 11043 * IO-like stream which allows access to all files mentioned on the 11044 * command line (or STDIN if no files are mentioned). ARGF provides 11045 * the methods <code>#path</code> and <code>#filename</code> to access 11046 * the name of the file currently being read. 11047 * 11048 * == io/console 11049 * 11050 * The io/console extension provides methods for interacting with the 11051 * console. The console can be accessed from <code>IO.console</code> or 11052 * the standard input/output/error IO objects. 11053 * 11054 * Requiring io/console adds the following methods: 11055 * 11056 * * IO::console 11057 * * IO#raw 11058 * * IO#raw! 11059 * * IO#cooked 11060 * * IO#cooked! 11061 * * IO#getch 11062 * * IO#echo= 11063 * * IO#echo? 11064 * * IO#noecho 11065 * * IO#winsize 11066 * * IO#winsize= 11067 * * IO#iflush 11068 * * IO#ioflush 11069 * * IO#oflush 11070 * 11071 * Example: 11072 * 11073 * require 'io/console' 11074 * rows, columns = $stdin.winsize 11075 * puts "You screen is #{columns} wide and #{rows} tall" 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 /* This is necessary only for forcing rdoc handle File::open */ 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); /* avoid modifying RS_default */ 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 /* Holds the original stdin */ 11268 rb_define_global_const("STDIN", rb_stdin); 11269 /* Holds the original stdout */ 11270 rb_define_global_const("STDOUT", rb_stdout); 11271 /* Holds the original stderr */ 11272 rb_define_global_const("STDERR", rb_stderr); 11273 11274 #if 0 11275 /* Hack to get rdoc to regard ARGF as a class: */ 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 * ARGF is a stream designed for use in scripts that process files given 11351 * as command-line arguments or passed in via STDIN. 11352 * 11353 * See ARGF (the class) for more details. 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 /* open for reading only */ 11373 rb_file_const("RDONLY", INT2FIX(O_RDONLY)); 11374 /* open for writing only */ 11375 rb_file_const("WRONLY", INT2FIX(O_WRONLY)); 11376 /* open for reading and writing */ 11377 rb_file_const("RDWR", INT2FIX(O_RDWR)); 11378 /* append on each write */ 11379 rb_file_const("APPEND", INT2FIX(O_APPEND)); 11380 /* create file if it does not exist */ 11381 rb_file_const("CREAT", INT2FIX(O_CREAT)); 11382 /* error if CREAT and the file exists */ 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 /* do not block on open or for data to become available */ 11389 rb_file_const("NONBLOCK", INT2FIX(O_NONBLOCK)); 11390 #endif 11391 /* truncate size to 0 */ 11392 rb_file_const("TRUNC", INT2FIX(O_TRUNC)); 11393 #ifdef O_NOCTTY 11394 /* not to make opened IO the controlling terminal device */ 11395 rb_file_const("NOCTTY", INT2FIX(O_NOCTTY)); 11396 #endif 11397 #ifndef O_BINARY 11398 # define O_BINARY 0 11399 #endif 11400 /* disable line code conversion and make ASCII-8BIT */ 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 /* do not follow symlinks */ 11413 rb_file_const("NOFOLLOW", INT2FIX(O_NOFOLLOW)); /* FreeBSD, Linux */ 11414 #endif 11415 #ifdef O_NOATIME 11416 /* do not change atime */ 11417 rb_file_const("NOATIME", INT2FIX(O_NOATIME)); /* Linux */ 11418 #endif 11419 #ifdef O_DIRECT 11420 /* Try to minimize cache effects of the I/O to and from this file. */ 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
1.7.6.1