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