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