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