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