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