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