PageRenderTime 339ms CodeModel.GetById 24ms RepoModel.GetById 4ms app.codeStats 1ms

/io.c

https://github.com/diabolo/ruby
C | 10125 lines | 6664 code | 926 blank | 2535 comment | 1551 complexity | 2b17d4671a383515e7a3d8139f578390 MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause
  1. /**********************************************************************
  2. io.c -
  3. $Author$
  4. created at: Fri Oct 15 18:08:59 JST 1993
  5. Copyright (C) 1993-2007 Yukihiro Matsumoto
  6. Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
  7. Copyright (C) 2000 Information-technology Promotion Agency, Japan
  8. **********************************************************************/
  9. #include "ruby/ruby.h"
  10. #include "ruby/io.h"
  11. #include "dln.h"
  12. #include <ctype.h>
  13. #include <errno.h>
  14. #define free(x) xfree(x)
  15. #if defined(DOSISH) || defined(__CYGWIN__)
  16. #include <io.h>
  17. #endif
  18. #include <sys/types.h>
  19. #if defined HAVE_NET_SOCKET_H
  20. # include <net/socket.h>
  21. #elif defined HAVE_SYS_SOCKET_H
  22. # include <sys/socket.h>
  23. #endif
  24. #if defined(__BOW__) || defined(__CYGWIN__) || defined(_WIN32) || defined(__EMX__) || defined(__BEOS__) || defined(__HAIKU__)
  25. # define NO_SAFE_RENAME
  26. #endif
  27. #if defined(__CYGWIN__) || defined(_WIN32)
  28. # define NO_LONG_FNAME
  29. #endif
  30. #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(sun) || defined(_nec_ews)
  31. # define USE_SETVBUF
  32. #endif
  33. #ifdef __QNXNTO__
  34. #include "unix.h"
  35. #endif
  36. #include <sys/types.h>
  37. #if defined(HAVE_SYS_IOCTL_H) && !defined(_WIN32)
  38. #include <sys/ioctl.h>
  39. #endif
  40. #if defined(HAVE_FCNTL_H) || defined(_WIN32)
  41. #include <fcntl.h>
  42. #elif defined(HAVE_SYS_FCNTL_H)
  43. #include <sys/fcntl.h>
  44. #endif
  45. #if !HAVE_OFF_T && !defined(off_t)
  46. # define off_t long
  47. #endif
  48. #include <sys/stat.h>
  49. /* EMX has sys/param.h, but.. */
  50. #if defined(HAVE_SYS_PARAM_H) && !(defined(__EMX__) || defined(__HIUX_MPP__))
  51. # include <sys/param.h>
  52. #endif
  53. #if !defined NOFILE
  54. # define NOFILE 64
  55. #endif
  56. #ifdef HAVE_UNISTD_H
  57. #include <unistd.h>
  58. #endif
  59. #ifdef HAVE_SYSCALL_H
  60. #include <syscall.h>
  61. #elif defined HAVE_SYS_SYSCALL_H
  62. #include <sys/syscall.h>
  63. #endif
  64. extern void Init_File(void);
  65. #if defined(__BEOS__) || defined(__HAIKU__)
  66. # ifndef NOFILE
  67. # define NOFILE (OPEN_MAX)
  68. # endif
  69. #endif
  70. #include "ruby/util.h"
  71. #ifndef O_ACCMODE
  72. #define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR)
  73. #endif
  74. #if SIZEOF_OFF_T > SIZEOF_LONG && !defined(HAVE_LONG_LONG)
  75. # error off_t is bigger than long, but you have no long long...
  76. #endif
  77. #ifndef PIPE_BUF
  78. # ifdef _POSIX_PIPE_BUF
  79. # define PIPE_BUF _POSIX_PIPE_BUF
  80. # else
  81. # define PIPE_BUF 512 /* is this ok? */
  82. # endif
  83. #endif
  84. #define numberof(array) (int)(sizeof(array) / sizeof((array)[0]))
  85. #define IO_RBUF_CAPA_MIN 8192
  86. #define IO_CBUF_CAPA_MIN (128*1024)
  87. #define IO_RBUF_CAPA_FOR(fptr) (NEED_READCONV(fptr) ? IO_CBUF_CAPA_MIN : IO_RBUF_CAPA_MIN)
  88. #define IO_WBUF_CAPA_MIN 8192
  89. /* define system APIs */
  90. #ifdef _WIN32
  91. #undef open
  92. #define open rb_w32_uopen
  93. #endif
  94. VALUE rb_cIO;
  95. VALUE rb_eEOFError;
  96. VALUE rb_eIOError;
  97. VALUE rb_mWaitReadable;
  98. VALUE rb_mWaitWritable;
  99. VALUE rb_stdin, rb_stdout, rb_stderr;
  100. VALUE rb_deferr; /* rescue VIM plugin */
  101. static VALUE orig_stdout, orig_stderr;
  102. VALUE rb_output_fs;
  103. VALUE rb_rs;
  104. VALUE rb_output_rs;
  105. VALUE rb_default_rs;
  106. static VALUE argf;
  107. static ID id_write, id_read, id_getc, id_flush, id_readpartial;
  108. static VALUE sym_mode, sym_perm, sym_extenc, sym_intenc, sym_encoding, sym_open_args;
  109. static VALUE sym_textmode, sym_binmode, sym_autoclose;
  110. struct timeval rb_time_interval(VALUE);
  111. struct argf {
  112. VALUE filename, current_file;
  113. int last_lineno; /* $. */
  114. int lineno;
  115. int init_p, next_p;
  116. VALUE argv;
  117. char *inplace;
  118. int binmode;
  119. struct rb_io_enc_t encs;
  120. };
  121. static int max_file_descriptor = NOFILE;
  122. #define UPDATE_MAXFD(fd) \
  123. do { \
  124. if (max_file_descriptor < (fd)) max_file_descriptor = (fd); \
  125. } while (0)
  126. #define argf_of(obj) (*(struct argf *)DATA_PTR(obj))
  127. #define ARGF argf_of(argf)
  128. #ifdef _STDIO_USES_IOSTREAM /* GNU libc */
  129. # ifdef _IO_fpos_t
  130. # define STDIO_READ_DATA_PENDING(fp) ((fp)->_IO_read_ptr != (fp)->_IO_read_end)
  131. # else
  132. # define STDIO_READ_DATA_PENDING(fp) ((fp)->_gptr < (fp)->_egptr)
  133. # endif
  134. #elif defined(FILE_COUNT)
  135. # define STDIO_READ_DATA_PENDING(fp) ((fp)->FILE_COUNT > 0)
  136. #elif defined(FILE_READEND)
  137. # define STDIO_READ_DATA_PENDING(fp) ((fp)->FILE_READPTR < (fp)->FILE_READEND)
  138. #elif defined(__BEOS__) || defined(__HAIKU__)
  139. # define STDIO_READ_DATA_PENDING(fp) (fp->_state._eof == 0)
  140. #else
  141. # define STDIO_READ_DATA_PENDING(fp) (!feof(fp))
  142. #endif
  143. #define GetWriteIO(io) rb_io_get_write_io(io)
  144. #define READ_DATA_PENDING(fptr) ((fptr)->rbuf_len)
  145. #define READ_DATA_PENDING_COUNT(fptr) ((fptr)->rbuf_len)
  146. #define READ_DATA_PENDING_PTR(fptr) ((fptr)->rbuf+(fptr)->rbuf_off)
  147. #define READ_DATA_BUFFERED(fptr) READ_DATA_PENDING(fptr)
  148. #define READ_CHAR_PENDING(fptr) ((fptr)->cbuf_len)
  149. #define READ_CHAR_PENDING_COUNT(fptr) ((fptr)->cbuf_len)
  150. #define READ_CHAR_PENDING_PTR(fptr) ((fptr)->cbuf+(fptr)->cbuf_off)
  151. #if defined(_WIN32)
  152. #define WAIT_FD_IN_WIN32(fptr) \
  153. (rb_w32_has_cancel_io() ? 0 : rb_thread_wait_fd((fptr)->fd))
  154. #else
  155. #define WAIT_FD_IN_WIN32(fptr)
  156. #endif
  157. #define READ_CHECK(fptr) do {\
  158. if (!READ_DATA_PENDING(fptr)) {\
  159. WAIT_FD_IN_WIN32(fptr);\
  160. rb_io_check_closed(fptr);\
  161. }\
  162. } while(0)
  163. #ifndef S_ISSOCK
  164. # ifdef _S_ISSOCK
  165. # define S_ISSOCK(m) _S_ISSOCK(m)
  166. # else
  167. # ifdef _S_IFSOCK
  168. # define S_ISSOCK(m) ((m & S_IFMT) == _S_IFSOCK)
  169. # else
  170. # ifdef S_IFSOCK
  171. # define S_ISSOCK(m) ((m & S_IFMT) == S_IFSOCK)
  172. # endif
  173. # endif
  174. # endif
  175. #endif
  176. #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
  177. /* Windows */
  178. # define NEED_NEWLINE_DECORATOR_ON_READ(fptr) (!(fptr->mode & FMODE_BINMODE))
  179. # define NEED_NEWLINE_DECORATOR_ON_WRITE(fptr) (!(fptr->mode & FMODE_BINMODE))
  180. # define TEXTMODE_NEWLINE_DECORATOR_ON_WRITE ECONV_CRLF_NEWLINE_DECORATOR
  181. #else
  182. /* Unix */
  183. # define NEED_NEWLINE_DECORATOR_ON_READ(fptr) (fptr->mode & FMODE_TEXTMODE)
  184. # define NEED_NEWLINE_DECORATOR_ON_WRITE(fptr) 0
  185. #endif
  186. #define NEED_READCONV(fptr) (fptr->encs.enc2 != NULL || NEED_NEWLINE_DECORATOR_ON_READ(fptr))
  187. #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)))
  188. #if !defined HAVE_SHUTDOWN && !defined shutdown
  189. #define shutdown(a,b) 0
  190. #endif
  191. #define rb_sys_fail_path(path) rb_sys_fail(NIL_P(path) ? 0 : RSTRING_PTR(path))
  192. #if defined(_WIN32)
  193. #define is_socket(fd, path) rb_w32_is_socket(fd)
  194. #elif !defined(S_ISSOCK)
  195. #define is_socket(fd, path) 0
  196. #else
  197. static int
  198. is_socket(int fd, VALUE path)
  199. {
  200. struct stat sbuf;
  201. if (fstat(fd, &sbuf) < 0)
  202. rb_sys_fail_path(path);
  203. return S_ISSOCK(sbuf.st_mode);
  204. }
  205. #endif
  206. void
  207. rb_eof_error(void)
  208. {
  209. rb_raise(rb_eEOFError, "end of file reached");
  210. }
  211. VALUE
  212. rb_io_taint_check(VALUE io)
  213. {
  214. if (!OBJ_UNTRUSTED(io) && rb_safe_level() >= 4)
  215. rb_raise(rb_eSecurityError, "Insecure: operation on trusted IO");
  216. rb_check_frozen(io);
  217. return io;
  218. }
  219. void
  220. rb_io_check_initialized(rb_io_t *fptr)
  221. {
  222. if (!fptr) {
  223. rb_raise(rb_eIOError, "uninitialized stream");
  224. }
  225. }
  226. void
  227. rb_io_check_closed(rb_io_t *fptr)
  228. {
  229. rb_io_check_initialized(fptr);
  230. if (fptr->fd < 0) {
  231. rb_raise(rb_eIOError, "closed stream");
  232. }
  233. }
  234. static int io_fflush(rb_io_t *);
  235. VALUE
  236. rb_io_get_io(VALUE io)
  237. {
  238. return rb_convert_type(io, T_FILE, "IO", "to_io");
  239. }
  240. static VALUE
  241. rb_io_check_io(VALUE io)
  242. {
  243. return rb_check_convert_type(io, T_FILE, "IO", "to_io");
  244. }
  245. VALUE
  246. rb_io_get_write_io(VALUE io)
  247. {
  248. VALUE write_io;
  249. rb_io_check_initialized(RFILE(io)->fptr);
  250. write_io = RFILE(io)->fptr->tied_io_for_writing;
  251. if (write_io) {
  252. return write_io;
  253. }
  254. return io;
  255. }
  256. /*
  257. * call-seq:
  258. * IO.try_convert(obj) -> io or nil
  259. *
  260. * Try to convert <i>obj</i> into an IO, using to_io method.
  261. * Returns converted IO or nil if <i>obj</i> cannot be converted
  262. * for any reason.
  263. *
  264. * IO.try_convert(STDOUT) #=> STDOUT
  265. * IO.try_convert("STDOUT") #=> nil
  266. *
  267. * require 'zlib'
  268. * f = open("/tmp/zz.gz") #=> #<File:/tmp/zz.gz>
  269. * z = Zlib::GzipReader.open(f) #=> #<Zlib::GzipReader:0x81d8744>
  270. * IO.try_convert(z) #=> #<File:/tmp/zz.gz>
  271. *
  272. */
  273. static VALUE
  274. rb_io_s_try_convert(VALUE dummy, VALUE io)
  275. {
  276. return rb_io_check_io(io);
  277. }
  278. static void
  279. io_unread(rb_io_t *fptr)
  280. {
  281. off_t r;
  282. rb_io_check_closed(fptr);
  283. if (fptr->rbuf_len == 0 || fptr->mode & FMODE_DUPLEX)
  284. return;
  285. /* xxx: target position may be negative if buffer is filled by ungetc */
  286. errno = 0;
  287. r = lseek(fptr->fd, -fptr->rbuf_len, SEEK_CUR);
  288. if (r < 0 && errno) {
  289. if (errno == ESPIPE)
  290. fptr->mode |= FMODE_DUPLEX;
  291. return;
  292. }
  293. fptr->rbuf_off = 0;
  294. fptr->rbuf_len = 0;
  295. return;
  296. }
  297. static rb_encoding *io_input_encoding(rb_io_t *fptr);
  298. static void
  299. io_ungetbyte(VALUE str, rb_io_t *fptr)
  300. {
  301. long len = RSTRING_LEN(str);
  302. if (fptr->rbuf == NULL) {
  303. const int min_capa = IO_RBUF_CAPA_FOR(fptr);
  304. fptr->rbuf_off = 0;
  305. fptr->rbuf_len = 0;
  306. #if SIZEOF_LONG > SIZEOF_INT
  307. if (len > INT_MAX)
  308. rb_raise(rb_eIOError, "ungetbyte failed");
  309. #endif
  310. if (len > min_capa)
  311. fptr->rbuf_capa = (int)len;
  312. else
  313. fptr->rbuf_capa = min_capa;
  314. fptr->rbuf = ALLOC_N(char, fptr->rbuf_capa);
  315. }
  316. if (fptr->rbuf_capa < len + fptr->rbuf_len) {
  317. rb_raise(rb_eIOError, "ungetbyte failed");
  318. }
  319. if (fptr->rbuf_off < len) {
  320. MEMMOVE(fptr->rbuf+fptr->rbuf_capa-fptr->rbuf_len,
  321. fptr->rbuf+fptr->rbuf_off,
  322. char, fptr->rbuf_len);
  323. fptr->rbuf_off = fptr->rbuf_capa-fptr->rbuf_len;
  324. }
  325. fptr->rbuf_off-=(int)len;
  326. fptr->rbuf_len+=(int)len;
  327. MEMMOVE(fptr->rbuf+fptr->rbuf_off, RSTRING_PTR(str), char, len);
  328. }
  329. static rb_io_t *
  330. flush_before_seek(rb_io_t *fptr)
  331. {
  332. if (io_fflush(fptr) < 0)
  333. rb_sys_fail(0);
  334. io_unread(fptr);
  335. errno = 0;
  336. return fptr;
  337. }
  338. #define io_seek(fptr, ofs, whence) (errno = 0, lseek(flush_before_seek(fptr)->fd, ofs, whence))
  339. #define io_tell(fptr) lseek(flush_before_seek(fptr)->fd, 0, SEEK_CUR)
  340. #ifndef SEEK_CUR
  341. # define SEEK_SET 0
  342. # define SEEK_CUR 1
  343. # define SEEK_END 2
  344. #endif
  345. #define FMODE_SYNCWRITE (FMODE_SYNC|FMODE_WRITABLE)
  346. void
  347. rb_io_check_char_readable(rb_io_t *fptr)
  348. {
  349. rb_io_check_closed(fptr);
  350. if (!(fptr->mode & FMODE_READABLE)) {
  351. rb_raise(rb_eIOError, "not opened for reading");
  352. }
  353. if (fptr->wbuf_len) {
  354. if (io_fflush(fptr) < 0)
  355. rb_sys_fail(0);
  356. }
  357. if (fptr->tied_io_for_writing) {
  358. rb_io_t *wfptr;
  359. GetOpenFile(fptr->tied_io_for_writing, wfptr);
  360. if (io_fflush(wfptr) < 0)
  361. rb_sys_fail(0);
  362. }
  363. }
  364. void
  365. rb_io_check_byte_readable(rb_io_t *fptr)
  366. {
  367. rb_io_check_char_readable(fptr);
  368. if (READ_CHAR_PENDING(fptr)) {
  369. rb_raise(rb_eIOError, "byte oriented read for character buffered IO");
  370. }
  371. }
  372. void
  373. rb_io_check_readable(rb_io_t *fptr)
  374. {
  375. rb_io_check_byte_readable(fptr);
  376. }
  377. static rb_encoding*
  378. io_read_encoding(rb_io_t *fptr)
  379. {
  380. if (fptr->encs.enc) {
  381. return fptr->encs.enc;
  382. }
  383. return rb_default_external_encoding();
  384. }
  385. static rb_encoding*
  386. io_input_encoding(rb_io_t *fptr)
  387. {
  388. if (fptr->encs.enc2) {
  389. return fptr->encs.enc2;
  390. }
  391. return io_read_encoding(fptr);
  392. }
  393. void
  394. rb_io_check_writable(rb_io_t *fptr)
  395. {
  396. rb_io_check_closed(fptr);
  397. if (!(fptr->mode & FMODE_WRITABLE)) {
  398. rb_raise(rb_eIOError, "not opened for writing");
  399. }
  400. if (fptr->rbuf_len) {
  401. io_unread(fptr);
  402. }
  403. }
  404. int
  405. rb_io_read_pending(rb_io_t *fptr)
  406. {
  407. /* This function is used for bytes and chars. Confusing. */
  408. if (READ_CHAR_PENDING(fptr))
  409. return 1; /* should raise? */
  410. return READ_DATA_PENDING(fptr);
  411. }
  412. void
  413. rb_read_check(FILE *fp)
  414. {
  415. if (!STDIO_READ_DATA_PENDING(fp)) {
  416. rb_thread_wait_fd(fileno(fp));
  417. }
  418. }
  419. void
  420. rb_io_read_check(rb_io_t *fptr)
  421. {
  422. if (!READ_DATA_PENDING(fptr)) {
  423. rb_thread_wait_fd(fptr->fd);
  424. }
  425. return;
  426. }
  427. static int
  428. ruby_dup(int orig)
  429. {
  430. int fd;
  431. fd = dup(orig);
  432. if (fd < 0) {
  433. if (errno == EMFILE || errno == ENFILE || errno == ENOMEM) {
  434. rb_gc();
  435. fd = dup(orig);
  436. }
  437. if (fd < 0) {
  438. rb_sys_fail(0);
  439. }
  440. }
  441. UPDATE_MAXFD(fd);
  442. return fd;
  443. }
  444. static VALUE
  445. io_alloc(VALUE klass)
  446. {
  447. NEWOBJ(io, struct RFile);
  448. OBJSETUP(io, klass, T_FILE);
  449. io->fptr = 0;
  450. return (VALUE)io;
  451. }
  452. #ifndef S_ISREG
  453. # define S_ISREG(m) ((m & S_IFMT) == S_IFREG)
  454. #endif
  455. static int
  456. wsplit_p(rb_io_t *fptr)
  457. {
  458. #if defined(HAVE_FCNTL) && defined(F_GETFL) && defined(O_NONBLOCK)
  459. int r;
  460. #endif
  461. if (!(fptr->mode & FMODE_WSPLIT_INITIALIZED)) {
  462. struct stat buf;
  463. if (fstat(fptr->fd, &buf) == 0 &&
  464. !S_ISREG(buf.st_mode)
  465. #if defined(HAVE_FCNTL) && defined(F_GETFL) && defined(O_NONBLOCK)
  466. && (r = fcntl(fptr->fd, F_GETFL)) != -1 &&
  467. !(r & O_NONBLOCK)
  468. #endif
  469. ) {
  470. fptr->mode |= FMODE_WSPLIT;
  471. }
  472. fptr->mode |= FMODE_WSPLIT_INITIALIZED;
  473. }
  474. return fptr->mode & FMODE_WSPLIT;
  475. }
  476. struct io_internal_struct {
  477. int fd;
  478. void *buf;
  479. size_t capa;
  480. };
  481. static VALUE
  482. internal_read_func(void *ptr)
  483. {
  484. struct io_internal_struct *iis = (struct io_internal_struct*)ptr;
  485. return read(iis->fd, iis->buf, iis->capa);
  486. }
  487. static VALUE
  488. internal_write_func(void *ptr)
  489. {
  490. struct io_internal_struct *iis = (struct io_internal_struct*)ptr;
  491. return write(iis->fd, iis->buf, iis->capa);
  492. }
  493. static ssize_t
  494. rb_read_internal(int fd, void *buf, size_t count)
  495. {
  496. struct io_internal_struct iis;
  497. iis.fd = fd;
  498. iis.buf = buf;
  499. iis.capa = count;
  500. return (ssize_t)rb_thread_blocking_region(internal_read_func, &iis, RUBY_UBF_IO, 0);
  501. }
  502. static ssize_t
  503. rb_write_internal(int fd, void *buf, size_t count)
  504. {
  505. struct io_internal_struct iis;
  506. iis.fd = fd;
  507. iis.buf = buf;
  508. iis.capa = count;
  509. return (ssize_t)rb_thread_blocking_region(internal_write_func, &iis, RUBY_UBF_IO, 0);
  510. }
  511. static long
  512. io_writable_length(rb_io_t *fptr, long l)
  513. {
  514. if (PIPE_BUF < l &&
  515. !rb_thread_alone() &&
  516. wsplit_p(fptr)) {
  517. l = PIPE_BUF;
  518. }
  519. return l;
  520. }
  521. static VALUE
  522. io_flush_buffer(VALUE arg)
  523. {
  524. rb_io_t *fptr = (rb_io_t *)arg;
  525. long l = io_writable_length(fptr, fptr->wbuf_len);
  526. return rb_write_internal(fptr->fd, fptr->wbuf+fptr->wbuf_off, l);
  527. }
  528. static int
  529. io_fflush(rb_io_t *fptr)
  530. {
  531. long r;
  532. rb_io_check_closed(fptr);
  533. if (fptr->wbuf_len == 0)
  534. return 0;
  535. if (!rb_thread_fd_writable(fptr->fd)) {
  536. rb_io_check_closed(fptr);
  537. }
  538. retry:
  539. if (fptr->wbuf_len == 0)
  540. return 0;
  541. if (fptr->write_lock) {
  542. r = rb_mutex_synchronize(fptr->write_lock, io_flush_buffer, (VALUE)fptr);
  543. }
  544. else {
  545. long l = io_writable_length(fptr, fptr->wbuf_len);
  546. r = rb_write_internal(fptr->fd, fptr->wbuf+fptr->wbuf_off, l);
  547. }
  548. /* xxx: Other threads may modify wbuf.
  549. * A lock is required, definitely. */
  550. rb_io_check_closed(fptr);
  551. if (fptr->wbuf_len <= r) {
  552. fptr->wbuf_off = 0;
  553. fptr->wbuf_len = 0;
  554. return 0;
  555. }
  556. if (0 <= r) {
  557. fptr->wbuf_off += (int)r;
  558. fptr->wbuf_len -= (int)r;
  559. errno = EAGAIN;
  560. }
  561. if (rb_io_wait_writable(fptr->fd)) {
  562. rb_io_check_closed(fptr);
  563. goto retry;
  564. }
  565. return -1;
  566. }
  567. #ifdef HAVE_RB_FD_INIT
  568. static VALUE
  569. wait_readable(VALUE p)
  570. {
  571. rb_fdset_t *rfds = (rb_fdset_t *)p;
  572. return rb_thread_select(rb_fd_max(rfds), rb_fd_ptr(rfds), NULL, NULL, NULL);
  573. }
  574. #endif
  575. int
  576. rb_io_wait_readable(int f)
  577. {
  578. rb_fdset_t rfds;
  579. if (f < 0) {
  580. rb_raise(rb_eIOError, "closed stream");
  581. }
  582. switch (errno) {
  583. case EINTR:
  584. #if defined(ERESTART)
  585. case ERESTART:
  586. #endif
  587. rb_thread_wait_fd(f);
  588. return TRUE;
  589. case EAGAIN:
  590. #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
  591. case EWOULDBLOCK:
  592. #endif
  593. rb_fd_init(&rfds);
  594. rb_fd_set(f, &rfds);
  595. #ifdef HAVE_RB_FD_INIT
  596. rb_ensure(wait_readable, (VALUE)&rfds,
  597. (VALUE (*)(VALUE))rb_fd_term, (VALUE)&rfds);
  598. #else
  599. rb_thread_select(f + 1, rb_fd_ptr(&rfds), NULL, NULL, NULL);
  600. #endif
  601. return TRUE;
  602. default:
  603. return FALSE;
  604. }
  605. }
  606. #ifdef HAVE_RB_FD_INIT
  607. static VALUE
  608. wait_writable(VALUE p)
  609. {
  610. rb_fdset_t *wfds = (rb_fdset_t *)p;
  611. return rb_thread_select(rb_fd_max(wfds), NULL, rb_fd_ptr(wfds), NULL, NULL);
  612. }
  613. #endif
  614. int
  615. rb_io_wait_writable(int f)
  616. {
  617. rb_fdset_t wfds;
  618. if (f < 0) {
  619. rb_raise(rb_eIOError, "closed stream");
  620. }
  621. switch (errno) {
  622. case EINTR:
  623. #if defined(ERESTART)
  624. case ERESTART:
  625. #endif
  626. rb_thread_fd_writable(f);
  627. return TRUE;
  628. case EAGAIN:
  629. #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
  630. case EWOULDBLOCK:
  631. #endif
  632. rb_fd_init(&wfds);
  633. rb_fd_set(f, &wfds);
  634. #ifdef HAVE_RB_FD_INIT
  635. rb_ensure(wait_writable, (VALUE)&wfds,
  636. (VALUE (*)(VALUE))rb_fd_term, (VALUE)&wfds);
  637. #else
  638. rb_thread_select(f + 1, NULL, rb_fd_ptr(&wfds), NULL, NULL);
  639. #endif
  640. return TRUE;
  641. default:
  642. return FALSE;
  643. }
  644. }
  645. static void
  646. make_writeconv(rb_io_t *fptr)
  647. {
  648. if (!fptr->writeconv_initialized) {
  649. const char *senc, *denc;
  650. rb_encoding *enc;
  651. int ecflags;
  652. VALUE ecopts;
  653. fptr->writeconv_initialized = 1;
  654. ecflags = fptr->encs.ecflags;
  655. ecopts = fptr->encs.ecopts;
  656. #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
  657. if (NEED_NEWLINE_DECORATOR_ON_WRITE(fptr))
  658. ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
  659. #endif
  660. if (!fptr->encs.enc || (fptr->encs.enc == rb_ascii8bit_encoding() && !fptr->encs.enc2)) {
  661. /* no encoding conversion */
  662. fptr->writeconv_pre_ecflags = 0;
  663. fptr->writeconv_pre_ecopts = Qnil;
  664. fptr->writeconv = rb_econv_open_opts("", "", ecflags, ecopts);
  665. if (!fptr->writeconv)
  666. rb_exc_raise(rb_econv_open_exc("", "", ecflags));
  667. fptr->writeconv_asciicompat = Qnil;
  668. }
  669. else {
  670. enc = fptr->encs.enc2 ? fptr->encs.enc2 : fptr->encs.enc;
  671. senc = rb_econv_asciicompat_encoding(rb_enc_name(enc));
  672. if (!senc && !(fptr->encs.ecflags & ECONV_STATEFUL_DECORATOR_MASK)) {
  673. /* single conversion */
  674. fptr->writeconv_pre_ecflags = ecflags;
  675. fptr->writeconv_pre_ecopts = ecopts;
  676. fptr->writeconv = NULL;
  677. fptr->writeconv_asciicompat = Qnil;
  678. }
  679. else {
  680. /* double conversion */
  681. fptr->writeconv_pre_ecflags = ecflags & ~ECONV_STATEFUL_DECORATOR_MASK;
  682. fptr->writeconv_pre_ecopts = ecopts;
  683. if (senc) {
  684. denc = rb_enc_name(enc);
  685. fptr->writeconv_asciicompat = rb_str_new2(senc);
  686. }
  687. else {
  688. senc = denc = "";
  689. fptr->writeconv_asciicompat = rb_str_new2(rb_enc_name(enc));
  690. }
  691. ecflags = fptr->encs.ecflags & (ECONV_ERROR_HANDLER_MASK|ECONV_STATEFUL_DECORATOR_MASK);
  692. ecopts = fptr->encs.ecopts;
  693. fptr->writeconv = rb_econv_open_opts(senc, denc, ecflags, ecopts);
  694. if (!fptr->writeconv)
  695. rb_exc_raise(rb_econv_open_exc(senc, denc, ecflags));
  696. }
  697. }
  698. }
  699. }
  700. /* writing functions */
  701. struct binwrite_arg {
  702. rb_io_t *fptr;
  703. VALUE str;
  704. long offset;
  705. long length;
  706. };
  707. static VALUE
  708. io_binwrite_string(VALUE arg)
  709. {
  710. struct binwrite_arg *p = (struct binwrite_arg *)arg;
  711. long l = io_writable_length(p->fptr, p->length);
  712. return rb_write_internal(p->fptr->fd, RSTRING_PTR(p->str)+p->offset, l);
  713. }
  714. static long
  715. io_binwrite(VALUE str, rb_io_t *fptr, int nosync)
  716. {
  717. long len, n, r, offset = 0;
  718. len = RSTRING_LEN(str);
  719. if ((n = len) <= 0) return n;
  720. if (fptr->wbuf == NULL && !(!nosync && (fptr->mode & FMODE_SYNC))) {
  721. fptr->wbuf_off = 0;
  722. fptr->wbuf_len = 0;
  723. fptr->wbuf_capa = IO_WBUF_CAPA_MIN;
  724. fptr->wbuf = ALLOC_N(char, fptr->wbuf_capa);
  725. fptr->write_lock = rb_mutex_new();
  726. }
  727. if ((!nosync && (fptr->mode & (FMODE_SYNC|FMODE_TTY))) ||
  728. (fptr->wbuf && fptr->wbuf_capa <= fptr->wbuf_len + len)) {
  729. struct binwrite_arg arg;
  730. /* xxx: use writev to avoid double write if available */
  731. if (fptr->wbuf_len && fptr->wbuf_len+len <= fptr->wbuf_capa) {
  732. if (fptr->wbuf_capa < fptr->wbuf_off+fptr->wbuf_len+len) {
  733. MEMMOVE(fptr->wbuf, fptr->wbuf+fptr->wbuf_off, char, fptr->wbuf_len);
  734. fptr->wbuf_off = 0;
  735. }
  736. MEMMOVE(fptr->wbuf+fptr->wbuf_off+fptr->wbuf_len, RSTRING_PTR(str)+offset, char, len);
  737. fptr->wbuf_len += (int)len;
  738. n = 0;
  739. }
  740. if (io_fflush(fptr) < 0)
  741. return -1L;
  742. if (n == 0)
  743. return len;
  744. /* avoid context switch between "a" and "\n" in STDERR.puts "a".
  745. [ruby-dev:25080] */
  746. if (fptr->stdio_file != stderr && !rb_thread_fd_writable(fptr->fd)) {
  747. rb_io_check_closed(fptr);
  748. }
  749. arg.fptr = fptr;
  750. arg.str = str;
  751. retry:
  752. arg.offset = offset;
  753. arg.length = n;
  754. if (fptr->write_lock) {
  755. r = rb_mutex_synchronize(fptr->write_lock, io_binwrite_string, (VALUE)&arg);
  756. }
  757. else {
  758. long l = io_writable_length(fptr, n);
  759. r = rb_write_internal(fptr->fd, RSTRING_PTR(str)+offset, l);
  760. }
  761. /* xxx: other threads may modify given string. */
  762. if (r == n) return len;
  763. if (0 <= r) {
  764. offset += r;
  765. n -= r;
  766. errno = EAGAIN;
  767. }
  768. if (rb_io_wait_writable(fptr->fd)) {
  769. rb_io_check_closed(fptr);
  770. if (offset < RSTRING_LEN(str))
  771. goto retry;
  772. }
  773. return -1L;
  774. }
  775. if (fptr->wbuf_off) {
  776. if (fptr->wbuf_len)
  777. MEMMOVE(fptr->wbuf, fptr->wbuf+fptr->wbuf_off, char, fptr->wbuf_len);
  778. fptr->wbuf_off = 0;
  779. }
  780. MEMMOVE(fptr->wbuf+fptr->wbuf_off+fptr->wbuf_len, RSTRING_PTR(str)+offset, char, len);
  781. fptr->wbuf_len += (int)len;
  782. return len;
  783. }
  784. static VALUE
  785. do_writeconv(VALUE str, rb_io_t *fptr)
  786. {
  787. if (NEED_WRITECONV(fptr)) {
  788. VALUE common_encoding = Qnil;
  789. make_writeconv(fptr);
  790. if (fptr->writeconv) {
  791. if (!NIL_P(fptr->writeconv_asciicompat))
  792. common_encoding = fptr->writeconv_asciicompat;
  793. else if (!rb_enc_asciicompat(rb_enc_get(str))) {
  794. rb_raise(rb_eArgError, "ASCII incompatible string written for text mode IO without encoding conversion: %s",
  795. rb_enc_name(rb_enc_get(str)));
  796. }
  797. }
  798. else {
  799. if (fptr->encs.enc2)
  800. common_encoding = rb_enc_from_encoding(fptr->encs.enc2);
  801. else if (fptr->encs.enc != rb_ascii8bit_encoding())
  802. common_encoding = rb_enc_from_encoding(fptr->encs.enc);
  803. }
  804. if (!NIL_P(common_encoding)) {
  805. str = rb_str_encode(str, common_encoding,
  806. fptr->writeconv_pre_ecflags, fptr->writeconv_pre_ecopts);
  807. }
  808. if (fptr->writeconv) {
  809. str = rb_econv_str_convert(fptr->writeconv, str, ECONV_PARTIAL_INPUT);
  810. }
  811. }
  812. return str;
  813. }
  814. static long
  815. io_fwrite(VALUE str, rb_io_t *fptr, int nosync)
  816. {
  817. str = do_writeconv(str, fptr);
  818. return io_binwrite(str, fptr, nosync);
  819. }
  820. static VALUE
  821. io_write(VALUE io, VALUE str, int nosync)
  822. {
  823. rb_io_t *fptr;
  824. long n;
  825. VALUE tmp;
  826. rb_secure(4);
  827. io = GetWriteIO(io);
  828. str = rb_obj_as_string(str);
  829. tmp = rb_io_check_io(io);
  830. if (NIL_P(tmp)) {
  831. /* port is not IO, call write method for it. */
  832. return rb_funcall(io, id_write, 1, str);
  833. }
  834. io = tmp;
  835. if (RSTRING_LEN(str) == 0) return INT2FIX(0);
  836. GetOpenFile(io, fptr);
  837. rb_io_check_writable(fptr);
  838. n = io_fwrite(str, fptr, nosync);
  839. if (n == -1L) rb_sys_fail_path(fptr->pathv);
  840. return LONG2FIX(n);
  841. }
  842. /*
  843. * call-seq:
  844. * ios.write(string) -> integer
  845. *
  846. * Writes the given string to <em>ios</em>. The stream must be opened
  847. * for writing. If the argument is not a string, it will be converted
  848. * to a string using <code>to_s</code>. Returns the number of bytes
  849. * written.
  850. *
  851. * count = $stdout.write( "This is a test\n" )
  852. * puts "That was #{count} bytes of data"
  853. *
  854. * <em>produces:</em>
  855. *
  856. * This is a test
  857. * That was 15 bytes of data
  858. */
  859. static VALUE
  860. io_write_m(VALUE io, VALUE str)
  861. {
  862. return io_write(io, str, 0);
  863. }
  864. VALUE
  865. rb_io_write(VALUE io, VALUE str)
  866. {
  867. return rb_funcall(io, id_write, 1, str);
  868. }
  869. /*
  870. * call-seq:
  871. * ios << obj -> ios
  872. *
  873. * String Output---Writes <i>obj</i> to <em>ios</em>.
  874. * <i>obj</i> will be converted to a string using
  875. * <code>to_s</code>.
  876. *
  877. * $stdout << "Hello " << "world!\n"
  878. *
  879. * <em>produces:</em>
  880. *
  881. * Hello world!
  882. */
  883. VALUE
  884. rb_io_addstr(VALUE io, VALUE str)
  885. {
  886. rb_io_write(io, str);
  887. return io;
  888. }
  889. /*
  890. * call-seq:
  891. * ios.flush -> ios
  892. *
  893. * Flushes any buffered data within <em>ios</em> to the underlying
  894. * operating system (note that this is Ruby internal buffering only;
  895. * the OS may buffer the data as well).
  896. *
  897. * $stdout.print "no newline"
  898. * $stdout.flush
  899. *
  900. * <em>produces:</em>
  901. *
  902. * no newline
  903. */
  904. VALUE
  905. rb_io_flush(VALUE io)
  906. {
  907. rb_io_t *fptr;
  908. if (TYPE(io) != T_FILE) {
  909. return rb_funcall(io, id_flush, 0);
  910. }
  911. io = GetWriteIO(io);
  912. GetOpenFile(io, fptr);
  913. if (fptr->mode & FMODE_WRITABLE) {
  914. if (io_fflush(fptr) < 0)
  915. rb_sys_fail(0);
  916. #ifdef _WIN32
  917. fsync(fptr->fd);
  918. #endif
  919. }
  920. if (fptr->mode & FMODE_READABLE) {
  921. io_unread(fptr);
  922. }
  923. return io;
  924. }
  925. /*
  926. * call-seq:
  927. * ios.pos -> integer
  928. * ios.tell -> integer
  929. *
  930. * Returns the current offset (in bytes) of <em>ios</em>.
  931. *
  932. * f = File.new("testfile")
  933. * f.pos #=> 0
  934. * f.gets #=> "This is line one\n"
  935. * f.pos #=> 17
  936. */
  937. static VALUE
  938. rb_io_tell(VALUE io)
  939. {
  940. rb_io_t *fptr;
  941. off_t pos;
  942. GetOpenFile(io, fptr);
  943. pos = io_tell(fptr);
  944. if (pos < 0 && errno) rb_sys_fail_path(fptr->pathv);
  945. pos -= fptr->rbuf_len;
  946. return OFFT2NUM(pos);
  947. }
  948. static VALUE
  949. rb_io_seek(VALUE io, VALUE offset, int whence)
  950. {
  951. rb_io_t *fptr;
  952. off_t pos;
  953. pos = NUM2OFFT(offset);
  954. GetOpenFile(io, fptr);
  955. pos = io_seek(fptr, pos, whence);
  956. if (pos < 0 && errno) rb_sys_fail_path(fptr->pathv);
  957. return INT2FIX(0);
  958. }
  959. /*
  960. * call-seq:
  961. * ios.seek(amount, whence=IO::SEEK_SET) -> 0
  962. *
  963. * Seeks to a given offset <i>anInteger</i> in the stream according to
  964. * the value of <i>whence</i>:
  965. *
  966. * IO::SEEK_CUR | Seeks to _amount_ plus current position
  967. * --------------+----------------------------------------------------
  968. * IO::SEEK_END | Seeks to _amount_ plus end of stream (you probably
  969. * | want a negative value for _amount_)
  970. * --------------+----------------------------------------------------
  971. * IO::SEEK_SET | Seeks to the absolute location given by _amount_
  972. *
  973. * Example:
  974. *
  975. * f = File.new("testfile")
  976. * f.seek(-13, IO::SEEK_END) #=> 0
  977. * f.readline #=> "And so on...\n"
  978. */
  979. static VALUE
  980. rb_io_seek_m(int argc, VALUE *argv, VALUE io)
  981. {
  982. VALUE offset, ptrname;
  983. int whence = SEEK_SET;
  984. if (rb_scan_args(argc, argv, "11", &offset, &ptrname) == 2) {
  985. whence = NUM2INT(ptrname);
  986. }
  987. return rb_io_seek(io, offset, whence);
  988. }
  989. /*
  990. * call-seq:
  991. * ios.pos = integer -> integer
  992. *
  993. * Seeks to the given position (in bytes) in <em>ios</em>.
  994. *
  995. * f = File.new("testfile")
  996. * f.pos = 17
  997. * f.gets #=> "This is line two\n"
  998. */
  999. static VALUE
  1000. rb_io_set_pos(VALUE io, VALUE offset)
  1001. {
  1002. rb_io_t *fptr;
  1003. off_t pos;
  1004. pos = NUM2OFFT(offset);
  1005. GetOpenFile(io, fptr);
  1006. pos = io_seek(fptr, pos, SEEK_SET);
  1007. if (pos < 0 && errno) rb_sys_fail_path(fptr->pathv);
  1008. return OFFT2NUM(pos);
  1009. }
  1010. static void clear_readconv(rb_io_t *fptr);
  1011. /*
  1012. * call-seq:
  1013. * ios.rewind -> 0
  1014. *
  1015. * Positions <em>ios</em> to the beginning of input, resetting
  1016. * <code>lineno</code> to zero.
  1017. *
  1018. * f = File.new("testfile")
  1019. * f.readline #=> "This is line one\n"
  1020. * f.rewind #=> 0
  1021. * f.lineno #=> 0
  1022. * f.readline #=> "This is line one\n"
  1023. *
  1024. * Note that it cannot be used with streams such as pipes, ttys, and sockets.
  1025. */
  1026. static VALUE
  1027. rb_io_rewind(VALUE io)
  1028. {
  1029. rb_io_t *fptr;
  1030. GetOpenFile(io, fptr);
  1031. if (io_seek(fptr, 0L, 0) < 0 && errno) rb_sys_fail_path(fptr->pathv);
  1032. if (io == ARGF.current_file) {
  1033. ARGF.lineno -= fptr->lineno;
  1034. }
  1035. fptr->lineno = 0;
  1036. if (fptr->readconv) {
  1037. clear_readconv(fptr);
  1038. }
  1039. return INT2FIX(0);
  1040. }
  1041. static int
  1042. io_fillbuf(rb_io_t *fptr)
  1043. {
  1044. ssize_t r;
  1045. if (fptr->rbuf == NULL) {
  1046. fptr->rbuf_off = 0;
  1047. fptr->rbuf_len = 0;
  1048. fptr->rbuf_capa = IO_RBUF_CAPA_FOR(fptr);
  1049. fptr->rbuf = ALLOC_N(char, fptr->rbuf_capa);
  1050. }
  1051. if (fptr->rbuf_len == 0) {
  1052. retry:
  1053. {
  1054. r = rb_read_internal(fptr->fd, fptr->rbuf, fptr->rbuf_capa);
  1055. }
  1056. if (r < 0) {
  1057. if (rb_io_wait_readable(fptr->fd))
  1058. goto retry;
  1059. rb_sys_fail_path(fptr->pathv);
  1060. }
  1061. fptr->rbuf_off = 0;
  1062. fptr->rbuf_len = (int)r; /* r should be <= rbuf_capa */
  1063. if (r == 0)
  1064. return -1; /* EOF */
  1065. }
  1066. return 0;
  1067. }
  1068. /*
  1069. * call-seq:
  1070. * ios.eof -> true or false
  1071. * ios.eof? -> true or false
  1072. *
  1073. * Returns true if <em>ios</em> is at end of file that means
  1074. * there are no more data to read.
  1075. * The stream must be opened for reading or an <code>IOError</code> will be
  1076. * raised.
  1077. *
  1078. * f = File.new("testfile")
  1079. * dummy = f.readlines
  1080. * f.eof #=> true
  1081. *
  1082. * If <em>ios</em> is a stream such as pipe or socket, <code>IO#eof?</code>
  1083. * blocks until the other end sends some data or closes it.
  1084. *
  1085. * r, w = IO.pipe
  1086. * Thread.new { sleep 1; w.close }
  1087. * r.eof? #=> true after 1 second blocking
  1088. *
  1089. * r, w = IO.pipe
  1090. * Thread.new { sleep 1; w.puts "a" }
  1091. * r.eof? #=> false after 1 second blocking
  1092. *
  1093. * r, w = IO.pipe
  1094. * r.eof? # blocks forever
  1095. *
  1096. * Note that <code>IO#eof?</code> reads data to the input byte buffer.
  1097. * So <code>IO#sysread</code> may not behave as you intend with
  1098. * <code>IO#eof?</code>, unless you call <code>IO#rewind</code>
  1099. * first (which is not available for some streams).
  1100. */
  1101. VALUE
  1102. rb_io_eof(VALUE io)
  1103. {
  1104. rb_io_t *fptr;
  1105. GetOpenFile(io, fptr);
  1106. rb_io_check_char_readable(fptr);
  1107. if (READ_CHAR_PENDING(fptr)) return Qfalse;
  1108. if (READ_DATA_PENDING(fptr)) return Qfalse;
  1109. READ_CHECK(fptr);
  1110. if (io_fillbuf(fptr) < 0) {
  1111. return Qtrue;
  1112. }
  1113. return Qfalse;
  1114. }
  1115. /*
  1116. * call-seq:
  1117. * ios.sync -> true or false
  1118. *
  1119. * Returns the current ``sync mode'' of <em>ios</em>. When sync mode is
  1120. * true, all output is immediately flushed to the underlying operating
  1121. * system and is not buffered by Ruby internally. See also
  1122. * <code>IO#fsync</code>.
  1123. *
  1124. * f = File.new("testfile")
  1125. * f.sync #=> false
  1126. */
  1127. static VALUE
  1128. rb_io_sync(VALUE io)
  1129. {
  1130. rb_io_t *fptr;
  1131. io = GetWriteIO(io);
  1132. GetOpenFile(io, fptr);
  1133. return (fptr->mode & FMODE_SYNC) ? Qtrue : Qfalse;
  1134. }
  1135. /*
  1136. * call-seq:
  1137. * ios.sync = boolean -> boolean
  1138. *
  1139. * Sets the ``sync mode'' to <code>true</code> or <code>false</code>.
  1140. * When sync mode is true, all output is immediately flushed to the
  1141. * underlying operating system and is not buffered internally. Returns
  1142. * the new state. See also <code>IO#fsync</code>.
  1143. *
  1144. * f = File.new("testfile")
  1145. * f.sync = true
  1146. *
  1147. * <em>(produces no output)</em>
  1148. */
  1149. static VALUE
  1150. rb_io_set_sync(VALUE io, VALUE sync)
  1151. {
  1152. rb_io_t *fptr;
  1153. io = GetWriteIO(io);
  1154. GetOpenFile(io, fptr);
  1155. if (RTEST(sync)) {
  1156. fptr->mode |= FMODE_SYNC;
  1157. }
  1158. else {
  1159. fptr->mode &= ~FMODE_SYNC;
  1160. }
  1161. return sync;
  1162. }
  1163. #ifdef HAVE_FSYNC
  1164. /*
  1165. * call-seq:
  1166. * ios.fsync -> 0 or nil
  1167. *
  1168. * Immediately writes all buffered data in <em>ios</em> to disk.
  1169. * Note that <code>fsync</code> differs from
  1170. * using <code>IO#sync=</code>. The latter ensures that data is flushed
  1171. * from Ruby's buffers, but doesn't not guarantee that the underlying
  1172. * operating system actually writes it to disk.
  1173. *
  1174. * <code>NotImplementedError</code> is raised
  1175. * if the underlying operating system does not support <em>fsync(2)</em>.
  1176. */
  1177. static VALUE
  1178. rb_io_fsync(VALUE io)
  1179. {
  1180. rb_io_t *fptr;
  1181. io = GetWriteIO(io);
  1182. GetOpenFile(io, fptr);
  1183. if (io_fflush(fptr) < 0)
  1184. rb_sys_fail(0);
  1185. if (fsync(fptr->fd) < 0)
  1186. rb_sys_fail_path(fptr->pathv);
  1187. return INT2FIX(0);
  1188. }
  1189. #else
  1190. #define rb_io_fsync rb_f_notimplement
  1191. #endif
  1192. #ifdef HAVE_FDATASYNC
  1193. /*
  1194. * call-seq:
  1195. * ios.fdatasync -> 0 or nil
  1196. *
  1197. * Immediately writes all buffered data in <em>ios</em> to disk.
  1198. *
  1199. * <code>NotImplementedError</code> is raised
  1200. * if the underlying operating system does not support <em>fdatasync(2)</em>.
  1201. */
  1202. static VALUE
  1203. rb_io_fdatasync(VALUE io)
  1204. {
  1205. rb_io_t *fptr;
  1206. io = GetWriteIO(io);
  1207. GetOpenFile(io, fptr);
  1208. if (io_fflush(fptr) < 0)
  1209. rb_sys_fail(0);
  1210. if (fdatasync(fptr->fd) < 0)
  1211. rb_sys_fail_path(fptr->pathv);
  1212. return INT2FIX(0);
  1213. }
  1214. #else
  1215. #define rb_io_fdatasync rb_f_notimplement
  1216. #endif
  1217. /*
  1218. * call-seq:
  1219. * ios.fileno -> fixnum
  1220. * ios.to_i -> fixnum
  1221. *
  1222. * Returns an integer representing the numeric file descriptor for
  1223. * <em>ios</em>.
  1224. *
  1225. * $stdin.fileno #=> 0
  1226. * $stdout.fileno #=> 1
  1227. */
  1228. static VALUE
  1229. rb_io_fileno(VALUE io)
  1230. {
  1231. rb_io_t *fptr;
  1232. int fd;
  1233. GetOpenFile(io, fptr);
  1234. fd = fptr->fd;
  1235. return INT2FIX(fd);
  1236. }
  1237. /*
  1238. * call-seq:
  1239. * ios.pid -> fixnum
  1240. *
  1241. * Returns the process ID of a child process associated with
  1242. * <em>ios</em>. This will be set by <code>IO.popen</code>.
  1243. *
  1244. * pipe = IO.popen("-")
  1245. * if pipe
  1246. * $stderr.puts "In parent, child pid is #{pipe.pid}"
  1247. * else
  1248. * $stderr.puts "In child, pid is #{$$}"
  1249. * end
  1250. *
  1251. * <em>produces:</em>
  1252. *
  1253. * In child, pid is 26209
  1254. * In parent, child pid is 26209
  1255. */
  1256. static VALUE
  1257. rb_io_pid(VALUE io)
  1258. {
  1259. rb_io_t *fptr;
  1260. GetOpenFile(io, fptr);
  1261. if (!fptr->pid)
  1262. return Qnil;
  1263. return PIDT2NUM(fptr->pid);
  1264. }
  1265. /*
  1266. * call-seq:
  1267. * ios.inspect -> string
  1268. *
  1269. * Return a string describing this IO object.
  1270. */
  1271. static VALUE
  1272. rb_io_inspect(VALUE obj)
  1273. {
  1274. rb_io_t *fptr;
  1275. const char *cname;
  1276. char fd_desc[4+sizeof(int)*3];
  1277. const char *path;
  1278. const char *st = "";
  1279. fptr = RFILE(rb_io_taint_check(obj))->fptr;
  1280. if (!fptr) return rb_any_to_s(obj);
  1281. cname = rb_obj_classname(obj);
  1282. if (NIL_P(fptr->pathv)) {
  1283. if (fptr->fd < 0) {
  1284. path = "";
  1285. st = "(closed)";
  1286. }
  1287. else {
  1288. snprintf(fd_desc, sizeof(fd_desc), "fd %d", fptr->fd);
  1289. path = fd_desc;
  1290. }
  1291. }
  1292. else {
  1293. path = RSTRING_PTR(fptr->pathv);
  1294. if (fptr->fd < 0) {
  1295. st = " (closed)";
  1296. }
  1297. }
  1298. return rb_sprintf("#<%s:%s%s>", cname, path, st);
  1299. }
  1300. /*
  1301. * call-seq:
  1302. * ios.to_io -> ios
  1303. *
  1304. * Returns <em>ios</em>.
  1305. */
  1306. static VALUE
  1307. rb_io_to_io(VALUE io)
  1308. {
  1309. return io;
  1310. }
  1311. /* reading functions */
  1312. static long
  1313. read_buffered_data(char *ptr, long len, rb_io_t *fptr)
  1314. {
  1315. int n;
  1316. n = READ_DATA_PENDING_COUNT(fptr);
  1317. if (n <= 0) return 0;
  1318. if (n > len) n = (int)len;
  1319. MEMMOVE(ptr, fptr->rbuf+fptr->rbuf_off, char, n);
  1320. fptr->rbuf_off += n;
  1321. fptr->rbuf_len -= n;
  1322. return n;
  1323. }
  1324. static long
  1325. io_fread(VALUE str, long offset, rb_io_t *fptr)
  1326. {
  1327. long len = RSTRING_LEN(str) - offset;
  1328. long n = len;
  1329. long c;
  1330. rb_str_locktmp(str);
  1331. if (READ_DATA_PENDING(fptr) == 0) {
  1332. while (n > 0) {
  1333. again:
  1334. c = rb_read_internal(fptr->fd, RSTRING_PTR(str)+offset, n);
  1335. if (c == 0) break;
  1336. if (c < 0) {
  1337. if (rb_io_wait_readable(fptr->fd))
  1338. goto again;
  1339. rb_sys_fail_path(fptr->pathv);
  1340. }
  1341. offset += c;
  1342. if ((n -= c) <= 0) break;
  1343. rb_thread_wait_fd(fptr->fd);
  1344. }
  1345. rb_str_unlocktmp(str);
  1346. return len - n;
  1347. }
  1348. while (n > 0) {
  1349. c = read_buffered_data(RSTRING_PTR(str)+offset, n, fptr);
  1350. if (c > 0) {
  1351. offset += c;
  1352. if ((n -= c) <= 0) break;
  1353. }
  1354. rb_thread_wait_fd(fptr->fd);
  1355. rb_io_check_closed(fptr);
  1356. if (io_fillbuf(fptr) < 0) {
  1357. break;
  1358. }
  1359. }
  1360. rb_str_unlocktmp(str);
  1361. return len - n;
  1362. }
  1363. #define SMALLBUF 100
  1364. static long
  1365. remain_size(rb_io_t *fptr)
  1366. {
  1367. struct stat st;
  1368. off_t siz = READ_DATA_PENDING_COUNT(fptr);
  1369. off_t pos;
  1370. if (fstat(fptr->fd, &st) == 0 && S_ISREG(st.st_mode)
  1371. #if defined(__BEOS__) || defined(__HAIKU__)
  1372. && (st.st_dev > 3)
  1373. #endif
  1374. )
  1375. {
  1376. if (io_fflush(fptr) < 0)
  1377. rb_sys_fail(0);
  1378. pos = lseek(fptr->fd, 0, SEEK_CUR);
  1379. if (st.st_size >= pos && pos >= 0) {
  1380. siz += st.st_size - pos;
  1381. if (siz > LONG_MAX) {
  1382. rb_raise(rb_eIOError, "file too big for single read");
  1383. }
  1384. }
  1385. }
  1386. else {
  1387. siz += BUFSIZ;
  1388. }
  1389. return (long)siz;
  1390. }
  1391. static VALUE
  1392. io_enc_str(VALUE str, rb_io_t *fptr)
  1393. {
  1394. OBJ_TAINT(str);
  1395. rb_enc_associate(str, io_read_encoding(fptr));
  1396. return str;
  1397. }
  1398. static void
  1399. make_readconv(rb_io_t *fptr, int size)
  1400. {
  1401. if (!fptr->readconv) {
  1402. int ecflags;
  1403. VALUE ecopts;
  1404. const char *sname, *dname;
  1405. ecflags = fptr->encs.ecflags;
  1406. ecopts = fptr->encs.ecopts;
  1407. if (NEED_NEWLINE_DECORATOR_ON_READ(fptr))
  1408. ecflags |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;
  1409. if (fptr->encs.enc2) {
  1410. sname = rb_enc_name(fptr->encs.enc2);
  1411. dname = rb_enc_name(fptr->encs.enc);
  1412. }
  1413. else {
  1414. sname = dname = "";
  1415. }
  1416. fptr->readconv = rb_econv_open_opts(sname, dname, ecflags, ecopts);
  1417. if (!fptr->readconv)
  1418. rb_exc_raise(rb_econv_open_exc(sname, dname, ecflags));
  1419. fptr->cbuf_off = 0;
  1420. fptr->cbuf_len = 0;
  1421. if (size < IO_CBUF_CAPA_MIN) size = IO_CBUF_CAPA_MIN;
  1422. fptr->cbuf_capa = size;
  1423. fptr->cbuf = ALLOC_N(char, fptr->cbuf_capa);
  1424. }
  1425. }
  1426. #define MORE_CHAR_SUSPENDED Qtrue
  1427. #define MORE_CHAR_FINISHED Qnil
  1428. static VALUE
  1429. fill_cbuf(rb_io_t *fptr, int ec_flags)
  1430. {
  1431. const unsigned char *ss, *sp, *se;
  1432. unsigned char *ds, *dp, *de;
  1433. rb_econv_result_t res;
  1434. int putbackable;
  1435. int cbuf_len0;
  1436. VALUE exc;
  1437. ec_flags |= ECONV_PARTIAL_INPUT;
  1438. if (fptr->cbuf_len == fptr->cbuf_capa)
  1439. return MORE_CHAR_SUSPENDED; /* cbuf full */
  1440. if (fptr->cbuf_len == 0)
  1441. fptr->cbuf_off = 0;
  1442. else if (fptr->cbuf_off + fptr->cbuf_len == fptr->cbuf_capa) {
  1443. memmove(fptr->cbuf, fptr->cbuf+fptr->cbuf_off, fptr->cbuf_len);
  1444. fptr->cbuf_off = 0;
  1445. }
  1446. cbuf_len0 = fptr->cbuf_len;
  1447. while (1) {
  1448. ss = sp = (const unsigned char *)fptr->rbuf + fptr->rbuf_off;
  1449. se = sp + fptr->rbuf_len;
  1450. ds = dp = (unsigned char *)fptr->cbuf + fptr->cbuf_off + fptr->cbuf_len;
  1451. de = (unsigned char *)fptr->cbuf + fptr->cbuf_capa;
  1452. res = rb_econv_convert(fptr->readconv, &sp, se, &dp, de, ec_flags);
  1453. fptr->rbuf_off += (int)(sp - ss);
  1454. fptr->rbuf_len -= (int)(sp - ss);
  1455. fptr->cbuf_len += (int)(dp - ds);
  1456. putbackable = rb_econv_putbackable(fptr->readconv);
  1457. if (putbackable) {
  1458. rb_econv_putback(fptr->readconv, (unsigned char *)fptr->rbuf + fptr->rbuf_off - putbackable, putbackable);
  1459. fptr->rbuf_off -= putbackable;
  1460. fptr->rbuf_len += putbackable;
  1461. }
  1462. exc = rb_econv_make_exception(fptr->readconv);
  1463. if (!NIL_P(exc))
  1464. return exc;
  1465. if (cbuf_len0 != fptr->cbuf_len)
  1466. return MORE_CHAR_SUSPENDED;
  1467. if (res == econv_finished) {
  1468. return MORE_CHAR_FINISHED;
  1469. }
  1470. if (res == econv_source_buffer_empty) {
  1471. if (fptr->rbuf_len == 0) {
  1472. READ_CHECK(fptr);
  1473. if (io_fillbuf(fptr) == -1) {
  1474. ds = dp = (unsigned char *)fptr->cbuf + fptr->cbuf_off + fptr->cbuf_len;
  1475. de = (unsigned char *)fptr->cbuf + fptr->cbuf_capa;
  1476. res = rb_econv_convert(fptr->readconv, NULL, NULL, &dp, de, 0);
  1477. fptr->cbuf_len += (int)(dp - ds);
  1478. rb_econv_check_error(fptr->readconv);
  1479. }
  1480. }
  1481. }
  1482. }
  1483. }
  1484. static VALUE
  1485. more_char(rb_io_t *fptr)
  1486. {
  1487. VALUE v;
  1488. v = fill_cbuf(fptr, ECONV_AFTER_OUTPUT);
  1489. if (v != MORE_CHAR_SUSPENDED && v != MORE_CHAR_FINISHED)
  1490. rb_exc_raise(v);
  1491. return v;
  1492. }
  1493. static VALUE
  1494. io_shift_cbuf(rb_io_t *fptr, int len, VALUE *strp)
  1495. {
  1496. VALUE str = Qnil;
  1497. if (strp) {
  1498. str = *strp;
  1499. if (NIL_P(str)) {
  1500. *strp = str = rb_str_new(fptr->cbuf+fptr->cbuf_off, len);
  1501. }
  1502. else {
  1503. rb_str_cat(str, fptr->cbuf+fptr->cbuf_off, len);
  1504. }
  1505. OBJ_TAINT(str);
  1506. rb_enc_associate(str, fptr->encs.enc);
  1507. }
  1508. fptr->cbuf_off += len;
  1509. fptr->cbuf_len -= len;
  1510. /* xxx: set coderange */
  1511. if (fptr->cbuf_len == 0)
  1512. fptr->cbuf_off = 0;
  1513. else if (fptr->cbuf_capa/2 < fptr->cbuf_off) {
  1514. memmove(fptr->cbuf, fptr->cbuf+fptr->cbuf_off, fptr->cbuf_len);
  1515. fptr->cbuf_off = 0;
  1516. }
  1517. return str;
  1518. }
  1519. static VALUE
  1520. read_all(rb_io_t *fptr, long siz, VALUE str)
  1521. {
  1522. long bytes;
  1523. long n;
  1524. long pos;
  1525. rb_encoding *enc;
  1526. int cr;
  1527. if (NEED_READCONV(fptr)) {
  1528. if (NIL_P(str)) str = rb_str_new(NULL, 0);
  1529. else rb_str_set_len(str, 0);
  1530. make_readconv(fptr, 0);
  1531. while (1) {
  1532. VALUE v;
  1533. if (fptr->cbuf_len) {
  1534. io_shift_cbuf(fptr, fptr->cbuf_len, &str);
  1535. }
  1536. v = fill_cbuf(fptr, 0);
  1537. if (v != MORE_CHAR_SUSPENDED && v != MORE_CHAR_FINISHED) {
  1538. if (fptr->cbuf_len) {
  1539. io_shift_cbuf(fptr, fptr->cbuf_len, &str);
  1540. }
  1541. rb_exc_raise(v);
  1542. }
  1543. if (v == MORE_CHAR_FINISHED) {
  1544. clear_readconv(fptr);
  1545. return io_enc_str(str, fptr);
  1546. }
  1547. }
  1548. }
  1549. bytes = 0;
  1550. pos = 0;
  1551. enc = io_read_encoding(fptr);
  1552. cr = 0;
  1553. if (siz == 0) siz = BUFSIZ;
  1554. if (NIL_P(str)) {
  1555. str = rb_str_new(0, siz);
  1556. }
  1557. else {
  1558. rb_str_resize(str, siz);
  1559. }
  1560. for (;;) {
  1561. READ_CHECK(fptr);
  1562. n = io_fread(str, bytes, fptr);
  1563. if (n == 0 && bytes == 0) {
  1564. break;
  1565. }
  1566. bytes += n;
  1567. if (cr != ENC_CODERANGE_BROKEN)
  1568. pos += rb_str_coderange_scan_restartable(RSTRING_PTR(str) + pos, RSTRING_PTR(str) + bytes, enc, &cr);
  1569. if (bytes < siz) break;
  1570. siz += BUFSIZ;
  1571. rb_str_resize(str, siz);
  1572. }
  1573. if (bytes != siz) rb_str_resize(str, bytes);
  1574. str = io_enc_str(str, fptr);
  1575. ENC_CODERANGE_SET(str, cr);
  1576. return str;
  1577. }
  1578. void
  1579. rb_io_set_nonblock(rb_io_t *fptr)
  1580. {
  1581. int oflags;
  1582. #ifdef F_GETFL
  1583. oflags = fcntl(fptr->fd, F_GETFL);
  1584. if (oflags == -1) {
  1585. rb_sys_fail_path(fptr->pathv);
  1586. }
  1587. #else
  1588. oflags = 0;
  1589. #endif
  1590. if ((oflags & O_NONBLOCK) == 0) {
  1591. oflags |= O_NONBLOCK;
  1592. if (fcntl(fptr->fd, F_SETFL, oflags) == -1) {
  1593. rb_sys_fail_path(fptr->pathv);
  1594. }
  1595. }
  1596. }
  1597. static VALUE
  1598. io_getpartial(int argc, VALUE *argv, VALUE io, int nonblock)
  1599. {
  1600. rb_io_t *fptr;
  1601. VALUE length, str;
  1602. long n, len;
  1603. rb_scan_args(argc, argv, "11", &length, &str);
  1604. if ((len = NUM2LONG(length)) < 0) {
  1605. rb_raise(rb_eArgError, "negative length %ld given", len);
  1606. }
  1607. if (NIL_P(str)) {
  1608. str = rb_str_new(0, len);
  1609. }
  1610. else {
  1611. StringValue(str);
  1612. rb_str_modify(str);
  1613. rb_str_resize(str, len);
  1614. }
  1615. OBJ_TAINT(str);
  1616. GetOpenFile(io, fptr);
  1617. rb_io_check_byte_readable(fptr);
  1618. if (len == 0)
  1619. return str;
  1620. if (!nonblock)
  1621. READ_CHECK(fptr);
  1622. n = read_buffered_data(RSTRING_PTR(str), len, fptr);
  1623. if (n <= 0) {
  1624. again:
  1625. if (nonblock) {
  1626. rb_io_set_nonblock(fptr);
  1627. }
  1628. rb_str_locktmp(str);
  1629. n = rb_read_internal(fptr->fd, RSTRING_PTR(str), len);
  1630. rb_str_unlocktmp(str);
  1631. if (n < 0) {
  1632. if (!nonblock && rb_io_wait_readable(fptr->fd))
  1633. goto again;
  1634. if (nonblock && (errno == EWOULDBLOCK || errno == EAGAIN))
  1635. rb_mod_sys_fail(rb_mWaitReadable, "read would block");
  1636. rb_sys_fail_path(fptr->pathv);
  1637. }
  1638. }
  1639. rb_str_resize(str, n);
  1640. if (n == 0)
  1641. return Qnil;
  1642. else
  1643. return str;
  1644. }
  1645. /*
  1646. * call-seq:
  1647. * ios.readpartial(maxlen) -> string
  1648. * ios.readpartial(maxlen, outbuf) -> outbuf
  1649. *
  1650. * Reads at most <i>maxlen</i> bytes from the I/O stream.
  1651. * It blocks only if <em>ios</em> has no data immediately available.
  1652. * It doesn't block if some data available.
  1653. * If the optional <i>outbuf</i> argument is present,
  1654. * it must reference a String, which will receive the data.
  1655. * It raises <code>EOFError</code> on end of file.
  1656. *
  1657. * readpartial is designed for streams such as pipe, socket, tty, etc.
  1658. * It blocks only when no data immediately available.
  1659. * This means that it blocks only when following all conditions hold.
  1660. * * the byte buffer in the IO object is empty.
  1661. * * the content of the stream is empty.
  1662. * * the stream is not reached to EOF.
  1663. *
  1664. * When readpartial blocks, it waits data or EOF on the stream.
  1665. * If some data is reached, readpartial returns with the data.
  1666. * If EOF is reached, readpartial raises EOFError.
  1667. *
  1668. * When readpartial doesn't blocks, it returns or raises immediately.
  1669. * If the byte buffer is not empty, it returns the data in the buffer.
  1670. * Otherwise if the stream has some content,
  1671. * it returns the data in the stream.
  1672. * Otherwise if the stream is reached to EOF, it raises EOFError.
  1673. *
  1674. * r, w = IO.pipe # buffer pipe content
  1675. * w << "abc" # "" "abc".
  1676. * r.readpartial(4096) #=> "abc" "" ""
  1677. * r.readpartial(4096) # blocks because buffer and pipe is empty.
  1678. *
  1679. * r, w = IO.pipe # buffer pipe content
  1680. * w << "abc" # "" "abc"
  1681. * w.close # "" "abc" EOF
  1682. * r.readpartial(4096) #=> "abc" "" EOF
  1683. * r.readpartial(4096) # raises EOFError
  1684. *
  1685. * r, w = IO.pipe # buffer pipe content
  1686. * w << "abc\ndef\n" # "" "abc\ndef\n"
  1687. * r.gets #=> "abc\n" "def\n" ""
  1688. * w << "ghi\n" # "def\n" "ghi\n"
  1689. * r.readpartial(4096) #=> "def\n" "" "ghi\n"
  1690. * r.readpartial(4096) #=> "ghi\n" "" ""
  1691. *
  1692. * Note that readpartial behaves similar to sysread.
  1693. * The differences are:
  1694. * * If the byte buffer is not empty, read from the byte buffer instead of "sysread for buffered IO (IOError)".
  1695. * * It doesn't cause Errno::EWOULDBLOCK and Errno::EINTR. When readpartial meets EWOULDBLOCK and EINTR by read system call, readpartial retry the system call.
  1696. *
  1697. * The later means that readpartial is nonblocking-flag insensitive.
  1698. * It blocks on the situation IO#sysread causes Errno::EWOULDBLOCK as if the fd is blocking mode.
  1699. *
  1700. */
  1701. static VALUE
  1702. io_readpartial(int argc, VALUE *argv, VALUE io)
  1703. {
  1704. VALUE ret;
  1705. ret = io_getpartial(argc, argv, io, 0);
  1706. if (NIL_P(ret))
  1707. rb_eof_error();
  1708. else
  1709. return ret;
  1710. }
  1711. /*
  1712. * call-seq:
  1713. * ios.read_nonblock(maxlen) -> string
  1714. * ios.read_nonblock(maxlen, outbuf) -> outbuf
  1715. *
  1716. * Reads at most <i>maxlen</i> bytes from <em>ios</em> using
  1717. * the read(2) system call after O_NONBLOCK is set for
  1718. * the underlying file descriptor.
  1719. *
  1720. * If the optional <i>outbuf</i> argument is present,
  1721. * it must reference a String, which will receive the data.
  1722. *
  1723. * read_nonblock just calls the read(2) system call.
  1724. * It causes all errors the read(2) system call causes: Errno::EWOULDBLOCK, Errno::EINTR, etc.
  1725. * The caller should care such errors.
  1726. *
  1727. * If the exception is Errno::EWOULDBLOCK or Errno::AGAIN,
  1728. * it is extended by IO::WaitReadable.
  1729. * So IO::WaitReadable can be used to rescue the exceptions for retrying read_nonblock.
  1730. *
  1731. * read_nonblock causes EOFError on EOF.
  1732. *
  1733. * If the read byte buffer is not empty,
  1734. * read_nonblock reads from the buffer like readpartial.
  1735. * In this case, the read(2) system call is not called.
  1736. *
  1737. * When read_nonblock raises an exception kind of IO::WaitReadable,
  1738. * read_nonblock should not be called
  1739. * until io is readable for avoiding busy loop.
  1740. * This can be done as follows.
  1741. *
  1742. * # emulates blocking read (readpartial).
  1743. * begin
  1744. * result = io.read_nonblock(maxlen)
  1745. * rescue IO::WaitReadable
  1746. * IO.select([io])
  1747. * retry
  1748. * end
  1749. *
  1750. * Although IO#read_nonblock doesn't raise IO::WaitWritable.
  1751. * OpenSSL::Buffering#read_nonblock can raise IO::WaitWritable.
  1752. * If IO and SSL should be used polymorphically,
  1753. * IO::WaitWritable should be rescued too.
  1754. * See the document of OpenSSL::Buffering#read_nonblock for sample code.
  1755. *
  1756. * Note that this method is identical to readpartial
  1757. * except the non-blocking flag is set.
  1758. */
  1759. static VALUE
  1760. io_read_nonblock(int argc, VALUE *argv, VALUE io)
  1761. {
  1762. VALUE ret;
  1763. ret = io_getpartial(argc, argv, io, 1);
  1764. if (NIL_P(ret))
  1765. rb_eof_error();
  1766. else
  1767. return ret;
  1768. }
  1769. /*
  1770. * call-seq:
  1771. * ios.write_nonblock(string) -> integer
  1772. *
  1773. * Writes the given string to <em>ios</em> using
  1774. * the write(2) system call after O_NONBLOCK is set for
  1775. * the underlying file descriptor.
  1776. *
  1777. * It returns the number of bytes written.
  1778. *
  1779. * write_nonblock just calls the write(2) system call.
  1780. * It causes all errors the write(2) system call causes: Errno::EWOULDBLOCK, Errno::EINTR, etc.
  1781. * The result may also be smaller than string.length (partial write).
  1782. * The caller should care such errors and partial write.
  1783. *
  1784. * If the exception is Errno::EWOULDBLOCK or Errno::AGAIN,
  1785. * it is extended by IO::WaitWritable.
  1786. * So IO::WaitWritable can be used to rescue the exceptions for retrying write_nonblock.
  1787. *
  1788. * # Creates a pipe.
  1789. * r, w = IO.pipe
  1790. *
  1791. * # write_nonblock writes only 65536 bytes and return 65536.
  1792. * # (The pipe size is 65536 bytes on this environment.)
  1793. * s = "a" * 100000
  1794. * p w.write_nonblock(s) #=> 65536
  1795. *
  1796. * # write_nonblock cannot write a byte and raise EWOULDBLOCK (EAGAIN).
  1797. * p w.write_nonblock("b") # Resource temporarily unavailable (Errno::EAGAIN)
  1798. *
  1799. * If the write buffer is not empty, it is flushed at first.
  1800. *
  1801. * When write_nonblock raises an exception kind of IO::WaitWritable,
  1802. * write_nonblock should not be called
  1803. * until io is writable for avoiding busy loop.
  1804. * This can be done as follows.
  1805. *
  1806. * begin
  1807. * result = io.write_nonblock(string)
  1808. * rescue IO::WaitWritable, Errno::EINTR
  1809. * IO.select(nil, [io])
  1810. * retry
  1811. * end
  1812. *
  1813. * Note that this doesn't guarantee to write all data in string.
  1814. * The length written is reported as result and it should be checked later.
  1815. *
  1816. * On some platforms such as Windows, write_nonblock is not supported
  1817. * according to the kind of the IO object.
  1818. * In such cases, write_nonblock raises <code>Errno::EBADF</code>.
  1819. *
  1820. */
  1821. static VALUE
  1822. rb_io_write_nonblock(VALUE io, VALUE str)
  1823. {
  1824. rb_io_t *fptr;
  1825. long n;
  1826. rb_secure(4);
  1827. if (TYPE(str) != T_STRING)
  1828. str = rb_obj_as_string(str);
  1829. io = GetWriteIO(io);
  1830. GetOpenFile(io, fptr);
  1831. rb_io_check_writable(fptr);
  1832. if (io_fflush(fptr) < 0)
  1833. rb_sys_fail(0);
  1834. rb_io_set_nonblock(fptr);
  1835. n = write(fptr->fd, RSTRING_PTR(str), RSTRING_LEN(str));
  1836. if (n == -1) {
  1837. if (errno == EWOULDBLOCK || errno == EAGAIN)
  1838. rb_mod_sys_fail(rb_mWaitWritable, "write would block");
  1839. rb_sys_fail_path(fptr->pathv);
  1840. }
  1841. return LONG2FIX(n);
  1842. }
  1843. /*
  1844. * call-seq:
  1845. * ios.read([length [, buffer]]) -> string, buffer, or nil
  1846. *
  1847. * Reads <i>length</i> bytes from the I/O stream.
  1848. *
  1849. * <i>length</i> must be a non-negative integer or <code>nil</code>.
  1850. *
  1851. * If <i>length</i> is a positive integer,
  1852. * it try to read <i>length</i> bytes without any conversion (binary mode).
  1853. * It returns <code>nil</code> or a string whose length is 1 to <i>length</i> bytes.
  1854. * <code>nil</code> means it met EOF at beginning.
  1855. * The 1 to <i>length</i>-1 bytes string means it met EOF after reading the result.
  1856. * The <i>length</i> bytes string means it doesn't meet EOF.
  1857. * The resulted string is always ASCII-8BIT encoding.
  1858. *
  1859. * If <i>length</i> is omitted or is <code>nil</code>,
  1860. * it reads until EOF and the encoding conversion is applied.
  1861. * It returns a string even if EOF is met at beginning.
  1862. *
  1863. * If <i>length</i> is zero, it returns <code>""</code>.
  1864. *
  1865. * If the optional <i>buffer</i> argument is present, it must reference
  1866. * a String, which will receive the data.
  1867. *
  1868. * At end of file, it returns <code>nil</code> or <code>""</code>
  1869. * depend on <i>length</i>.
  1870. * <code><i>ios</i>.read()</code> and
  1871. * <code><i>ios</i>.read(nil)</code> returns <code>""</code>.
  1872. * <code><i>ios</i>.read(<i>positive-integer</i>)</code> returns <code>nil</code>.
  1873. *
  1874. * f = File.new("testfile")
  1875. * f.read(16) #=> "This is line one"
  1876. *
  1877. * # reads whole file
  1878. * open("file") {|f|
  1879. * data = f.read # This returns a string even if the file is empty.
  1880. * ...
  1881. * }
  1882. *
  1883. * # iterate over fixed length records.
  1884. * open("fixed-record-file") {|f|
  1885. * while record = f.read(256)
  1886. * ...
  1887. * end
  1888. * }
  1889. *
  1890. * # iterate over variable length records.
  1891. * # record is prefixed by 32-bit length.
  1892. * open("variable-record-file") {|f|
  1893. * while len = f.read(4)
  1894. * len = len.unpack("N")[0] # 32-bit length
  1895. * record = f.read(len) # This returns a string even if len is 0.
  1896. * end
  1897. * }
  1898. *
  1899. * Note that this method behaves like fread() function in C.
  1900. * If you need the behavior like read(2) system call,
  1901. * consider readpartial, read_nonblock and sysread.
  1902. */
  1903. static VALUE
  1904. io_read(int argc, VALUE *argv, VALUE io)
  1905. {
  1906. rb_io_t *fptr;
  1907. long n, len;
  1908. VALUE length, str;
  1909. rb_scan_args(argc, argv, "02", &length, &str);
  1910. if (NIL_P(length)) {
  1911. if (!NIL_P(str)) StringValue(str);
  1912. GetOpenFile(io, fptr);
  1913. rb_io_check_char_readable(fptr);
  1914. return read_all(fptr, remain_size(fptr), str);
  1915. }
  1916. len = NUM2LONG(length);
  1917. if (len < 0) {
  1918. rb_raise(rb_eArgError, "negative length %ld given", len);
  1919. }
  1920. if (NIL_P(str)) {
  1921. str = rb_str_new(0, len);
  1922. }
  1923. else {
  1924. StringValue(str);
  1925. rb_str_modify(str);
  1926. rb_str_resize(str,len);
  1927. }
  1928. GetOpenFile(io, fptr);
  1929. rb_io_check_byte_readable(fptr);
  1930. if (len == 0) return str;
  1931. READ_CHECK(fptr);
  1932. n = io_fread(str, 0, fptr);
  1933. if (n == 0) {
  1934. if (fptr->fd < 0) return Qnil;
  1935. rb_str_resize(str, 0);
  1936. return Qnil;
  1937. }
  1938. rb_str_resize(str, n);
  1939. OBJ_TAINT(str);
  1940. return str;
  1941. }
  1942. static void
  1943. rscheck(const char *rsptr, long rslen, VALUE rs)
  1944. {
  1945. if (!rs) return;
  1946. if (RSTRING_PTR(rs) != rsptr && RSTRING_LEN(rs) != rslen)
  1947. rb_raise(rb_eRuntimeError, "rs modified");
  1948. }
  1949. static int
  1950. appendline(rb_io_t *fptr, int delim, VALUE *strp, long *lp)
  1951. {
  1952. VALUE str = *strp;
  1953. long limit = *lp;
  1954. if (NEED_READCONV(fptr)) {
  1955. make_readconv(fptr, 0);
  1956. do {
  1957. const char *p, *e;
  1958. int searchlen;
  1959. if (fptr->cbuf_len) {
  1960. p = fptr->cbuf+fptr->cbuf_off;
  1961. searchlen = fptr->cbuf_len;
  1962. if (0 < limit && limit < searchlen)
  1963. searchlen = (int)limit;
  1964. e = memchr(p, delim, searchlen);
  1965. if (e) {
  1966. int len = (int)(e-p+1);
  1967. if (NIL_P(str))
  1968. *strp = str = rb_str_new(p, len);
  1969. else
  1970. rb_str_buf_cat(str, p, len);
  1971. fptr->cbuf_off += len;
  1972. fptr->cbuf_len -= len;
  1973. limit -= len;
  1974. *lp = limit;
  1975. return delim;
  1976. }
  1977. if (NIL_P(str))
  1978. *strp = str = rb_str_new(p, searchlen);
  1979. else
  1980. rb_str_buf_cat(str, p, searchlen);
  1981. fptr->cbuf_off += searchlen;
  1982. fptr->cbuf_len -= searchlen;
  1983. limit -= searchlen;
  1984. if (limit == 0) {
  1985. *lp = limit;
  1986. return (unsigned char)RSTRING_PTR(str)[RSTRING_LEN(str)-1];
  1987. }
  1988. }
  1989. } while (more_char(fptr) != MORE_CHAR_FINISHED);
  1990. clear_readconv(fptr);
  1991. *lp = limit;
  1992. return EOF;
  1993. }
  1994. do {
  1995. long pending = READ_DATA_PENDING_COUNT(fptr);
  1996. if (pending > 0) {
  1997. const char *p = READ_DATA_PENDING_PTR(fptr);
  1998. const char *e;
  1999. long last;
  2000. if (limit > 0 && pending > limit) pending = limit;
  2001. e = memchr(p, delim, pending);
  2002. if (e) pending = e - p + 1;
  2003. if (!NIL_P(str)) {
  2004. last = RSTRING_LEN(str);
  2005. rb_str_resize(str, last + pending);
  2006. }
  2007. else {
  2008. last = 0;
  2009. *strp = str = rb_str_buf_new(pending);
  2010. rb_str_set_len(str, pending);
  2011. }
  2012. read_buffered_data(RSTRING_PTR(str) + last, pending, fptr); /* must not fail */
  2013. limit -= pending;
  2014. *lp = limit;
  2015. if (e) return delim;
  2016. if (limit == 0)
  2017. return (unsigned char)RSTRING_PTR(str)[RSTRING_LEN(str)-1];
  2018. }
  2019. READ_CHECK(fptr);
  2020. } while (io_fillbuf(fptr) >= 0);
  2021. *lp = limit;
  2022. return EOF;
  2023. }
  2024. static inline int
  2025. swallow(rb_io_t *fptr, int term)
  2026. {
  2027. if (NEED_READCONV(fptr)) {
  2028. rb_encoding *enc = io_read_encoding(fptr);
  2029. int needconv = rb_enc_mbminlen(enc) != 1;
  2030. make_readconv(fptr, 0);
  2031. do {
  2032. size_t cnt;
  2033. while ((cnt = READ_CHAR_PENDING_COUNT(fptr)) > 0) {
  2034. const char *p = READ_CHAR_PENDING_PTR(fptr);
  2035. int i;
  2036. if (!needconv) {
  2037. if (*p != term) return TRUE;
  2038. i = (int)cnt;
  2039. while (--i && *++p == term);
  2040. }
  2041. else {
  2042. const char *e = p + cnt;
  2043. if (rb_enc_ascget(p, e, &i, enc) != term) return TRUE;
  2044. while ((p += i) < e && rb_enc_ascget(p, e, &i, enc) == term);
  2045. i = (int)(e - p);
  2046. }
  2047. io_shift_cbuf(fptr, (int)cnt - i, NULL);
  2048. }
  2049. } while (more_char(fptr) != MORE_CHAR_FINISHED);
  2050. return FALSE;
  2051. }
  2052. do {
  2053. size_t cnt;
  2054. while ((cnt = READ_DATA_PENDING_COUNT(fptr)) > 0) {
  2055. char buf[1024];
  2056. const char *p = READ_DATA_PENDING_PTR(fptr);
  2057. int i;
  2058. if (cnt > sizeof buf) cnt = sizeof buf;
  2059. if (*p != term) return TRUE;
  2060. i = (int)cnt;
  2061. while (--i && *++p == term);
  2062. if (!read_buffered_data(buf, cnt - i, fptr)) /* must not fail */
  2063. rb_sys_fail_path(fptr->pathv);
  2064. }
  2065. READ_CHECK(fptr);
  2066. } while (io_fillbuf(fptr) == 0);
  2067. return FALSE;
  2068. }
  2069. static VALUE
  2070. rb_io_getline_fast(rb_io_t *fptr, rb_encoding *enc, VALUE io)
  2071. {
  2072. VALUE str = Qnil;
  2073. int len = 0;
  2074. long pos = 0;
  2075. int cr = 0;
  2076. for (;;) {
  2077. int pending = READ_DATA_PENDING_COUNT(fptr);
  2078. if (pending > 0) {
  2079. const char *p = READ_DATA_PENDING_PTR(fptr);
  2080. const char *e;
  2081. e = memchr(p, '\n', pending);
  2082. if (e) {
  2083. pending = (int)(e - p + 1);
  2084. }
  2085. if (NIL_P(str)) {
  2086. str = rb_str_new(p, pending);
  2087. fptr->rbuf_off += pending;
  2088. fptr->rbuf_len -= pending;
  2089. }
  2090. else {
  2091. rb_str_resize(str, len + pending);
  2092. read_buffered_data(RSTRING_PTR(str)+len, pending, fptr);
  2093. }
  2094. len += pending;
  2095. if (cr != ENC_CODERANGE_BROKEN)
  2096. pos += rb_str_coderange_scan_restartable(RSTRING_PTR(str) + pos, RSTRING_PTR(str) + len, enc, &cr);
  2097. if (e) break;
  2098. }
  2099. READ_CHECK(fptr);
  2100. if (io_fillbuf(fptr) < 0) {
  2101. if (NIL_P(str)) return Qnil;
  2102. break;
  2103. }
  2104. }
  2105. str = io_enc_str(str, fptr);
  2106. ENC_CODERANGE_SET(str, cr);
  2107. fptr->lineno++;
  2108. if (io == ARGF.current_file) {
  2109. ARGF.lineno++;
  2110. ARGF.last_lineno = ARGF.lineno;
  2111. }
  2112. else {
  2113. ARGF.last_lineno = fptr->lineno;
  2114. }
  2115. return str;
  2116. }
  2117. static void
  2118. prepare_getline_args(int argc, VALUE *argv, VALUE *rsp, long *limit, VALUE io)
  2119. {
  2120. VALUE rs = rb_rs, lim = Qnil;
  2121. rb_io_t *fptr;
  2122. if (argc == 1) {
  2123. VALUE tmp = Qnil;
  2124. if (NIL_P(argv[0]) || !NIL_P(tmp = rb_check_string_type(argv[0]))) {
  2125. rs = tmp;
  2126. }
  2127. else {
  2128. lim = argv[0];
  2129. }
  2130. }
  2131. else if (2 <= argc) {
  2132. rb_scan_args(argc, argv, "2", &rs, &lim);
  2133. if (!NIL_P(rs))
  2134. StringValue(rs);
  2135. }
  2136. if (!NIL_P(rs)) {
  2137. rb_encoding *enc_rs, *enc_io;
  2138. GetOpenFile(io, fptr);
  2139. enc_rs = rb_enc_get(rs);
  2140. enc_io = io_read_encoding(fptr);
  2141. if (enc_io != enc_rs &&
  2142. (rb_enc_str_coderange(rs) != ENC_CODERANGE_7BIT ||
  2143. (RSTRING_LEN(rs) > 0 && !rb_enc_asciicompat(enc_io)))) {
  2144. if (rs == rb_default_rs) {
  2145. rs = rb_enc_str_new(0, 0, enc_io);
  2146. rb_str_buf_cat_ascii(rs, "\n");
  2147. }
  2148. else {
  2149. rb_raise(rb_eArgError, "encoding mismatch: %s IO with %s RS",
  2150. rb_enc_name(enc_io),
  2151. rb_enc_name(enc_rs));
  2152. }
  2153. }
  2154. }
  2155. *rsp = rs;
  2156. *limit = NIL_P(lim) ? -1L : NUM2LONG(lim);
  2157. }
  2158. static VALUE
  2159. rb_io_getline_1(VALUE rs, long limit, VALUE io)
  2160. {
  2161. VALUE str = Qnil;
  2162. rb_io_t *fptr;
  2163. int nolimit = 0;
  2164. rb_encoding *enc;
  2165. GetOpenFile(io, fptr);
  2166. rb_io_check_char_readable(fptr);
  2167. if (NIL_P(rs) && limit < 0) {
  2168. str = read_all(fptr, 0, Qnil);
  2169. if (RSTRING_LEN(str) == 0) return Qnil;
  2170. }
  2171. else if (limit == 0) {
  2172. return rb_enc_str_new(0, 0, io_read_encoding(fptr));
  2173. }
  2174. else if (rs == rb_default_rs && limit < 0 && !NEED_READCONV(fptr) &&
  2175. rb_enc_asciicompat(enc = io_read_encoding(fptr))) {
  2176. return rb_io_getline_fast(fptr, enc, io);
  2177. }
  2178. else {
  2179. int c, newline = -1;
  2180. const char *rsptr = 0;
  2181. long rslen = 0;
  2182. int rspara = 0;
  2183. int extra_limit = 16;
  2184. enc = io_read_encoding(fptr);
  2185. if (!NIL_P(rs)) {
  2186. rslen = RSTRING_LEN(rs);
  2187. if (rslen == 0) {
  2188. rsptr = "\n\n";
  2189. rslen = 2;
  2190. rspara = 1;
  2191. swallow(fptr, '\n');
  2192. rs = 0;
  2193. if (!rb_enc_asciicompat(enc)) {
  2194. rs = rb_usascii_str_new(rsptr, rslen);
  2195. rs = rb_str_encode(rs, rb_enc_from_encoding(enc), 0, Qnil);
  2196. OBJ_FREEZE(rs);
  2197. rsptr = RSTRING_PTR(rs);
  2198. rslen = RSTRING_LEN(rs);
  2199. }
  2200. }
  2201. else {
  2202. rsptr = RSTRING_PTR(rs);
  2203. }
  2204. newline = (unsigned char)rsptr[rslen - 1];
  2205. }
  2206. /* MS - Optimisation */
  2207. while ((c = appendline(fptr, newline, &str, &limit)) != EOF) {
  2208. const char *s, *p, *pp, *e;
  2209. if (c == newline) {
  2210. if (RSTRING_LEN(str) < rslen) continue;
  2211. s = RSTRING_PTR(str);
  2212. e = s + RSTRING_LEN(str);
  2213. p = e - rslen;
  2214. pp = rb_enc_left_char_head(s, p, e, enc);
  2215. if (pp != p) continue;
  2216. if (!rspara) rscheck(rsptr, rslen, rs);
  2217. if (memcmp(p, rsptr, rslen) == 0) break;
  2218. }
  2219. if (limit == 0) {
  2220. s = RSTRING_PTR(str);
  2221. p = s + RSTRING_LEN(str);
  2222. pp = rb_enc_left_char_head(s, p-1, p, enc);
  2223. if (extra_limit &&
  2224. MBCLEN_NEEDMORE_P(rb_enc_precise_mbclen(pp, p, enc))) {
  2225. /* relax the limit while incomplete character.
  2226. * extra_limit limits the relax length */
  2227. limit = 1;
  2228. extra_limit--;
  2229. }
  2230. else {
  2231. nolimit = 1;
  2232. break;
  2233. }
  2234. }
  2235. }
  2236. if (rspara) {
  2237. if (c != EOF) {
  2238. swallow(fptr, '\n');
  2239. }
  2240. }
  2241. if (!NIL_P(str))
  2242. str = io_enc_str(str, fptr);
  2243. }
  2244. if (!NIL_P(str)) {
  2245. if (!nolimit) {
  2246. fptr->lineno++;
  2247. if (io == ARGF.current_file) {
  2248. ARGF.lineno++;
  2249. ARGF.last_lineno = ARGF.lineno;
  2250. }
  2251. else {
  2252. ARGF.last_lineno = fptr->lineno;
  2253. }
  2254. }
  2255. }
  2256. return str;
  2257. }
  2258. static VALUE
  2259. rb_io_getline(int argc, VALUE *argv, VALUE io)
  2260. {
  2261. VALUE rs;
  2262. long limit;
  2263. prepare_getline_args(argc, argv, &rs, &limit, io);
  2264. return rb_io_getline_1(rs, limit, io);
  2265. }
  2266. VALUE
  2267. rb_io_gets(VALUE io)
  2268. {
  2269. return rb_io_getline_1(rb_default_rs, -1, io);
  2270. }
  2271. /*
  2272. * call-seq:
  2273. * ios.gets(sep=$/) -> string or nil
  2274. * ios.gets(limit) -> string or nil
  2275. * ios.gets(sep, limit) -> string or nil
  2276. *
  2277. * Reads the next ``line'' from the I/O stream; lines are separated by
  2278. * <i>sep</i>. A separator of <code>nil</code> reads the entire
  2279. * contents, and a zero-length separator reads the input a paragraph at
  2280. * a time (two successive newlines in the input separate paragraphs).
  2281. * The stream must be opened for reading or an <code>IOError</code>
  2282. * will be raised. The line read in will be returned and also assigned
  2283. * to <code>$_</code>. Returns <code>nil</code> if called at end of
  2284. * file. If the first argument is an integer, or optional second
  2285. * argument is given, the returning string would not be longer than the
  2286. * given value in bytes.
  2287. *
  2288. * File.new("testfile").gets #=> "This is line one\n"
  2289. * $_ #=> "This is line one\n"
  2290. */
  2291. static VALUE
  2292. rb_io_gets_m(int argc, VALUE *argv, VALUE io)
  2293. {
  2294. VALUE str;
  2295. str = rb_io_getline(argc, argv, io);
  2296. rb_lastline_set(str);
  2297. return str;
  2298. }
  2299. /*
  2300. * call-seq:
  2301. * ios.lineno -> integer
  2302. *
  2303. * Returns the current line number in <em>ios</em>. The stream must be
  2304. * opened for reading. <code>lineno</code> counts the number of times
  2305. * <code>gets</code> is called, rather than the number of newlines
  2306. * encountered. The two values will differ if <code>gets</code> is
  2307. * called with a separator other than newline. See also the
  2308. * <code>$.</code> variable.
  2309. *
  2310. * f = File.new("testfile")
  2311. * f.lineno #=> 0
  2312. * f.gets #=> "This is line one\n"
  2313. * f.lineno #=> 1
  2314. * f.gets #=> "This is line two\n"
  2315. * f.lineno #=> 2
  2316. */
  2317. static VALUE
  2318. rb_io_lineno(VALUE io)
  2319. {
  2320. rb_io_t *fptr;
  2321. GetOpenFile(io, fptr);
  2322. rb_io_check_char_readable(fptr);
  2323. return INT2NUM(fptr->lineno);
  2324. }
  2325. /*
  2326. * call-seq:
  2327. * ios.lineno = integer -> integer
  2328. *
  2329. * Manually sets the current line number to the given value.
  2330. * <code>$.</code> is updated only on the next read.
  2331. *
  2332. * f = File.new("testfile")
  2333. * f.gets #=> "This is line one\n"
  2334. * $. #=> 1
  2335. * f.lineno = 1000
  2336. * f.lineno #=> 1000
  2337. * $. #=> 1 # lineno of last read
  2338. * f.gets #=> "This is line two\n"
  2339. * $. #=> 1001 # lineno of last read
  2340. */
  2341. static VALUE
  2342. rb_io_set_lineno(VALUE io, VALUE lineno)
  2343. {
  2344. rb_io_t *fptr;
  2345. GetOpenFile(io, fptr);
  2346. rb_io_check_char_readable(fptr);
  2347. fptr->lineno = NUM2INT(lineno);
  2348. return lineno;
  2349. }
  2350. /*
  2351. * call-seq:
  2352. * ios.readline(sep=$/) -> string
  2353. * ios.readline(limit) -> string
  2354. * ios.readline(sep, limit) -> string
  2355. *
  2356. * Reads a line as with <code>IO#gets</code>, but raises an
  2357. * <code>EOFError</code> on end of file.
  2358. */
  2359. static VALUE
  2360. rb_io_readline(int argc, VALUE *argv, VALUE io)
  2361. {
  2362. VALUE line = rb_io_gets_m(argc, argv, io);
  2363. if (NIL_P(line)) {
  2364. rb_eof_error();
  2365. }
  2366. return line;
  2367. }
  2368. /*
  2369. * call-seq:
  2370. * ios.readlines(sep=$/) -> array
  2371. * ios.readlines(limit) -> array
  2372. * ios.readlines(sep, limit) -> array
  2373. *
  2374. * Reads all of the lines in <em>ios</em>, and returns them in
  2375. * <i>anArray</i>. Lines are separated by the optional <i>sep</i>. If
  2376. * <i>sep</i> is <code>nil</code>, the rest of the stream is returned
  2377. * as a single record. If the first argument is an integer, or
  2378. * optional second argument is given, the returning string would not be
  2379. * longer than the given value in bytes. The stream must be opened for
  2380. * reading or an <code>IOError</code> will be raised.
  2381. *
  2382. * f = File.new("testfile")
  2383. * f.readlines[0] #=> "This is line one\n"
  2384. */
  2385. static VALUE
  2386. rb_io_readlines(int argc, VALUE *argv, VALUE io)
  2387. {
  2388. VALUE line, ary, rs;
  2389. long limit;
  2390. prepare_getline_args(argc, argv, &rs, &limit, io);
  2391. ary = rb_ary_new();
  2392. while (!NIL_P(line = rb_io_getline_1(rs, limit, io))) {
  2393. rb_ary_push(ary, line);
  2394. }
  2395. return ary;
  2396. }
  2397. /*
  2398. * call-seq:
  2399. * ios.each(sep=$/) {|line| block } -> ios
  2400. * ios.each(limit) {|line| block } -> ios
  2401. * ios.each(sep,limit) {|line| block } -> ios
  2402. * ios.each(...) -> an_enumerator
  2403. *
  2404. * ios.each_line(sep=$/) {|line| block } -> ios
  2405. * ios.each_line(limit) {|line| block } -> ios
  2406. * ios.each_line(sep,limit) {|line| block } -> ios
  2407. * ios.each_line(...) -> an_enumerator
  2408. *
  2409. * ios.lines(sep=$/) {|line| block } -> ios
  2410. * ios.lines(limit) {|line| block } -> ios
  2411. * ios.lines(sep,limit) {|line| block } -> ios
  2412. * ios.lines(...) -> an_enumerator
  2413. *
  2414. * Executes the block for every line in <em>ios</em>, where lines are
  2415. * separated by <i>sep</i>. <em>ios</em> must be opened for
  2416. * reading or an <code>IOError</code> will be raised.
  2417. *
  2418. * If no block is given, an enumerator is returned instead.
  2419. *
  2420. * f = File.new("testfile")
  2421. * f.each {|line| puts "#{f.lineno}: #{line}" }
  2422. *
  2423. * <em>produces:</em>
  2424. *
  2425. * 1: This is line one
  2426. * 2: This is line two
  2427. * 3: This is line three
  2428. * 4: And so on...
  2429. */
  2430. static VALUE
  2431. rb_io_each_line(int argc, VALUE *argv, VALUE io)
  2432. {
  2433. VALUE str, rs;
  2434. long limit;
  2435. RETURN_ENUMERATOR(io, argc, argv);
  2436. prepare_getline_args(argc, argv, &rs, &limit, io);
  2437. while (!NIL_P(str = rb_io_getline_1(rs, limit, io))) {
  2438. rb_yield(str);
  2439. }
  2440. return io;
  2441. }
  2442. /*
  2443. * call-seq:
  2444. * ios.bytes {|byte| block } -> ios
  2445. * ios.bytes -> an_enumerator
  2446. *
  2447. * ios.each_byte {|byte| block } -> ios
  2448. * ios.each_byte -> an_enumerator
  2449. *
  2450. * Calls the given block once for each byte (0..255) in <em>ios</em>,
  2451. * passing the byte as an argument. The stream must be opened for
  2452. * reading or an <code>IOError</code> will be raised.
  2453. *
  2454. * If no block is given, an enumerator is returned instead.
  2455. *
  2456. * f = File.new("testfile")
  2457. * checksum = 0
  2458. * f.each_byte {|x| checksum ^= x } #=> #<File:testfile>
  2459. * checksum #=> 12
  2460. */
  2461. static VALUE
  2462. rb_io_each_byte(VALUE io)
  2463. {
  2464. rb_io_t *fptr;
  2465. char *p, *e;
  2466. RETURN_ENUMERATOR(io, 0, 0);
  2467. GetOpenFile(io, fptr);
  2468. for (;;) {
  2469. p = fptr->rbuf+fptr->rbuf_off;
  2470. e = p + fptr->rbuf_len;
  2471. while (p < e) {
  2472. fptr->rbuf_off++;
  2473. fptr->rbuf_len--;
  2474. rb_yield(INT2FIX(*p & 0xff));
  2475. p++;
  2476. errno = 0;
  2477. }
  2478. rb_io_check_byte_readable(fptr);
  2479. READ_CHECK(fptr);
  2480. if (io_fillbuf(fptr) < 0) {
  2481. break;
  2482. }
  2483. }
  2484. return io;
  2485. }
  2486. static VALUE
  2487. io_getc(rb_io_t *fptr, rb_encoding *enc)
  2488. {
  2489. int r, n, cr = 0;
  2490. VALUE str;
  2491. if (NEED_READCONV(fptr)) {
  2492. VALUE str = Qnil;
  2493. rb_encoding *read_enc = io_read_encoding(fptr);
  2494. make_readconv(fptr, 0);
  2495. while (1) {
  2496. if (fptr->cbuf_len) {
  2497. r = rb_enc_precise_mbclen(fptr->cbuf+fptr->cbuf_off,
  2498. fptr->cbuf+fptr->cbuf_off+fptr->cbuf_len,
  2499. read_enc);
  2500. if (!MBCLEN_NEEDMORE_P(r))
  2501. break;
  2502. if (fptr->cbuf_len == fptr->cbuf_capa) {
  2503. rb_raise(rb_eIOError, "too long character");
  2504. }
  2505. }
  2506. if (more_char(fptr) == MORE_CHAR_FINISHED) {
  2507. if (fptr->cbuf_len == 0) {
  2508. clear_readconv(fptr);
  2509. return Qnil;
  2510. }
  2511. /* return an unit of an incomplete character just before EOF */
  2512. str = rb_enc_str_new(fptr->cbuf+fptr->cbuf_off, 1, read_enc);
  2513. fptr->cbuf_off += 1;
  2514. fptr->cbuf_len -= 1;
  2515. if (fptr->cbuf_len == 0) clear_readconv(fptr);
  2516. ENC_CODERANGE_SET(str, ENC_CODERANGE_BROKEN);
  2517. return str;
  2518. }
  2519. }
  2520. if (MBCLEN_INVALID_P(r)) {
  2521. r = rb_enc_mbclen(fptr->cbuf+fptr->cbuf_off,
  2522. fptr->cbuf+fptr->cbuf_off+fptr->cbuf_len,
  2523. read_enc);
  2524. io_shift_cbuf(fptr, r, &str);
  2525. cr = ENC_CODERANGE_BROKEN;
  2526. }
  2527. else {
  2528. io_shift_cbuf(fptr, MBCLEN_CHARFOUND_LEN(r), &str);
  2529. cr = ENC_CODERANGE_VALID;
  2530. }
  2531. str = io_enc_str(str, fptr);
  2532. ENC_CODERANGE_SET(str, cr);
  2533. return str;
  2534. }
  2535. if (io_fillbuf(fptr) < 0) {
  2536. return Qnil;
  2537. }
  2538. if (rb_enc_asciicompat(enc) && ISASCII(fptr->rbuf[fptr->rbuf_off])) {
  2539. str = rb_str_new(fptr->rbuf+fptr->rbuf_off, 1);
  2540. fptr->rbuf_off += 1;
  2541. fptr->rbuf_len -= 1;
  2542. cr = ENC_CODERANGE_7BIT;
  2543. }
  2544. else {
  2545. r = rb_enc_precise_mbclen(fptr->rbuf+fptr->rbuf_off, fptr->rbuf+fptr->rbuf_off+fptr->rbuf_len, enc);
  2546. if (MBCLEN_CHARFOUND_P(r) &&
  2547. (n = MBCLEN_CHARFOUND_LEN(r)) <= fptr->rbuf_len) {
  2548. str = rb_str_new(fptr->rbuf+fptr->rbuf_off, n);
  2549. fptr->rbuf_off += n;
  2550. fptr->rbuf_len -= n;
  2551. cr = ENC_CODERANGE_VALID;
  2552. }
  2553. else if (MBCLEN_NEEDMORE_P(r)) {
  2554. str = rb_str_new(fptr->rbuf+fptr->rbuf_off, fptr->rbuf_len);
  2555. fptr->rbuf_len = 0;
  2556. getc_needmore:
  2557. if (io_fillbuf(fptr) != -1) {
  2558. rb_str_cat(str, fptr->rbuf+fptr->rbuf_off, 1);
  2559. fptr->rbuf_off++;
  2560. fptr->rbuf_len--;
  2561. r = rb_enc_precise_mbclen(RSTRING_PTR(str), RSTRING_PTR(str)+RSTRING_LEN(str), enc);
  2562. if (MBCLEN_NEEDMORE_P(r)) {
  2563. goto getc_needmore;
  2564. }
  2565. else if (MBCLEN_CHARFOUND_P(r)) {
  2566. cr = ENC_CODERANGE_VALID;
  2567. }
  2568. }
  2569. }
  2570. else {
  2571. str = rb_str_new(fptr->rbuf+fptr->rbuf_off, 1);
  2572. fptr->rbuf_off++;
  2573. fptr->rbuf_len--;
  2574. }
  2575. }
  2576. if (!cr) cr = ENC_CODERANGE_BROKEN;
  2577. str = io_enc_str(str, fptr);
  2578. ENC_CODERANGE_SET(str, cr);
  2579. return str;
  2580. }
  2581. /*
  2582. * call-seq:
  2583. * ios.chars {|c| block } -> ios
  2584. * ios.chars -> an_enumerator
  2585. *
  2586. * ios.each_char {|c| block } -> ios
  2587. * ios.each_char -> an_enumerator
  2588. *
  2589. * Calls the given block once for each character in <em>ios</em>,
  2590. * passing the character as an argument. The stream must be opened for
  2591. * reading or an <code>IOError</code> will be raised.
  2592. *
  2593. * If no block is given, an enumerator is returned instead.
  2594. *
  2595. * f = File.new("testfile")
  2596. * f.each_char {|c| print c, ' ' } #=> #<File:testfile>
  2597. */
  2598. static VALUE
  2599. rb_io_each_char(VALUE io)
  2600. {
  2601. rb_io_t *fptr;
  2602. rb_encoding *enc;
  2603. VALUE c;
  2604. RETURN_ENUMERATOR(io, 0, 0);
  2605. GetOpenFile(io, fptr);
  2606. rb_io_check_char_readable(fptr);
  2607. enc = io_input_encoding(fptr);
  2608. READ_CHECK(fptr);
  2609. while (!NIL_P(c = io_getc(fptr, enc))) {
  2610. rb_yield(c);
  2611. }
  2612. return io;
  2613. }
  2614. /*
  2615. * call-seq:
  2616. * ios.each_codepoint {|c| block } -> ios
  2617. * ios.codepoints {|c| block } -> ios
  2618. * ios.each_codepoint -> an_enumerator
  2619. * ios.codepoints -> an_enumerator
  2620. *
  2621. * Passes the <code>Integer</code> ordinal of each character in <i>ios</i>,
  2622. * passing the codepoint as an argument. The stream must be opened for
  2623. * reading or an <code>IOError</code> will be raised.
  2624. *
  2625. * If no block is given, an enumerator is returned instead.
  2626. *
  2627. */
  2628. static VALUE
  2629. rb_io_each_codepoint(VALUE io)
  2630. {
  2631. rb_io_t *fptr;
  2632. rb_encoding *enc;
  2633. unsigned int c;
  2634. int r, n;
  2635. RETURN_ENUMERATOR(io, 0, 0);
  2636. GetOpenFile(io, fptr);
  2637. rb_io_check_char_readable(fptr);
  2638. READ_CHECK(fptr);
  2639. if (NEED_READCONV(fptr)) {
  2640. for (;;) {
  2641. make_readconv(fptr, 0);
  2642. for (;;) {
  2643. if (fptr->cbuf_len) {
  2644. if (fptr->encs.enc)
  2645. r = rb_enc_precise_mbclen(fptr->cbuf+fptr->cbuf_off,
  2646. fptr->cbuf+fptr->cbuf_off+fptr->cbuf_len,
  2647. fptr->encs.enc);
  2648. else
  2649. r = ONIGENC_CONSTRUCT_MBCLEN_CHARFOUND(1);
  2650. if (!MBCLEN_NEEDMORE_P(r))
  2651. break;
  2652. if (fptr->cbuf_len == fptr->cbuf_capa) {
  2653. rb_raise(rb_eIOError, "too long character");
  2654. }
  2655. }
  2656. if (more_char(fptr) == MORE_CHAR_FINISHED) {
  2657. clear_readconv(fptr);
  2658. /* ignore an incomplete character before EOF */
  2659. return io;
  2660. }
  2661. }
  2662. if (MBCLEN_INVALID_P(r)) {
  2663. rb_raise(rb_eArgError, "invalid byte sequence in %s",
  2664. rb_enc_name(fptr->encs.enc));
  2665. }
  2666. n = MBCLEN_CHARFOUND_LEN(r);
  2667. if (fptr->encs.enc) {
  2668. c = rb_enc_codepoint(fptr->cbuf+fptr->cbuf_off,
  2669. fptr->cbuf+fptr->cbuf_off+fptr->cbuf_len,
  2670. fptr->encs.enc);
  2671. }
  2672. else {
  2673. c = (unsigned char)fptr->cbuf[fptr->cbuf_off];
  2674. }
  2675. fptr->cbuf_off += n;
  2676. fptr->cbuf_len -= n;
  2677. rb_yield(UINT2NUM(c));
  2678. }
  2679. }
  2680. enc = io_input_encoding(fptr);
  2681. for (;;) {
  2682. if (io_fillbuf(fptr) < 0) {
  2683. return io;
  2684. }
  2685. r = rb_enc_precise_mbclen(fptr->rbuf+fptr->rbuf_off,
  2686. fptr->rbuf+fptr->rbuf_off+fptr->rbuf_len, enc);
  2687. if (MBCLEN_CHARFOUND_P(r) &&
  2688. (n = MBCLEN_CHARFOUND_LEN(r)) <= fptr->rbuf_len) {
  2689. c = rb_enc_codepoint(fptr->rbuf+fptr->rbuf_off,
  2690. fptr->rbuf+fptr->rbuf_off+fptr->rbuf_len, enc);
  2691. fptr->rbuf_off += n;
  2692. fptr->rbuf_len -= n;
  2693. rb_yield(UINT2NUM(c));
  2694. }
  2695. else if (MBCLEN_INVALID_P(r)) {
  2696. rb_raise(rb_eArgError, "invalid byte sequence in %s", rb_enc_name(enc));
  2697. }
  2698. else {
  2699. continue;
  2700. }
  2701. }
  2702. return io;
  2703. }
  2704. /*
  2705. * call-seq:
  2706. * ios.getc -> string or nil
  2707. *
  2708. * Reads a one-character string from <em>ios</em>. Returns
  2709. * <code>nil</code> if called at end of file.
  2710. *
  2711. * f = File.new("testfile")
  2712. * f.getc #=> "h"
  2713. * f.getc #=> "e"
  2714. */
  2715. static VALUE
  2716. rb_io_getc(VALUE io)
  2717. {
  2718. rb_io_t *fptr;
  2719. rb_encoding *enc;
  2720. GetOpenFile(io, fptr);
  2721. rb_io_check_char_readable(fptr);
  2722. enc = io_input_encoding(fptr);
  2723. READ_CHECK(fptr);
  2724. return io_getc(fptr, enc);
  2725. }
  2726. /*
  2727. * call-seq:
  2728. * ios.readchar -> string
  2729. *
  2730. * Reads a one-character string from <em>ios</em>. Raises an
  2731. * <code>EOFError</code> on end of file.
  2732. *
  2733. * f = File.new("testfile")
  2734. * f.readchar #=> "h"
  2735. * f.readchar #=> "e"
  2736. */
  2737. static VALUE
  2738. rb_io_readchar(VALUE io)
  2739. {
  2740. VALUE c = rb_io_getc(io);
  2741. if (NIL_P(c)) {
  2742. rb_eof_error();
  2743. }
  2744. return c;
  2745. }
  2746. /*
  2747. * call-seq:
  2748. * ios.getbyte -> fixnum or nil
  2749. *
  2750. * Gets the next 8-bit byte (0..255) from <em>ios</em>. Returns
  2751. * <code>nil</code> if called at end of file.
  2752. *
  2753. * f = File.new("testfile")
  2754. * f.getbyte #=> 84
  2755. * f.getbyte #=> 104
  2756. */
  2757. VALUE
  2758. rb_io_getbyte(VALUE io)
  2759. {
  2760. rb_io_t *fptr;
  2761. int c;
  2762. GetOpenFile(io, fptr);
  2763. rb_io_check_byte_readable(fptr);
  2764. READ_CHECK(fptr);
  2765. if (fptr->fd == 0 && (fptr->mode & FMODE_TTY) && TYPE(rb_stdout) == T_FILE) {
  2766. rb_io_t *ofp;
  2767. GetOpenFile(rb_stdout, ofp);
  2768. if (ofp->mode & FMODE_TTY) {
  2769. rb_io_flush(rb_stdout);
  2770. }
  2771. }
  2772. if (io_fillbuf(fptr) < 0) {
  2773. return Qnil;
  2774. }
  2775. fptr->rbuf_off++;
  2776. fptr->rbuf_len--;
  2777. c = (unsigned char)fptr->rbuf[fptr->rbuf_off-1];
  2778. return INT2FIX(c & 0xff);
  2779. }
  2780. /*
  2781. * call-seq:
  2782. * ios.readbyte -> fixnum
  2783. *
  2784. * Reads a byte as with <code>IO#getbyte</code>, but raises an
  2785. * <code>EOFError</code> on end of file.
  2786. */
  2787. static VALUE
  2788. rb_io_readbyte(VALUE io)
  2789. {
  2790. VALUE c = rb_io_getbyte(io);
  2791. if (NIL_P(c)) {
  2792. rb_eof_error();
  2793. }
  2794. return c;
  2795. }
  2796. /*
  2797. * call-seq:
  2798. * ios.ungetbyte(string) -> nil
  2799. * ios.ungetbyte(integer) -> nil
  2800. *
  2801. * Pushes back bytes (passed as a parameter) onto <em>ios</em>,
  2802. * such that a subsequent buffered read will return it. Only one byte
  2803. * may be pushed back before a subsequent read operation (that is,
  2804. * you will be able to read only the last of several bytes that have been pushed
  2805. * back). Has no effect with unbuffered reads (such as <code>IO#sysread</code>).
  2806. *
  2807. * f = File.new("testfile") #=> #<File:testfile>
  2808. * b = f.getbyte #=> 0x38
  2809. * f.ungetbyte(b) #=> nil
  2810. * f.getbyte #=> 0x38
  2811. */
  2812. VALUE
  2813. rb_io_ungetbyte(VALUE io, VALUE b)
  2814. {
  2815. rb_io_t *fptr;
  2816. GetOpenFile(io, fptr);
  2817. rb_io_check_byte_readable(fptr);
  2818. if (NIL_P(b)) return Qnil;
  2819. if (FIXNUM_P(b)) {
  2820. char cc = FIX2INT(b);
  2821. b = rb_str_new(&cc, 1);
  2822. }
  2823. else {
  2824. SafeStringValue(b);
  2825. }
  2826. io_ungetbyte(b, fptr);
  2827. return Qnil;
  2828. }
  2829. /*
  2830. * call-seq:
  2831. * ios.ungetc(string) -> nil
  2832. *
  2833. * Pushes back one character (passed as a parameter) onto <em>ios</em>,
  2834. * such that a subsequent buffered character read will return it. Only one character
  2835. * may be pushed back before a subsequent read operation (that is,
  2836. * you will be able to read only the last of several characters that have been pushed
  2837. * back). Has no effect with unbuffered reads (such as <code>IO#sysread</code>).
  2838. *
  2839. * f = File.new("testfile") #=> #<File:testfile>
  2840. * c = f.getc #=> "8"
  2841. * f.ungetc(c) #=> nil
  2842. * f.getc #=> "8"
  2843. */
  2844. VALUE
  2845. rb_io_ungetc(VALUE io, VALUE c)
  2846. {
  2847. rb_io_t *fptr;
  2848. long len;
  2849. GetOpenFile(io, fptr);
  2850. rb_io_check_char_readable(fptr);
  2851. if (NIL_P(c)) return Qnil;
  2852. if (FIXNUM_P(c)) {
  2853. int cc = FIX2INT(c);
  2854. rb_encoding *enc = io_read_encoding(fptr);
  2855. char buf[16];
  2856. c = rb_str_new(buf, rb_enc_mbcput(cc, buf, enc));
  2857. }
  2858. else {
  2859. SafeStringValue(c);
  2860. }
  2861. if (NEED_READCONV(fptr)) {
  2862. len = RSTRING_LEN(c);
  2863. #if SIZEOF_LONG > SIZEOF_INT
  2864. if (len > INT_MAX)
  2865. rb_raise(rb_eIOError, "ungetc failed");
  2866. #endif
  2867. make_readconv(fptr, (int)len);
  2868. if (fptr->cbuf_capa - fptr->cbuf_len < len)
  2869. rb_raise(rb_eIOError, "ungetc failed");
  2870. if (fptr->cbuf_off < len) {
  2871. MEMMOVE(fptr->cbuf+fptr->cbuf_capa-fptr->cbuf_len,
  2872. fptr->cbuf+fptr->cbuf_off,
  2873. char, fptr->cbuf_len);
  2874. fptr->cbuf_off = fptr->cbuf_capa-fptr->cbuf_len;
  2875. }
  2876. fptr->cbuf_off -= (int)len;
  2877. fptr->cbuf_len += (int)len;
  2878. MEMMOVE(fptr->cbuf+fptr->cbuf_off, RSTRING_PTR(c), char, len);
  2879. }
  2880. else {
  2881. io_ungetbyte(c, fptr);
  2882. }
  2883. return Qnil;
  2884. }
  2885. /*
  2886. * call-seq:
  2887. * ios.isatty -> true or false
  2888. * ios.tty? -> true or false
  2889. *
  2890. * Returns <code>true</code> if <em>ios</em> is associated with a
  2891. * terminal device (tty), <code>false</code> otherwise.
  2892. *
  2893. * File.new("testfile").isatty #=> false
  2894. * File.new("/dev/tty").isatty #=> true
  2895. */
  2896. static VALUE
  2897. rb_io_isatty(VALUE io)
  2898. {
  2899. rb_io_t *fptr;
  2900. GetOpenFile(io, fptr);
  2901. if (isatty(fptr->fd) == 0)
  2902. return Qfalse;
  2903. return Qtrue;
  2904. }
  2905. #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
  2906. /*
  2907. * call-seq:
  2908. * ios.close_on_exec? -> true or false
  2909. *
  2910. * Returns <code>true</code> if <em>ios</em> will be closed on exec.
  2911. *
  2912. * f = open("/dev/null")
  2913. * f.close_on_exec? #=> false
  2914. * f.close_on_exec = true
  2915. * f.close_on_exec? #=> true
  2916. * f.close_on_exec = false
  2917. * f.close_on_exec? #=> false
  2918. */
  2919. static VALUE
  2920. rb_io_close_on_exec_p(VALUE io)
  2921. {
  2922. rb_io_t *fptr;
  2923. VALUE write_io;
  2924. int fd, ret;
  2925. write_io = GetWriteIO(io);
  2926. if (io != write_io) {
  2927. GetOpenFile(write_io, fptr);
  2928. if (fptr && 0 <= (fd = fptr->fd)) {
  2929. if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
  2930. if (!(ret & FD_CLOEXEC)) return Qfalse;
  2931. }
  2932. }
  2933. GetOpenFile(io, fptr);
  2934. if (fptr && 0 <= (fd = fptr->fd)) {
  2935. if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
  2936. if (!(ret & FD_CLOEXEC)) return Qfalse;
  2937. }
  2938. return Qtrue;
  2939. }
  2940. #else
  2941. #define rb_io_close_on_exec_p rb_f_notimplement
  2942. #endif
  2943. #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
  2944. /*
  2945. * call-seq:
  2946. * ios.close_on_exec = bool -> true or false
  2947. *
  2948. * Sets a close-on-exec flag.
  2949. *
  2950. * f = open("/dev/null")
  2951. * f.close_on_exec = true
  2952. * system("cat", "/proc/self/fd/#{f.fileno}") # cat: /proc/self/fd/3: No such file or directory
  2953. * f.closed? #=> false
  2954. */
  2955. static VALUE
  2956. rb_io_set_close_on_exec(VALUE io, VALUE arg)
  2957. {
  2958. int flag = RTEST(arg) ? FD_CLOEXEC : 0;
  2959. rb_io_t *fptr;
  2960. VALUE write_io;
  2961. int fd, ret;
  2962. write_io = GetWriteIO(io);
  2963. if (io != write_io) {
  2964. GetOpenFile(write_io, fptr);
  2965. if (fptr && 0 <= (fd = fptr->fd)) {
  2966. if ((ret = fcntl(fptr->fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
  2967. if ((ret & FD_CLOEXEC) != flag) {
  2968. ret = (ret & ~FD_CLOEXEC) | flag;
  2969. ret = fcntl(fd, F_SETFD, ret);
  2970. if (ret == -1) rb_sys_fail_path(fptr->pathv);
  2971. }
  2972. }
  2973. }
  2974. GetOpenFile(io, fptr);
  2975. if (fptr && 0 <= (fd = fptr->fd)) {
  2976. if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
  2977. if ((ret & FD_CLOEXEC) != flag) {
  2978. ret = (ret & ~FD_CLOEXEC) | flag;
  2979. ret = fcntl(fd, F_SETFD, ret);
  2980. if (ret == -1) rb_sys_fail_path(fptr->pathv);
  2981. }
  2982. }
  2983. return Qnil;
  2984. }
  2985. #else
  2986. #define rb_io_set_close_on_exec rb_f_notimplement
  2987. #endif
  2988. #define FMODE_PREP (1<<16)
  2989. #define IS_PREP_STDIO(f) ((f)->mode & FMODE_PREP)
  2990. #define PREP_STDIO_NAME(f) (RSTRING_PTR((f)->pathv))
  2991. static VALUE
  2992. finish_writeconv(rb_io_t *fptr, int noalloc)
  2993. {
  2994. unsigned char *ds, *dp, *de;
  2995. rb_econv_result_t res;
  2996. if (!fptr->wbuf) {
  2997. unsigned char buf[1024];
  2998. long r;
  2999. res = econv_destination_buffer_full;
  3000. while (res == econv_destination_buffer_full) {
  3001. ds = dp = buf;
  3002. de = buf + sizeof(buf);
  3003. res = rb_econv_convert(fptr->writeconv, NULL, NULL, &dp, de, 0);
  3004. while (dp-ds) {
  3005. retry:
  3006. r = rb_write_internal(fptr->fd, ds, dp-ds);
  3007. if (r == dp-ds)
  3008. break;
  3009. if (0 <= r) {
  3010. ds += r;
  3011. }
  3012. if (rb_io_wait_writable(fptr->fd)) {
  3013. if (fptr->fd < 0)
  3014. return noalloc ? Qtrue : rb_exc_new3(rb_eIOError, rb_str_new_cstr("closed stream"));
  3015. goto retry;
  3016. }
  3017. return noalloc ? Qtrue : INT2NUM(errno);
  3018. }
  3019. if (res == econv_invalid_byte_sequence ||
  3020. res == econv_incomplete_input ||
  3021. res == econv_undefined_conversion) {
  3022. return noalloc ? Qtrue : rb_econv_make_exception(fptr->writeconv);
  3023. }
  3024. }
  3025. return Qnil;
  3026. }
  3027. res = econv_destination_buffer_full;
  3028. while (res == econv_destination_buffer_full) {
  3029. if (fptr->wbuf_len == fptr->wbuf_capa) {
  3030. if (io_fflush(fptr) < 0)
  3031. return noalloc ? Qtrue : INT2NUM(errno);
  3032. }
  3033. ds = dp = (unsigned char *)fptr->wbuf + fptr->wbuf_off + fptr->wbuf_len;
  3034. de = (unsigned char *)fptr->wbuf + fptr->wbuf_capa;
  3035. res = rb_econv_convert(fptr->writeconv, NULL, NULL, &dp, de, 0);
  3036. fptr->wbuf_len += (int)(dp - ds);
  3037. if (res == econv_invalid_byte_sequence ||
  3038. res == econv_incomplete_input ||
  3039. res == econv_undefined_conversion) {
  3040. return noalloc ? Qtrue : rb_econv_make_exception(fptr->writeconv);
  3041. }
  3042. }
  3043. return Qnil;
  3044. }
  3045. struct finish_writeconv_arg {
  3046. rb_io_t *fptr;
  3047. int noalloc;
  3048. };
  3049. static VALUE
  3050. finish_writeconv_sync(VALUE arg)
  3051. {
  3052. struct finish_writeconv_arg *p = (struct finish_writeconv_arg *)arg;
  3053. return finish_writeconv(p->fptr, p->noalloc);
  3054. }
  3055. static void
  3056. fptr_finalize(rb_io_t *fptr, int noraise)
  3057. {
  3058. VALUE err = Qnil;
  3059. if (fptr->writeconv) {
  3060. if (fptr->write_lock) {
  3061. struct finish_writeconv_arg arg;
  3062. arg.fptr = fptr;
  3063. arg.noalloc = noraise;
  3064. err = rb_mutex_synchronize(fptr->write_lock, finish_writeconv_sync, (VALUE)&arg);
  3065. }
  3066. else {
  3067. err = finish_writeconv(fptr, noraise);
  3068. }
  3069. }
  3070. if (fptr->wbuf_len) {
  3071. if (io_fflush(fptr) < 0 && NIL_P(err))
  3072. err = noraise ? Qtrue : INT2NUM(errno);
  3073. }
  3074. if (IS_PREP_STDIO(fptr) || fptr->fd <= 2) {
  3075. goto skip_fd_close;
  3076. }
  3077. if (fptr->stdio_file) {
  3078. /* fptr->stdio_file is deallocated anyway
  3079. * even if fclose failed. */
  3080. if (fclose(fptr->stdio_file) < 0 && NIL_P(err))
  3081. err = noraise ? Qtrue : INT2NUM(errno);
  3082. }
  3083. else if (0 <= fptr->fd) {
  3084. /* fptr->fd may be closed even if close fails.
  3085. * POSIX doesn't specify it.
  3086. * We assumes it is closed. */
  3087. if (close(fptr->fd) < 0 && NIL_P(err))
  3088. err = noraise ? Qtrue : INT2NUM(errno);
  3089. }
  3090. skip_fd_close:
  3091. fptr->fd = -1;
  3092. fptr->stdio_file = 0;
  3093. fptr->mode &= ~(FMODE_READABLE|FMODE_WRITABLE);
  3094. if (!NIL_P(err) && !noraise) {
  3095. switch(TYPE(err)) {
  3096. case T_FIXNUM:
  3097. case T_BIGNUM:
  3098. errno = NUM2INT(err);
  3099. rb_sys_fail_path(fptr->pathv);
  3100. default:
  3101. rb_exc_raise(err);
  3102. }
  3103. }
  3104. }
  3105. static void
  3106. rb_io_fptr_cleanup(rb_io_t *fptr, int noraise)
  3107. {
  3108. if (fptr->finalize) {
  3109. (*fptr->finalize)(fptr, noraise);
  3110. }
  3111. else {
  3112. fptr_finalize(fptr, noraise);
  3113. }
  3114. }
  3115. static void
  3116. clear_readconv(rb_io_t *fptr)
  3117. {
  3118. if (fptr->readconv) {
  3119. rb_econv_close(fptr->readconv);
  3120. fptr->readconv = NULL;
  3121. }
  3122. if (fptr->cbuf) {
  3123. free(fptr->cbuf);
  3124. fptr->cbuf = NULL;
  3125. }
  3126. }
  3127. static void
  3128. clear_writeconv(rb_io_t *fptr)
  3129. {
  3130. if (fptr->writeconv) {
  3131. rb_econv_close(fptr->writeconv);
  3132. fptr->writeconv = NULL;
  3133. }
  3134. fptr->writeconv_initialized = 0;
  3135. }
  3136. static void
  3137. clear_codeconv(rb_io_t *fptr)
  3138. {
  3139. clear_readconv(fptr);
  3140. clear_writeconv(fptr);
  3141. }
  3142. int
  3143. rb_io_fptr_finalize(rb_io_t *fptr)
  3144. {
  3145. if (!fptr) return 0;
  3146. fptr->pathv = Qnil;
  3147. fptr->write_lock = 0;
  3148. if (0 <= fptr->fd)
  3149. rb_io_fptr_cleanup(fptr, TRUE);
  3150. if (fptr->rbuf) {
  3151. free(fptr->rbuf);
  3152. fptr->rbuf = 0;
  3153. }
  3154. if (fptr->wbuf) {
  3155. free(fptr->wbuf);
  3156. fptr->wbuf = 0;
  3157. }
  3158. clear_codeconv(fptr);
  3159. free(fptr);
  3160. return 1;
  3161. }
  3162. size_t rb_econv_memsize(rb_econv_t *);
  3163. size_t
  3164. rb_io_memsize(rb_io_t *fptr)
  3165. {
  3166. size_t size = sizeof(rb_io_t);
  3167. size += fptr->rbuf_capa;
  3168. size += fptr->wbuf_capa;
  3169. size += fptr->cbuf_capa;
  3170. if (fptr->readconv) size += rb_econv_memsize(fptr->readconv);
  3171. if (fptr->writeconv) size += rb_econv_memsize(fptr->writeconv);
  3172. return size;
  3173. }
  3174. VALUE
  3175. rb_io_close(VALUE io)
  3176. {
  3177. rb_io_t *fptr;
  3178. int fd;
  3179. VALUE write_io;
  3180. rb_io_t *write_fptr;
  3181. write_io = GetWriteIO(io);
  3182. if (io != write_io) {
  3183. write_fptr = RFILE(write_io)->fptr;
  3184. if (write_fptr && 0 <= write_fptr->fd) {
  3185. rb_io_fptr_cleanup(write_fptr, TRUE);
  3186. }
  3187. }
  3188. fptr = RFILE(io)->fptr;
  3189. if (!fptr) return Qnil;
  3190. if (fptr->fd < 0) return Qnil;
  3191. fd = fptr->fd;
  3192. rb_io_fptr_cleanup(fptr, FALSE);
  3193. rb_thread_fd_close(fd);
  3194. if (fptr->pid) {
  3195. rb_syswait(fptr->pid);
  3196. fptr->pid = 0;
  3197. }
  3198. return Qnil;
  3199. }
  3200. /*
  3201. * call-seq:
  3202. * ios.close -> nil
  3203. *
  3204. * Closes <em>ios</em> and flushes any pending writes to the operating
  3205. * system. The stream is unavailable for any further data operations;
  3206. * an <code>IOError</code> is raised if such an attempt is made. I/O
  3207. * streams are automatically closed when they are claimed by the
  3208. * garbage collector.
  3209. *
  3210. * If <em>ios</em> is opened by <code>IO.popen</code>,
  3211. * <code>close</code> sets <code>$?</code>.
  3212. */
  3213. static VALUE
  3214. rb_io_close_m(VALUE io)
  3215. {
  3216. if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(io)) {
  3217. rb_raise(rb_eSecurityError, "Insecure: can't close");
  3218. }
  3219. rb_io_check_closed(RFILE(io)->fptr);
  3220. rb_io_close(io);
  3221. return Qnil;
  3222. }
  3223. static VALUE
  3224. io_call_close(VALUE io)
  3225. {
  3226. return rb_funcall(io, rb_intern("close"), 0, 0);
  3227. }
  3228. static VALUE
  3229. io_close(VALUE io)
  3230. {
  3231. return rb_rescue(io_call_close, io, 0, 0);
  3232. }
  3233. /*
  3234. * call-seq:
  3235. * ios.closed? -> true or false
  3236. *
  3237. * Returns <code>true</code> if <em>ios</em> is completely closed (for
  3238. * duplex streams, both reader and writer), <code>false</code>
  3239. * otherwise.
  3240. *
  3241. * f = File.new("testfile")
  3242. * f.close #=> nil
  3243. * f.closed? #=> true
  3244. * f = IO.popen("/bin/sh","r+")
  3245. * f.close_write #=> nil
  3246. * f.closed? #=> false
  3247. * f.close_read #=> nil
  3248. * f.closed? #=> true
  3249. */
  3250. static VALUE
  3251. rb_io_closed(VALUE io)
  3252. {
  3253. rb_io_t *fptr;
  3254. VALUE write_io;
  3255. rb_io_t *write_fptr;
  3256. write_io = GetWriteIO(io);
  3257. if (io != write_io) {
  3258. write_fptr = RFILE(write_io)->fptr;
  3259. if (write_fptr && 0 <= write_fptr->fd) {
  3260. return Qfalse;
  3261. }
  3262. }
  3263. fptr = RFILE(io)->fptr;
  3264. rb_io_check_initialized(fptr);
  3265. return 0 <= fptr->fd ? Qfalse : Qtrue;
  3266. }
  3267. /*
  3268. * call-seq:
  3269. * ios.close_read -> nil
  3270. *
  3271. * Closes the read end of a duplex I/O stream (i.e., one that contains
  3272. * both a read and a write stream, such as a pipe). Will raise an
  3273. * <code>IOError</code> if the stream is not duplexed.
  3274. *
  3275. * f = IO.popen("/bin/sh","r+")
  3276. * f.close_read
  3277. * f.readlines
  3278. *
  3279. * <em>produces:</em>
  3280. *
  3281. * prog.rb:3:in `readlines': not opened for reading (IOError)
  3282. * from prog.rb:3
  3283. */
  3284. static VALUE
  3285. rb_io_close_read(VALUE io)
  3286. {
  3287. rb_io_t *fptr;
  3288. VALUE write_io;
  3289. if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(io)) {
  3290. rb_raise(rb_eSecurityError, "Insecure: can't close");
  3291. }
  3292. GetOpenFile(io, fptr);
  3293. if (is_socket(fptr->fd, fptr->pathv)) {
  3294. #ifndef SHUT_RD
  3295. # define SHUT_RD 0
  3296. #endif
  3297. if (shutdown(fptr->fd, SHUT_RD) < 0)
  3298. rb_sys_fail_path(fptr->pathv);
  3299. fptr->mode &= ~FMODE_READABLE;
  3300. if (!(fptr->mode & FMODE_WRITABLE))
  3301. return rb_io_close(io);
  3302. return Qnil;
  3303. }
  3304. write_io = GetWriteIO(io);
  3305. if (io != write_io) {
  3306. rb_io_t *wfptr;
  3307. rb_io_fptr_cleanup(fptr, FALSE);
  3308. GetOpenFile(write_io, wfptr);
  3309. RFILE(io)->fptr = wfptr;
  3310. RFILE(write_io)->fptr = NULL;
  3311. rb_io_fptr_finalize(fptr);
  3312. return Qnil;
  3313. }
  3314. if (fptr->mode & FMODE_WRITABLE) {
  3315. rb_raise(rb_eIOError, "closing non-duplex IO for reading");
  3316. }
  3317. return rb_io_close(io);
  3318. }
  3319. /*
  3320. * call-seq:
  3321. * ios.close_write -> nil
  3322. *
  3323. * Closes the write end of a duplex I/O stream (i.e., one that contains
  3324. * both a read and a write stream, such as a pipe). Will raise an
  3325. * <code>IOError</code> if the stream is not duplexed.
  3326. *
  3327. * f = IO.popen("/bin/sh","r+")
  3328. * f.close_write
  3329. * f.print "nowhere"
  3330. *
  3331. * <em>produces:</em>
  3332. *
  3333. * prog.rb:3:in `write': not opened for writing (IOError)
  3334. * from prog.rb:3:in `print'
  3335. * from prog.rb:3
  3336. */
  3337. static VALUE
  3338. rb_io_close_write(VALUE io)
  3339. {
  3340. rb_io_t *fptr;
  3341. VALUE write_io;
  3342. if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(io)) {
  3343. rb_raise(rb_eSecurityError, "Insecure: can't close");
  3344. }
  3345. write_io = GetWriteIO(io);
  3346. GetOpenFile(write_io, fptr);
  3347. if (is_socket(fptr->fd, fptr->pathv)) {
  3348. #ifndef SHUT_WR
  3349. # define SHUT_WR 1
  3350. #endif
  3351. if (shutdown(fptr->fd, SHUT_WR) < 0)
  3352. rb_sys_fail_path(fptr->pathv);
  3353. fptr->mode &= ~FMODE_WRITABLE;
  3354. if (!(fptr->mode & FMODE_READABLE))
  3355. return rb_io_close(write_io);
  3356. return Qnil;
  3357. }
  3358. if (fptr->mode & FMODE_READABLE) {
  3359. rb_raise(rb_eIOError, "closing non-duplex IO for writing");
  3360. }
  3361. rb_io_close(write_io);
  3362. if (io != write_io) {
  3363. GetOpenFile(io, fptr);
  3364. fptr->tied_io_for_writing = 0;
  3365. fptr->mode &= ~FMODE_DUPLEX;
  3366. }
  3367. return Qnil;
  3368. }
  3369. /*
  3370. * call-seq:
  3371. * ios.sysseek(offset, whence=IO::SEEK_SET) -> integer
  3372. *
  3373. * Seeks to a given <i>offset</i> in the stream according to the value
  3374. * of <i>whence</i> (see <code>IO#seek</code> for values of
  3375. * <i>whence</i>). Returns the new offset into the file.
  3376. *
  3377. * f = File.new("testfile")
  3378. * f.sysseek(-13, IO::SEEK_END) #=> 53
  3379. * f.sysread(10) #=> "And so on."
  3380. */
  3381. static VALUE
  3382. rb_io_sysseek(int argc, VALUE *argv, VALUE io)
  3383. {
  3384. VALUE offset, ptrname;
  3385. int whence = SEEK_SET;
  3386. rb_io_t *fptr;
  3387. off_t pos;
  3388. if (rb_scan_args(argc, argv, "11", &offset, &ptrname) == 2) {
  3389. whence = NUM2INT(ptrname);
  3390. }
  3391. pos = NUM2OFFT(offset);
  3392. GetOpenFile(io, fptr);
  3393. if ((fptr->mode & FMODE_READABLE) &&
  3394. (READ_DATA_BUFFERED(fptr) || READ_CHAR_PENDING(fptr))) {
  3395. rb_raise(rb_eIOError, "sysseek for buffered IO");
  3396. }
  3397. if ((fptr->mode & FMODE_WRITABLE) && fptr->wbuf_len) {
  3398. rb_warn("sysseek for buffered IO");
  3399. }
  3400. errno = 0;
  3401. pos = lseek(fptr->fd, pos, whence);
  3402. if (pos == -1 && errno) rb_sys_fail_path(fptr->pathv);
  3403. return OFFT2NUM(pos);
  3404. }
  3405. /*
  3406. * call-seq:
  3407. * ios.syswrite(string) -> integer
  3408. *
  3409. * Writes the given string to <em>ios</em> using a low-level write.
  3410. * Returns the number of bytes written. Do not mix with other methods
  3411. * that write to <em>ios</em> or you may get unpredictable results.
  3412. * Raises <code>SystemCallError</code> on error.
  3413. *
  3414. * f = File.new("out", "w")
  3415. * f.syswrite("ABCDEF") #=> 6
  3416. */
  3417. static VALUE
  3418. rb_io_syswrite(VALUE io, VALUE str)
  3419. {
  3420. rb_io_t *fptr;
  3421. long n;
  3422. rb_secure(4);
  3423. if (TYPE(str) != T_STRING)
  3424. str = rb_obj_as_string(str);
  3425. io = GetWriteIO(io);
  3426. GetOpenFile(io, fptr);
  3427. rb_io_check_writable(fptr);
  3428. if (fptr->wbuf_len) {
  3429. rb_warn("syswrite for buffered IO");
  3430. }
  3431. if (!rb_thread_fd_writable(fptr->fd)) {
  3432. rb_io_check_closed(fptr);
  3433. }
  3434. n = write(fptr->fd, RSTRING_PTR(str), RSTRING_LEN(str));
  3435. if (n == -1) rb_sys_fail_path(fptr->pathv);
  3436. return LONG2FIX(n);
  3437. }
  3438. /*
  3439. * call-seq:
  3440. * ios.sysread(integer[, outbuf]) -> string
  3441. *
  3442. * Reads <i>integer</i> bytes from <em>ios</em> using a low-level
  3443. * read and returns them as a string. Do not mix with other methods
  3444. * that read from <em>ios</em> or you may get unpredictable results.
  3445. * If the optional <i>outbuf</i> argument is present, it must reference
  3446. * a String, which will receive the data.
  3447. * Raises <code>SystemCallError</code> on error and
  3448. * <code>EOFError</code> at end of file.
  3449. *
  3450. * f = File.new("testfile")
  3451. * f.sysread(16) #=> "This is line one"
  3452. */
  3453. static VALUE
  3454. rb_io_sysread(int argc, VALUE *argv, VALUE io)
  3455. {
  3456. VALUE len, str;
  3457. rb_io_t *fptr;
  3458. long n, ilen;
  3459. rb_scan_args(argc, argv, "11", &len, &str);
  3460. ilen = NUM2LONG(len);
  3461. if (NIL_P(str)) {
  3462. str = rb_str_new(0, ilen);
  3463. }
  3464. else {
  3465. StringValue(str);
  3466. rb_str_modify(str);
  3467. rb_str_resize(str, ilen);
  3468. }
  3469. if (ilen == 0) return str;
  3470. GetOpenFile(io, fptr);
  3471. rb_io_check_byte_readable(fptr);
  3472. if (READ_DATA_BUFFERED(fptr)) {
  3473. rb_raise(rb_eIOError, "sysread for buffered IO");
  3474. }
  3475. n = fptr->fd;
  3476. rb_thread_wait_fd(fptr->fd);
  3477. rb_io_check_closed(fptr);
  3478. rb_str_locktmp(str);
  3479. n = rb_read_internal(fptr->fd, RSTRING_PTR(str), ilen);
  3480. rb_str_unlocktmp(str);
  3481. if (n == -1) {
  3482. rb_sys_fail_path(fptr->pathv);
  3483. }
  3484. rb_str_set_len(str, n);
  3485. if (n == 0 && ilen > 0) {
  3486. rb_eof_error();
  3487. }
  3488. rb_str_resize(str, n);
  3489. OBJ_TAINT(str);
  3490. return str;
  3491. }
  3492. VALUE
  3493. rb_io_binmode(VALUE io)
  3494. {
  3495. rb_io_t *fptr;
  3496. GetOpenFile(io, fptr);
  3497. if (fptr->readconv)
  3498. rb_econv_binmode(fptr->readconv);
  3499. if (fptr->writeconv)
  3500. rb_econv_binmode(fptr->writeconv);
  3501. fptr->mode |= FMODE_BINMODE;
  3502. fptr->mode &= ~FMODE_TEXTMODE;
  3503. fptr->writeconv_pre_ecflags &= ~(ECONV_UNIVERSAL_NEWLINE_DECORATOR|ECONV_CRLF_NEWLINE_DECORATOR|ECONV_CR_NEWLINE_DECORATOR);
  3504. return io;
  3505. }
  3506. VALUE
  3507. rb_io_ascii8bit_binmode(VALUE io)
  3508. {
  3509. rb_io_t *fptr;
  3510. GetOpenFile(io, fptr);
  3511. if (fptr->readconv) {
  3512. rb_econv_close(fptr->readconv);
  3513. fptr->readconv = NULL;
  3514. }
  3515. if (fptr->writeconv) {
  3516. rb_econv_close(fptr->writeconv);
  3517. fptr->writeconv = NULL;
  3518. }
  3519. fptr->mode |= FMODE_BINMODE;
  3520. fptr->mode &= ~FMODE_TEXTMODE;
  3521. fptr->encs.enc = rb_ascii8bit_encoding();
  3522. fptr->encs.enc2 = NULL;
  3523. fptr->encs.ecflags = 0;
  3524. fptr->encs.ecopts = Qnil;
  3525. clear_codeconv(fptr);
  3526. return io;
  3527. }
  3528. /*
  3529. * call-seq:
  3530. * ios.binmode -> ios
  3531. *
  3532. * Puts <em>ios</em> into binary mode.
  3533. * Once a stream is in binary mode, it cannot be reset to nonbinary mode.
  3534. *
  3535. * - newline conversion disabled
  3536. * - encoding conversion disabled
  3537. * - content is treated as ASCII-8BIT
  3538. *
  3539. */
  3540. static VALUE
  3541. rb_io_binmode_m(VALUE io)
  3542. {
  3543. VALUE write_io;
  3544. rb_io_ascii8bit_binmode(io);
  3545. write_io = GetWriteIO(io);
  3546. if (write_io != io)
  3547. rb_io_ascii8bit_binmode(write_io);
  3548. return io;
  3549. }
  3550. /*
  3551. * call-seq:
  3552. * ios.binmode? -> true or false
  3553. *
  3554. * Returns <code>true</code> if <em>ios</em> is binmode.
  3555. */
  3556. static VALUE
  3557. rb_io_binmode_p(VALUE io)
  3558. {
  3559. rb_io_t *fptr;
  3560. GetOpenFile(io, fptr);
  3561. return fptr->mode & FMODE_BINMODE ? Qtrue : Qfalse;
  3562. }
  3563. static const char*
  3564. rb_io_fmode_modestr(int fmode)
  3565. {
  3566. # define MODE_BTMODE(a,b,c) ((fmode & FMODE_BINMODE) ? (b) : \
  3567. (fmode & FMODE_TEXTMODE) ? (c) : (a))
  3568. if (fmode & FMODE_APPEND) {
  3569. if ((fmode & FMODE_READWRITE) == FMODE_READWRITE) {
  3570. return MODE_BTMODE("a+", "ab+", "at+");
  3571. }
  3572. return MODE_BTMODE("a", "ab", "at");
  3573. }
  3574. switch (fmode & FMODE_READWRITE) {
  3575. case FMODE_READABLE:
  3576. return MODE_BTMODE("r", "rb", "rt");
  3577. case FMODE_WRITABLE:
  3578. return MODE_BTMODE("w", "wb", "wt");
  3579. case FMODE_READWRITE:
  3580. if (fmode & FMODE_CREATE) {
  3581. return MODE_BTMODE("w+", "wb+", "wt+");
  3582. }
  3583. return MODE_BTMODE("r+", "rb+", "rt+");
  3584. }
  3585. rb_raise(rb_eArgError, "invalid access fmode 0x%x", fmode);
  3586. return NULL; /* not reached */
  3587. }
  3588. static int
  3589. io_encname_bom_p(const char *name, long len)
  3590. {
  3591. static const char bom_prefix[] = "bom|utf-";
  3592. enum {bom_prefix_len = (int)sizeof(bom_prefix) - 1};
  3593. if (!len) {
  3594. const char *p = strchr(name, ':');
  3595. len = p ? (long)(p - name) : (long)strlen(name);
  3596. }
  3597. return len > bom_prefix_len && STRNCASECMP(name, bom_prefix, bom_prefix_len) == 0;
  3598. }
  3599. int
  3600. rb_io_modestr_fmode(const char *modestr)
  3601. {
  3602. int fmode = 0;
  3603. const char *m = modestr, *p = NULL;
  3604. switch (*m++) {
  3605. case 'r':
  3606. fmode |= FMODE_READABLE;
  3607. break;
  3608. case 'w':
  3609. fmode |= FMODE_WRITABLE | FMODE_TRUNC | FMODE_CREATE;
  3610. break;
  3611. case 'a':
  3612. fmode |= FMODE_WRITABLE | FMODE_APPEND | FMODE_CREATE;
  3613. break;
  3614. default:
  3615. error:
  3616. rb_raise(rb_eArgError, "invalid access mode %s", modestr);
  3617. }
  3618. while (*m) {
  3619. switch (*m++) {
  3620. case 'b':
  3621. fmode |= FMODE_BINMODE;
  3622. break;
  3623. case 't':
  3624. fmode |= FMODE_TEXTMODE;
  3625. break;
  3626. case '+':
  3627. fmode |= FMODE_READWRITE;
  3628. break;
  3629. default:
  3630. goto error;
  3631. case ':':
  3632. p = m;
  3633. goto finished;
  3634. }
  3635. }
  3636. finished:
  3637. if ((fmode & FMODE_BINMODE) && (fmode & FMODE_TEXTMODE))
  3638. goto error;
  3639. if (p && io_encname_bom_p(p, 0))
  3640. fmode |= FMODE_SETENC_BY_BOM;
  3641. return fmode;
  3642. }
  3643. int
  3644. rb_io_oflags_fmode(int oflags)
  3645. {
  3646. int fmode = 0;
  3647. switch (oflags & (O_RDONLY|O_WRONLY|O_RDWR)) {
  3648. case O_RDONLY:
  3649. fmode = FMODE_READABLE;
  3650. break;
  3651. case O_WRONLY:
  3652. fmode = FMODE_WRITABLE;
  3653. break;
  3654. case O_RDWR:
  3655. fmode = FMODE_READWRITE;
  3656. break;
  3657. }
  3658. if (oflags & O_APPEND) {
  3659. fmode |= FMODE_APPEND;
  3660. }
  3661. if (oflags & O_TRUNC) {
  3662. fmode |= FMODE_TRUNC;
  3663. }
  3664. if (oflags & O_CREAT) {
  3665. fmode |= FMODE_CREATE;
  3666. }
  3667. #ifdef O_BINARY
  3668. if (oflags & O_BINARY) {
  3669. fmode |= FMODE_BINMODE;
  3670. }
  3671. #endif
  3672. return fmode;
  3673. }
  3674. static int
  3675. rb_io_fmode_oflags(int fmode)
  3676. {
  3677. int oflags = 0;
  3678. switch (fmode & FMODE_READWRITE) {
  3679. case FMODE_READABLE:
  3680. oflags |= O_RDONLY;
  3681. break;
  3682. case FMODE_WRITABLE:
  3683. oflags |= O_WRONLY;
  3684. break;
  3685. case FMODE_READWRITE:
  3686. oflags |= O_RDWR;
  3687. break;
  3688. }
  3689. if (fmode & FMODE_APPEND) {
  3690. oflags |= O_APPEND;
  3691. }
  3692. if (fmode & FMODE_TRUNC) {
  3693. oflags |= O_TRUNC;
  3694. }
  3695. if (fmode & FMODE_CREATE) {
  3696. oflags |= O_CREAT;
  3697. }
  3698. #ifdef O_BINARY
  3699. if (fmode & FMODE_BINMODE) {
  3700. oflags |= O_BINARY;
  3701. }
  3702. #endif
  3703. return oflags;
  3704. }
  3705. int
  3706. rb_io_modestr_oflags(const char *modestr)
  3707. {
  3708. return rb_io_fmode_oflags(rb_io_modestr_fmode(modestr));
  3709. }
  3710. static const char*
  3711. rb_io_oflags_modestr(int oflags)
  3712. {
  3713. #ifdef O_BINARY
  3714. # define MODE_BINARY(a,b) ((oflags & O_BINARY) ? (b) : (a))
  3715. #else
  3716. # define MODE_BINARY(a,b) (a)
  3717. #endif
  3718. int accmode = oflags & (O_RDONLY|O_WRONLY|O_RDWR);
  3719. if (oflags & O_APPEND) {
  3720. if (accmode == O_WRONLY) {
  3721. return MODE_BINARY("a", "ab");
  3722. }
  3723. if (accmode == O_RDWR) {
  3724. return MODE_BINARY("a+", "ab+");
  3725. }
  3726. }
  3727. switch (oflags & (O_RDONLY|O_WRONLY|O_RDWR)) {
  3728. case O_RDONLY:
  3729. return MODE_BINARY("r", "rb");
  3730. case O_WRONLY:
  3731. return MODE_BINARY("w", "wb");
  3732. case O_RDWR:
  3733. return MODE_BINARY("r+", "rb+");
  3734. }
  3735. rb_raise(rb_eArgError, "invalid access oflags 0x%x", oflags);
  3736. return NULL; /* not reached */
  3737. }
  3738. /*
  3739. * Convert external/internal encodings to enc/enc2
  3740. * NULL => use default encoding
  3741. * Qnil => no encoding specified (internal only)
  3742. */
  3743. static void
  3744. rb_io_ext_int_to_encs(rb_encoding *ext, rb_encoding *intern, rb_encoding **enc, rb_encoding **enc2)
  3745. {
  3746. int default_ext = 0;
  3747. if (ext == NULL) {
  3748. ext = rb_default_external_encoding();
  3749. default_ext = 1;
  3750. }
  3751. if (intern == NULL && ext != rb_ascii8bit_encoding())
  3752. /* If external is ASCII-8BIT, no default transcoding */
  3753. intern = rb_default_internal_encoding();
  3754. if (intern == NULL || intern == (rb_encoding *)Qnil || intern == ext) {
  3755. /* No internal encoding => use external + no transcoding */
  3756. *enc = (default_ext && intern != ext) ? NULL : ext;
  3757. *enc2 = NULL;
  3758. }
  3759. else {
  3760. *enc = intern;
  3761. *enc2 = ext;
  3762. }
  3763. }
  3764. static void
  3765. parse_mode_enc(const char *estr, rb_encoding **enc_p, rb_encoding **enc2_p, int *fmode_p)
  3766. {
  3767. const char *p;
  3768. char encname[ENCODING_MAXNAMELEN+1];
  3769. int idx, idx2;
  3770. rb_encoding *ext_enc, *int_enc;
  3771. /* parse estr as "enc" or "enc2:enc" or "enc:-" */
  3772. p = strrchr(estr, ':');
  3773. if (p) {
  3774. long len = (p++) - estr;
  3775. if (len == 0 || len > ENCODING_MAXNAMELEN)
  3776. idx = -1;
  3777. else {
  3778. if (io_encname_bom_p(estr, len)) {
  3779. if (fmode_p) *fmode_p |= FMODE_SETENC_BY_BOM;
  3780. estr += 4;
  3781. len -= 4;
  3782. }
  3783. memcpy(encname, estr, len);
  3784. encname[len] = '\0';
  3785. estr = encname;
  3786. idx = rb_enc_find_index(encname);
  3787. }
  3788. }
  3789. else {
  3790. long len = strlen(estr);
  3791. if (io_encname_bom_p(estr, len)) {
  3792. if (fmode_p) *fmode_p |= FMODE_SETENC_BY_BOM;
  3793. estr += 4;
  3794. len -= 4;
  3795. memcpy(encname, estr, len);
  3796. encname[len] = '\0';
  3797. estr = encname;
  3798. }
  3799. idx = rb_enc_find_index(estr);
  3800. }
  3801. if (idx >= 0)
  3802. ext_enc = rb_enc_from_index(idx);
  3803. else {
  3804. if (idx != -2)
  3805. rb_warn("Unsupported encoding %s ignored", estr);
  3806. ext_enc = NULL;
  3807. }
  3808. int_enc = NULL;
  3809. if (p) {
  3810. if (*p == '-' && *(p+1) == '\0') {
  3811. /* Special case - "-" => no transcoding */
  3812. int_enc = (rb_encoding *)Qnil;
  3813. }
  3814. else {
  3815. idx2 = rb_enc_find_index(p);
  3816. if (idx2 < 0)
  3817. rb_warn("Unsupported encoding %s ignored", p);
  3818. else if (idx2 == idx) {
  3819. rb_warn("Ignoring internal encoding %s: it is identical to external encoding %s", p, estr);
  3820. int_enc = (rb_encoding *)Qnil;
  3821. }
  3822. else
  3823. int_enc = rb_enc_from_index(idx2);
  3824. }
  3825. }
  3826. rb_io_ext_int_to_encs(ext_enc, int_enc, enc_p, enc2_p);
  3827. }
  3828. static void
  3829. mode_enc(rb_io_t *fptr, const char *estr)
  3830. {
  3831. clear_codeconv(fptr);
  3832. parse_mode_enc(estr, &fptr->encs.enc, &fptr->encs.enc2, NULL);
  3833. }
  3834. static void
  3835. rb_io_mode_enc(rb_io_t *fptr, const char *modestr)
  3836. {
  3837. const char *p = strchr(modestr, ':');
  3838. if (p) {
  3839. mode_enc(fptr, p+1);
  3840. }
  3841. }
  3842. int
  3843. rb_io_extract_encoding_option(VALUE opt, rb_encoding **enc_p, rb_encoding **enc2_p, int *fmode_p)
  3844. {
  3845. VALUE encoding=Qnil, extenc=Qundef, intenc=Qundef, tmp;
  3846. int extracted = 0;
  3847. rb_encoding *extencoding = NULL;
  3848. rb_encoding *intencoding = NULL;
  3849. if (!NIL_P(opt)) {
  3850. VALUE v;
  3851. v = rb_hash_lookup2(opt, sym_encoding, Qnil);
  3852. if (v != Qnil) encoding = v;
  3853. v = rb_hash_lookup2(opt, sym_extenc, Qundef);
  3854. if (v != Qnil) extenc = v;
  3855. v = rb_hash_lookup2(opt, sym_intenc, Qundef);
  3856. if (v != Qundef) intenc = v;
  3857. }
  3858. if ((extenc != Qundef || intenc != Qundef) && !NIL_P(encoding)) {
  3859. rb_warn("Ignoring encoding parameter '%s': %s_encoding is used",
  3860. StringValueCStr(encoding),
  3861. extenc == Qundef ? "internal" : "external");
  3862. encoding = Qnil;
  3863. }
  3864. if (extenc != Qundef && !NIL_P(extenc)) {
  3865. extencoding = rb_to_encoding(extenc);
  3866. }
  3867. if (intenc != Qundef) {
  3868. if (NIL_P(intenc)) {
  3869. /* internal_encoding: nil => no transcoding */
  3870. intencoding = (rb_encoding *)Qnil;
  3871. }
  3872. else if (!NIL_P(tmp = rb_check_string_type(intenc))) {
  3873. char *p = StringValueCStr(tmp);
  3874. if (*p == '-' && *(p+1) == '\0') {
  3875. /* Special case - "-" => no transcoding */
  3876. intencoding = (rb_encoding *)Qnil;
  3877. }
  3878. else {
  3879. intencoding = rb_to_encoding(intenc);
  3880. }
  3881. }
  3882. else {
  3883. intencoding = rb_to_encoding(intenc);
  3884. }
  3885. if (extencoding == intencoding) {
  3886. intencoding = (rb_encoding *)Qnil;
  3887. }
  3888. }
  3889. if (!NIL_P(encoding)) {
  3890. extracted = 1;
  3891. parse_mode_enc(StringValueCStr(encoding), enc_p, enc2_p, fmode_p);
  3892. }
  3893. else if (extenc != Qundef || intenc != Qundef) {
  3894. extracted = 1;
  3895. rb_io_ext_int_to_encs(extencoding, intencoding, enc_p, enc2_p);
  3896. }
  3897. return extracted;
  3898. }
  3899. typedef struct rb_io_enc_t convconfig_t;
  3900. static void
  3901. validate_enc_binmode(int fmode, rb_encoding *enc, rb_encoding *enc2)
  3902. {
  3903. if ((fmode & FMODE_READABLE) &&
  3904. !enc2 &&
  3905. !(fmode & FMODE_BINMODE) &&
  3906. !rb_enc_asciicompat(enc ? enc : rb_default_external_encoding()))
  3907. rb_raise(rb_eArgError, "ASCII incompatible encoding needs binmode");
  3908. }
  3909. static void
  3910. extract_binmode(VALUE opthash, int *fmode)
  3911. {
  3912. if (!NIL_P(opthash)) {
  3913. VALUE v;
  3914. v = rb_hash_aref(opthash, sym_textmode);
  3915. if (!NIL_P(v) && RTEST(v))
  3916. *fmode |= FMODE_TEXTMODE;
  3917. v = rb_hash_aref(opthash, sym_binmode);
  3918. if (!NIL_P(v) && RTEST(v))
  3919. *fmode |= FMODE_BINMODE;
  3920. if ((*fmode & FMODE_BINMODE) && (*fmode & FMODE_TEXTMODE))
  3921. rb_raise(rb_eArgError, "both textmode and binmode specified");
  3922. }
  3923. }
  3924. static void
  3925. rb_io_extract_modeenc(VALUE *vmode_p, VALUE *vperm_p, VALUE opthash,
  3926. int *oflags_p, int *fmode_p, convconfig_t *convconfig_p)
  3927. {
  3928. VALUE vmode;
  3929. int oflags, fmode;
  3930. rb_encoding *enc, *enc2;
  3931. int ecflags;
  3932. VALUE ecopts;
  3933. int has_enc = 0, has_vmode = 0;
  3934. VALUE intmode;
  3935. vmode = *vmode_p;
  3936. /* Set to defaults */
  3937. rb_io_ext_int_to_encs(NULL, NULL, &enc, &enc2);
  3938. if (NIL_P(vmode)) {
  3939. fmode = FMODE_READABLE;
  3940. oflags = O_RDONLY;
  3941. }
  3942. else if (!NIL_P(intmode = rb_check_to_integer(vmode, "to_int"))) {
  3943. vmode = intmode;
  3944. oflags = NUM2INT(intmode);
  3945. fmode = rb_io_oflags_fmode(oflags);
  3946. }
  3947. else {
  3948. const char *p;
  3949. vmode_handle:
  3950. SafeStringValue(vmode);
  3951. p = StringValueCStr(vmode);
  3952. fmode = rb_io_modestr_fmode(p);
  3953. oflags = rb_io_fmode_oflags(fmode);
  3954. p = strchr(p, ':');
  3955. if (p) {
  3956. has_enc = 1;
  3957. parse_mode_enc(p+1, &enc, &enc2, &fmode);
  3958. }
  3959. else {
  3960. rb_encoding *e;
  3961. e = (fmode & FMODE_BINMODE) ? rb_ascii8bit_encoding() : NULL;
  3962. rb_io_ext_int_to_encs(e, NULL, &enc, &enc2);
  3963. }
  3964. }
  3965. if (NIL_P(opthash)) {
  3966. ecflags = 0;
  3967. ecopts = Qnil;
  3968. }
  3969. else {
  3970. VALUE v;
  3971. extract_binmode(opthash, &fmode);
  3972. #ifdef O_BINARY
  3973. if (fmode & FMODE_BINMODE)
  3974. oflags |= O_BINARY;
  3975. #endif
  3976. if (!has_vmode) {
  3977. v = rb_hash_aref(opthash, sym_mode);
  3978. if (!NIL_P(v)) {
  3979. if (!NIL_P(vmode)) {
  3980. rb_raise(rb_eArgError, "mode specified twice");
  3981. }
  3982. has_vmode = 1;
  3983. vmode = v;
  3984. goto vmode_handle;
  3985. }
  3986. }
  3987. v = rb_hash_aref(opthash, sym_perm);
  3988. if (!NIL_P(v)) {
  3989. if (vperm_p) {
  3990. if (!NIL_P(*vperm_p)) {
  3991. rb_raise(rb_eArgError, "perm specified twice");
  3992. }
  3993. *vperm_p = v;
  3994. }
  3995. else {
  3996. /* perm no use, just ignore */
  3997. }
  3998. }
  3999. ecflags = rb_econv_prepare_opts(opthash, &ecopts);
  4000. if (rb_io_extract_encoding_option(opthash, &enc, &enc2, &fmode)) {
  4001. if (has_enc) {
  4002. rb_raise(rb_eArgError, "encoding specified twice");
  4003. }
  4004. }
  4005. }
  4006. validate_enc_binmode(fmode, enc, enc2);
  4007. *vmode_p = vmode;
  4008. *oflags_p = oflags;
  4009. *fmode_p = fmode;
  4010. convconfig_p->enc = enc;
  4011. convconfig_p->enc2 = enc2;
  4012. convconfig_p->ecflags = ecflags;
  4013. convconfig_p->ecopts = ecopts;
  4014. }
  4015. struct sysopen_struct {
  4016. VALUE fname;
  4017. int oflags;
  4018. mode_t perm;
  4019. };
  4020. static VALUE
  4021. sysopen_func(void *ptr)
  4022. {
  4023. const struct sysopen_struct *data = ptr;
  4024. const char *fname = RSTRING_PTR(data->fname);
  4025. return (VALUE)open(fname, data->oflags, data->perm);
  4026. }
  4027. static inline int
  4028. rb_sysopen_internal(struct sysopen_struct *data)
  4029. {
  4030. return (int)rb_thread_blocking_region(sysopen_func, data, RUBY_UBF_IO, 0);
  4031. }
  4032. static int
  4033. rb_sysopen(VALUE fname, int oflags, mode_t perm)
  4034. {
  4035. int fd;
  4036. struct sysopen_struct data;
  4037. #ifdef O_BINARY
  4038. oflags |= O_BINARY;
  4039. #endif
  4040. data.fname = rb_str_encode_ospath(fname);
  4041. data.oflags = oflags;
  4042. data.perm = perm;
  4043. fd = rb_sysopen_internal(&data);
  4044. if (fd < 0) {
  4045. if (errno == EMFILE || errno == ENFILE) {
  4046. rb_gc();
  4047. fd = rb_sysopen_internal(&data);
  4048. }
  4049. if (fd < 0) {
  4050. rb_sys_fail(RSTRING_PTR(fname));
  4051. }
  4052. }
  4053. UPDATE_MAXFD(fd);
  4054. return fd;
  4055. }
  4056. FILE *
  4057. rb_fdopen(int fd, const char *modestr)
  4058. {
  4059. FILE *file;
  4060. #if defined(sun)
  4061. errno = 0;
  4062. #endif
  4063. file = fdopen(fd, modestr);
  4064. if (!file) {
  4065. if (
  4066. #if defined(sun)
  4067. errno == 0 ||
  4068. #endif
  4069. errno == EMFILE || errno == ENFILE) {
  4070. rb_gc();
  4071. #if defined(sun)
  4072. errno = 0;
  4073. #endif
  4074. file = fdopen(fd, modestr);
  4075. }
  4076. if (!file) {
  4077. #ifdef _WIN32
  4078. if (errno == 0) errno = EINVAL;
  4079. #elif defined(sun)
  4080. if (errno == 0) errno = EMFILE;
  4081. #endif
  4082. rb_sys_fail(0);
  4083. }
  4084. }
  4085. /* xxx: should be _IONBF? A buffer in FILE may have trouble. */
  4086. #ifdef USE_SETVBUF
  4087. if (setvbuf(file, NULL, _IOFBF, 0) != 0)
  4088. rb_warn("setvbuf() can't be honoured (fd=%d)", fd);
  4089. #endif
  4090. return file;
  4091. }
  4092. static void
  4093. io_check_tty(rb_io_t *fptr)
  4094. {
  4095. if (isatty(fptr->fd))
  4096. fptr->mode |= FMODE_TTY|FMODE_DUPLEX;
  4097. }
  4098. static VALUE rb_io_internal_encoding(VALUE);
  4099. static void io_encoding_set(rb_io_t *, VALUE, VALUE, VALUE);
  4100. static int
  4101. io_strip_bom(VALUE io)
  4102. {
  4103. int b1, b2, b3, b4;
  4104. switch (b1 = FIX2INT(rb_io_getbyte(io))) {
  4105. case 0xEF:
  4106. b2 = FIX2INT(rb_io_getbyte(io));
  4107. if (b2 == 0xBB) {
  4108. b3 = FIX2INT(rb_io_getbyte(io));
  4109. if (b3 == 0xBF) {
  4110. return rb_utf8_encindex();
  4111. }
  4112. rb_io_ungetbyte(io, INT2FIX(b3));
  4113. }
  4114. rb_io_ungetbyte(io, INT2FIX(b2));
  4115. break;
  4116. case 0xFE:
  4117. b2 = FIX2INT(rb_io_getbyte(io));
  4118. if (b2 == 0xFF) {
  4119. return rb_enc_find_index("UTF-16BE");
  4120. }
  4121. rb_io_ungetbyte(io, INT2FIX(b2));
  4122. break;
  4123. case 0xFF:
  4124. b2 = FIX2INT(rb_io_getbyte(io));
  4125. if (b2 == 0xFE) {
  4126. b3 = FIX2INT(rb_io_getbyte(io));
  4127. if (b3 == 0) {
  4128. b4 = FIX2INT(rb_io_getbyte(io));
  4129. if (b4 == 0) {
  4130. return rb_enc_find_index("UTF-32LE");
  4131. }
  4132. rb_io_ungetbyte(io, INT2FIX(b4));
  4133. }
  4134. else {
  4135. rb_io_ungetbyte(io, INT2FIX(b3));
  4136. return rb_enc_find_index("UTF-16LE");
  4137. }
  4138. rb_io_ungetbyte(io, INT2FIX(b3));
  4139. }
  4140. rb_io_ungetbyte(io, INT2FIX(b2));
  4141. break;
  4142. case 0:
  4143. b2 = FIX2INT(rb_io_getbyte(io));
  4144. if (b2 == 0) {
  4145. b3 = FIX2INT(rb_io_getbyte(io));
  4146. if (b3 == 0xFE) {
  4147. b4 = FIX2INT(rb_io_getbyte(io));
  4148. if (b4 == 0xFF) {
  4149. return rb_enc_find_index("UTF-32BE");
  4150. }
  4151. rb_io_ungetbyte(io, INT2FIX(b4));
  4152. }
  4153. rb_io_ungetbyte(io, INT2FIX(b3));
  4154. }
  4155. rb_io_ungetbyte(io, INT2FIX(b2));
  4156. break;
  4157. }
  4158. rb_io_ungetbyte(io, INT2FIX(b1));
  4159. return 0;
  4160. }
  4161. static void
  4162. io_set_encoding_by_bom(VALUE io)
  4163. {
  4164. int idx = io_strip_bom(io);
  4165. if (idx) {
  4166. rb_io_t *fptr;
  4167. GetOpenFile(io, fptr);
  4168. io_encoding_set(fptr, rb_enc_from_encoding(rb_enc_from_index(idx)),
  4169. rb_io_internal_encoding(io), Qnil);
  4170. }
  4171. }
  4172. static VALUE
  4173. rb_file_open_generic(VALUE io, VALUE filename, int oflags, int fmode, convconfig_t *convconfig, mode_t perm)
  4174. {
  4175. rb_io_t *fptr;
  4176. convconfig_t cc;
  4177. if (!convconfig) {
  4178. /* Set to default encodings */
  4179. rb_io_ext_int_to_encs(NULL, NULL, &cc.enc, &cc.enc2);
  4180. cc.ecflags = 0;
  4181. cc.ecopts = Qnil;
  4182. convconfig = &cc;
  4183. }
  4184. validate_enc_binmode(fmode, convconfig->enc, convconfig->enc2);
  4185. MakeOpenFile(io, fptr);
  4186. fptr->mode = fmode;
  4187. fptr->encs = *convconfig;
  4188. fptr->pathv = rb_str_new_frozen(filename);
  4189. fptr->fd = rb_sysopen(fptr->pathv, oflags, perm);
  4190. io_check_tty(fptr);
  4191. if (fmode & FMODE_SETENC_BY_BOM) io_set_encoding_by_bom(io);
  4192. return io;
  4193. }
  4194. static VALUE
  4195. rb_file_open_internal(VALUE io, VALUE filename, const char *modestr)
  4196. {
  4197. int fmode = rb_io_modestr_fmode(modestr);
  4198. const char *p = strchr(modestr, ':');
  4199. convconfig_t convconfig;
  4200. if (p) {
  4201. parse_mode_enc(p+1, &convconfig.enc, &convconfig.enc2, &fmode);
  4202. }
  4203. else {
  4204. rb_encoding *e;
  4205. /* Set to default encodings */
  4206. e = (fmode & FMODE_BINMODE) ? rb_ascii8bit_encoding() : NULL;
  4207. rb_io_ext_int_to_encs(e, NULL, &convconfig.enc, &convconfig.enc2);
  4208. convconfig.ecflags = 0;
  4209. convconfig.ecopts = Qnil;
  4210. }
  4211. return rb_file_open_generic(io, filename,
  4212. rb_io_fmode_oflags(fmode),
  4213. fmode,
  4214. &convconfig,
  4215. 0666);
  4216. }
  4217. VALUE
  4218. rb_file_open_str(VALUE fname, const char *modestr)
  4219. {
  4220. FilePathValue(fname);
  4221. return rb_file_open_internal(io_alloc(rb_cFile), fname, modestr);
  4222. }
  4223. VALUE
  4224. rb_file_open(const char *fname, const char *modestr)
  4225. {
  4226. return rb_file_open_internal(io_alloc(rb_cFile), rb_str_new_cstr(fname), modestr);
  4227. }
  4228. #if defined(__CYGWIN__) || !defined(HAVE_FORK)
  4229. static struct pipe_list {
  4230. rb_io_t *fptr;
  4231. struct pipe_list *next;
  4232. } *pipe_list;
  4233. static void
  4234. pipe_add_fptr(rb_io_t *fptr)
  4235. {
  4236. struct pipe_list *list;
  4237. list = ALLOC(struct pipe_list);
  4238. list->fptr = fptr;
  4239. list->next = pipe_list;
  4240. pipe_list = list;
  4241. }
  4242. static void
  4243. pipe_del_fptr(rb_io_t *fptr)
  4244. {
  4245. struct pipe_list *list = pipe_list;
  4246. struct pipe_list *tmp;
  4247. if (list->fptr == fptr) {
  4248. pipe_list = list->next;
  4249. free(list);
  4250. return;
  4251. }
  4252. while (list->next) {
  4253. if (list->next->fptr == fptr) {
  4254. tmp = list->next;
  4255. list->next = list->next->next;
  4256. free(tmp);
  4257. return;
  4258. }
  4259. list = list->next;
  4260. }
  4261. }
  4262. static void
  4263. pipe_atexit(void)
  4264. {
  4265. struct pipe_list *list = pipe_list;
  4266. struct pipe_list *tmp;
  4267. while (list) {
  4268. tmp = list->next;
  4269. rb_io_fptr_finalize(list->fptr);
  4270. list = tmp;
  4271. }
  4272. }
  4273. static void
  4274. pipe_finalize(rb_io_t *fptr, int noraise)
  4275. {
  4276. #if !defined(HAVE_FORK) && !defined(_WIN32)
  4277. int status;
  4278. if (fptr->stdio_file) {
  4279. status = pclose(fptr->stdio_file);
  4280. }
  4281. fptr->fd = -1;
  4282. fptr->stdio_file = 0;
  4283. rb_last_status_set(status, fptr->pid);
  4284. #else
  4285. fptr_finalize(fptr, noraise);
  4286. #endif
  4287. pipe_del_fptr(fptr);
  4288. }
  4289. #endif
  4290. void
  4291. rb_io_synchronized(rb_io_t *fptr)
  4292. {
  4293. rb_io_check_initialized(fptr);
  4294. fptr->mode |= FMODE_SYNC;
  4295. }
  4296. void
  4297. rb_io_unbuffered(rb_io_t *fptr)
  4298. {
  4299. rb_io_synchronized(fptr);
  4300. }
  4301. int
  4302. rb_pipe(int *pipes)
  4303. {
  4304. int ret;
  4305. ret = pipe(pipes);
  4306. if (ret == -1) {
  4307. if (errno == EMFILE || errno == ENFILE) {
  4308. rb_gc();
  4309. ret = pipe(pipes);
  4310. }
  4311. }
  4312. if (ret == 0) {
  4313. UPDATE_MAXFD(pipes[0]);
  4314. UPDATE_MAXFD(pipes[1]);
  4315. }
  4316. return ret;
  4317. }
  4318. #ifdef HAVE_FORK
  4319. struct popen_arg {
  4320. struct rb_exec_arg *execp;
  4321. int modef;
  4322. int pair[2];
  4323. int write_pair[2];
  4324. };
  4325. static void
  4326. popen_redirect(struct popen_arg *p)
  4327. {
  4328. if ((p->modef & FMODE_READABLE) && (p->modef & FMODE_WRITABLE)) {
  4329. close(p->write_pair[1]);
  4330. if (p->write_pair[0] != 0) {
  4331. dup2(p->write_pair[0], 0);
  4332. close(p->write_pair[0]);
  4333. }
  4334. close(p->pair[0]);
  4335. if (p->pair[1] != 1) {
  4336. dup2(p->pair[1], 1);
  4337. close(p->pair[1]);
  4338. }
  4339. }
  4340. else if (p->modef & FMODE_READABLE) {
  4341. close(p->pair[0]);
  4342. if (p->pair[1] != 1) {
  4343. dup2(p->pair[1], 1);
  4344. close(p->pair[1]);
  4345. }
  4346. }
  4347. else {
  4348. close(p->pair[1]);
  4349. if (p->pair[0] != 0) {
  4350. dup2(p->pair[0], 0);
  4351. close(p->pair[0]);
  4352. }
  4353. }
  4354. }
  4355. void
  4356. rb_close_before_exec(int lowfd, int maxhint, VALUE noclose_fds)
  4357. {
  4358. int fd, ret;
  4359. int max = max_file_descriptor;
  4360. if (max < maxhint)
  4361. max = maxhint;
  4362. for (fd = lowfd; fd <= max; fd++) {
  4363. if (!NIL_P(noclose_fds) &&
  4364. RTEST(rb_hash_lookup(noclose_fds, INT2FIX(fd))))
  4365. continue;
  4366. #ifdef FD_CLOEXEC
  4367. ret = fcntl(fd, F_GETFD);
  4368. if (ret != -1 && !(ret & FD_CLOEXEC)) {
  4369. fcntl(fd, F_SETFD, ret|FD_CLOEXEC);
  4370. }
  4371. #else
  4372. ret = close(fd);
  4373. #endif
  4374. #define CONTIGUOUS_CLOSED_FDS 20
  4375. if (ret != -1) {
  4376. if (max < fd + CONTIGUOUS_CLOSED_FDS)
  4377. max = fd + CONTIGUOUS_CLOSED_FDS;
  4378. }
  4379. }
  4380. }
  4381. static int
  4382. popen_exec(void *pp, char *errmsg, size_t errmsg_len)
  4383. {
  4384. struct popen_arg *p = (struct popen_arg*)pp;
  4385. rb_thread_atfork_before_exec();
  4386. return rb_exec_err(p->execp, errmsg, errmsg_len);
  4387. }
  4388. #endif
  4389. static VALUE
  4390. pipe_open(struct rb_exec_arg *eargp, VALUE prog, const char *modestr, int fmode, convconfig_t *convconfig)
  4391. {
  4392. rb_pid_t pid = 0;
  4393. rb_io_t *fptr;
  4394. VALUE port;
  4395. rb_io_t *write_fptr;
  4396. VALUE write_port;
  4397. #if defined(HAVE_FORK)
  4398. int status;
  4399. struct popen_arg arg;
  4400. char errmsg[80] = { '\0' };
  4401. #elif defined(_WIN32)
  4402. volatile VALUE argbuf;
  4403. char **args = NULL;
  4404. int pair[2], write_pair[2];
  4405. #endif
  4406. #if !defined(HAVE_FORK)
  4407. struct rb_exec_arg sarg;
  4408. #endif
  4409. FILE *fp = 0;
  4410. int fd = -1;
  4411. int write_fd = -1;
  4412. const char *cmd = 0;
  4413. int argc;
  4414. VALUE *argv;
  4415. if (prog)
  4416. cmd = StringValueCStr(prog);
  4417. if (!eargp) {
  4418. /* fork : IO.popen("-") */
  4419. argc = 0;
  4420. argv = 0;
  4421. }
  4422. else if (eargp->argc) {
  4423. /* no shell : IO.popen([prog, arg0], arg1, ...) */
  4424. argc = eargp->argc;
  4425. argv = eargp->argv;
  4426. }
  4427. else {
  4428. /* with shell : IO.popen(prog) */
  4429. argc = 0;
  4430. argv = 0;
  4431. }
  4432. #if defined(HAVE_FORK)
  4433. arg.execp = eargp;
  4434. arg.modef = fmode;
  4435. arg.pair[0] = arg.pair[1] = -1;
  4436. arg.write_pair[0] = arg.write_pair[1] = -1;
  4437. switch (fmode & (FMODE_READABLE|FMODE_WRITABLE)) {
  4438. case FMODE_READABLE|FMODE_WRITABLE:
  4439. if (rb_pipe(arg.write_pair) < 0)
  4440. rb_sys_fail(cmd);
  4441. if (rb_pipe(arg.pair) < 0) {
  4442. int e = errno;
  4443. close(arg.write_pair[0]);
  4444. close(arg.write_pair[1]);
  4445. errno = e;
  4446. rb_sys_fail(cmd);
  4447. }
  4448. if (eargp) {
  4449. rb_exec_arg_addopt(eargp, INT2FIX(0), INT2FIX(arg.write_pair[0]));
  4450. rb_exec_arg_addopt(eargp, INT2FIX(1), INT2FIX(arg.pair[1]));
  4451. }
  4452. break;
  4453. case FMODE_READABLE:
  4454. if (rb_pipe(arg.pair) < 0)
  4455. rb_sys_fail(cmd);
  4456. if (eargp)
  4457. rb_exec_arg_addopt(eargp, INT2FIX(1), INT2FIX(arg.pair[1]));
  4458. break;
  4459. case FMODE_WRITABLE:
  4460. if (rb_pipe(arg.pair) < 0)
  4461. rb_sys_fail(cmd);
  4462. if (eargp)
  4463. rb_exec_arg_addopt(eargp, INT2FIX(0), INT2FIX(arg.pair[0]));
  4464. break;
  4465. default:
  4466. rb_sys_fail(cmd);
  4467. }
  4468. if (eargp) {
  4469. rb_exec_arg_fixup(arg.execp);
  4470. pid = rb_fork_err(&status, popen_exec, &arg, arg.execp->redirect_fds, errmsg, sizeof(errmsg));
  4471. }
  4472. else {
  4473. fflush(stdin); /* is it really needed? */
  4474. pid = rb_fork(&status, 0, 0, Qnil);
  4475. if (pid == 0) { /* child */
  4476. popen_redirect(&arg);
  4477. rb_io_synchronized(RFILE(orig_stdout)->fptr);
  4478. rb_io_synchronized(RFILE(orig_stderr)->fptr);
  4479. return Qnil;
  4480. }
  4481. }
  4482. /* parent */
  4483. if (pid == -1) {
  4484. int e = errno;
  4485. close(arg.pair[0]);
  4486. close(arg.pair[1]);
  4487. if ((fmode & (FMODE_READABLE|FMODE_WRITABLE)) == (FMODE_READABLE|FMODE_WRITABLE)) {
  4488. close(arg.write_pair[0]);
  4489. close(arg.write_pair[1]);
  4490. }
  4491. errno = e;
  4492. if (errmsg[0])
  4493. rb_sys_fail(errmsg);
  4494. rb_sys_fail(cmd);
  4495. }
  4496. if ((fmode & FMODE_READABLE) && (fmode & FMODE_WRITABLE)) {
  4497. close(arg.pair[1]);
  4498. fd = arg.pair[0];
  4499. close(arg.write_pair[0]);
  4500. write_fd = arg.write_pair[1];
  4501. }
  4502. else if (fmode & FMODE_READABLE) {
  4503. close(arg.pair[1]);
  4504. fd = arg.pair[0];
  4505. }
  4506. else {
  4507. close(arg.pair[0]);
  4508. fd = arg.pair[1];
  4509. }
  4510. #elif defined(_WIN32)
  4511. if (argc) {
  4512. int i;
  4513. if (argc >= (int)(FIXNUM_MAX / sizeof(char *))) {
  4514. rb_raise(rb_eArgError, "too many arguments");
  4515. }
  4516. argbuf = rb_str_tmp_new((argc+1) * sizeof(char *));
  4517. args = (void *)RSTRING_PTR(argbuf);
  4518. for (i = 0; i < argc; ++i) {
  4519. args[i] = StringValueCStr(argv[i]);
  4520. }
  4521. args[i] = NULL;
  4522. }
  4523. switch (fmode & (FMODE_READABLE|FMODE_WRITABLE)) {
  4524. case FMODE_READABLE|FMODE_WRITABLE:
  4525. if (rb_pipe(write_pair) < 0)
  4526. rb_sys_fail(cmd);
  4527. if (rb_pipe(pair) < 0) {
  4528. int e = errno;
  4529. close(write_pair[0]);
  4530. close(write_pair[1]);
  4531. errno = e;
  4532. rb_sys_fail(cmd);
  4533. }
  4534. if (eargp) {
  4535. rb_exec_arg_addopt(eargp, INT2FIX(0), INT2FIX(write_pair[0]));
  4536. rb_exec_arg_addopt(eargp, INT2FIX(1), INT2FIX(pair[1]));
  4537. }
  4538. break;
  4539. case FMODE_READABLE:
  4540. if (rb_pipe(pair) < 0)
  4541. rb_sys_fail(cmd);
  4542. if (eargp)
  4543. rb_exec_arg_addopt(eargp, INT2FIX(1), INT2FIX(pair[1]));
  4544. break;
  4545. case FMODE_WRITABLE:
  4546. if (rb_pipe(pair) < 0)
  4547. rb_sys_fail(cmd);
  4548. if (eargp)
  4549. rb_exec_arg_addopt(eargp, INT2FIX(0), INT2FIX(pair[0]));
  4550. break;
  4551. default:
  4552. rb_sys_fail(cmd);
  4553. }
  4554. if (eargp) {
  4555. rb_exec_arg_fixup(eargp);
  4556. rb_run_exec_options(eargp, &sarg);
  4557. }
  4558. while ((pid = (args ?
  4559. rb_w32_aspawn(P_NOWAIT, cmd, args) :
  4560. rb_w32_spawn(P_NOWAIT, cmd, 0))) == -1) {
  4561. /* exec failed */
  4562. switch (errno) {
  4563. case EAGAIN:
  4564. #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
  4565. case EWOULDBLOCK:
  4566. #endif
  4567. rb_thread_sleep(1);
  4568. break;
  4569. default:
  4570. {
  4571. int e = errno;
  4572. if (eargp)
  4573. rb_run_exec_options(&sarg, NULL);
  4574. close(pair[0]);
  4575. close(pair[1]);
  4576. if ((fmode & (FMODE_READABLE|FMODE_WRITABLE)) == (FMODE_READABLE|FMODE_WRITABLE)) {
  4577. close(write_pair[0]);
  4578. close(write_pair[1]);
  4579. }
  4580. errno = e;
  4581. rb_sys_fail(cmd);
  4582. }
  4583. break;
  4584. }
  4585. }
  4586. RB_GC_GUARD(argbuf);
  4587. if (eargp)
  4588. rb_run_exec_options(&sarg, NULL);
  4589. if ((fmode & FMODE_READABLE) && (fmode & FMODE_WRITABLE)) {
  4590. close(pair[1]);
  4591. fd = pair[0];
  4592. close(write_pair[0]);
  4593. write_fd = write_pair[1];
  4594. }
  4595. else if (fmode & FMODE_READABLE) {
  4596. close(pair[1]);
  4597. fd = pair[0];
  4598. }
  4599. else {
  4600. close(pair[0]);
  4601. fd = pair[1];
  4602. }
  4603. #else
  4604. if (argc) {
  4605. prog = rb_ary_join(rb_ary_new4(argc, argv), rb_str_new2(" "));
  4606. cmd = StringValueCStr(prog);
  4607. }
  4608. if (eargp) {
  4609. rb_exec_arg_fixup(eargp);
  4610. rb_run_exec_options(eargp, &sarg);
  4611. }
  4612. fp = popen(cmd, modestr);
  4613. if (eargp)
  4614. rb_run_exec_options(&sarg, NULL);
  4615. if (!fp) rb_sys_fail(RSTRING_PTR(prog));
  4616. fd = fileno(fp);
  4617. #endif
  4618. port = io_alloc(rb_cIO);
  4619. MakeOpenFile(port, fptr);
  4620. fptr->fd = fd;
  4621. fptr->stdio_file = fp;
  4622. fptr->mode = fmode | FMODE_SYNC|FMODE_DUPLEX;
  4623. if (convconfig) {
  4624. fptr->encs = *convconfig;
  4625. }
  4626. fptr->pid = pid;
  4627. if (0 <= write_fd) {
  4628. write_port = io_alloc(rb_cIO);
  4629. MakeOpenFile(write_port, write_fptr);
  4630. write_fptr->fd = write_fd;
  4631. write_fptr->mode = (fmode & ~FMODE_READABLE)| FMODE_SYNC|FMODE_DUPLEX;
  4632. fptr->mode &= ~FMODE_WRITABLE;
  4633. fptr->tied_io_for_writing = write_port;
  4634. rb_ivar_set(port, rb_intern("@tied_io_for_writing"), write_port);
  4635. }
  4636. #if defined (__CYGWIN__) || !defined(HAVE_FORK)
  4637. fptr->finalize = pipe_finalize;
  4638. pipe_add_fptr(fptr);
  4639. #endif
  4640. return port;
  4641. }
  4642. static VALUE
  4643. pipe_open_v(int argc, VALUE *argv, const char *modestr, int fmode, convconfig_t *convconfig)
  4644. {
  4645. VALUE prog;
  4646. struct rb_exec_arg earg;
  4647. prog = rb_exec_arg_init(argc, argv, FALSE, &earg);
  4648. return pipe_open(&earg, prog, modestr, fmode, convconfig);
  4649. }
  4650. static VALUE
  4651. pipe_open_s(VALUE prog, const char *modestr, int fmode, convconfig_t *convconfig)
  4652. {
  4653. const char *cmd = RSTRING_PTR(prog);
  4654. int argc = 1;
  4655. VALUE *argv = &prog;
  4656. struct rb_exec_arg earg;
  4657. if (RSTRING_LEN(prog) == 1 && cmd[0] == '-') {
  4658. #if !defined(HAVE_FORK)
  4659. rb_raise(rb_eNotImpError,
  4660. "fork() function is unimplemented on this machine");
  4661. #endif
  4662. return pipe_open(0, 0, modestr, fmode, convconfig);
  4663. }
  4664. rb_exec_arg_init(argc, argv, TRUE, &earg);
  4665. return pipe_open(&earg, prog, modestr, fmode, convconfig);
  4666. }
  4667. static VALUE
  4668. pop_last_hash(int *argc_p, VALUE *argv)
  4669. {
  4670. VALUE last, tmp;
  4671. if (*argc_p == 0)
  4672. return Qnil;
  4673. last = argv[*argc_p-1];
  4674. if (NIL_P(last)) return Qnil;
  4675. tmp = rb_check_convert_type(last, T_HASH, "Hash", "to_hash");
  4676. if (NIL_P(tmp))
  4677. return Qnil;
  4678. (*argc_p)--;
  4679. return tmp;
  4680. }
  4681. /*
  4682. * call-seq:
  4683. * IO.popen(cmd, mode="r" [, opt]) -> io
  4684. * IO.popen(cmd, mode="r" [, opt]) {|io| block } -> obj
  4685. *
  4686. * Runs the specified command as a subprocess; the subprocess's
  4687. * standard input and output will be connected to the returned
  4688. * <code>IO</code> object.
  4689. *
  4690. * The PID of the started process can be obtained by IO#pid method.
  4691. *
  4692. * _cmd_ is a string or an array as follows.
  4693. *
  4694. * cmd:
  4695. * "-" : fork
  4696. * commandline : command line string which is passed to a shell
  4697. * [env, cmdname, arg1, ..., opts] : command name and zero or more arguments (no shell)
  4698. * [env, [cmdname, argv0], arg1, ..., opts] : command name, argv[0] and zero or more arguments (no shell)
  4699. * (env and opts are optional.)
  4700. *
  4701. * If _cmd_ is a +String+ ``<code>-</code>'',
  4702. * then a new instance of Ruby is started as the subprocess.
  4703. *
  4704. * If <i>cmd</i> is an +Array+ of +String+,
  4705. * then it will be used as the subprocess's +argv+ bypassing a shell.
  4706. * The array can contains a hash at first for environments and
  4707. * a hash at last for options similar to <code>spawn</code>.
  4708. *
  4709. * The default mode for the new file object is ``r'',
  4710. * but <i>mode</i> may be set to any of the modes listed in the description for class IO.
  4711. * The last argument <i>opt</i> qualifies <i>mode</i>.
  4712. *
  4713. * # set IO encoding
  4714. * IO.popen("nkf -e filename", :external_encoding=>"EUC-JP") {|nkf_io|
  4715. * euc_jp_string = nkf_io.read
  4716. * }
  4717. *
  4718. * # merge standard output and standard error using
  4719. * # spawn option. See the document of Kernel.spawn.
  4720. * IO.popen(["ls", "/", :err=>[:child, :out]]) {|ls_io|
  4721. * ls_result_with_error = ls_io.read
  4722. * }
  4723. *
  4724. * Raises exceptions which <code>IO.pipe</code> and
  4725. * <code>Kernel.spawn</code> raise.
  4726. *
  4727. * If a block is given, Ruby will run the command as a child connected
  4728. * to Ruby with a pipe. Ruby's end of the pipe will be passed as a
  4729. * parameter to the block.
  4730. * At the end of block, Ruby close the pipe and sets <code>$?</code>.
  4731. * In this case <code>IO.popen</code> returns
  4732. * the value of the block.
  4733. *
  4734. * If a block is given with a _cmd_ of ``<code>-</code>'',
  4735. * the block will be run in two separate processes: once in the parent,
  4736. * and once in a child. The parent process will be passed the pipe
  4737. * object as a parameter to the block, the child version of the block
  4738. * will be passed <code>nil</code>, and the child's standard in and
  4739. * standard out will be connected to the parent through the pipe. Not
  4740. * available on all platforms.
  4741. *
  4742. * f = IO.popen("uname")
  4743. * p f.readlines
  4744. * f.close
  4745. * puts "Parent is #{Process.pid}"
  4746. * IO.popen("date") { |f| puts f.gets }
  4747. * IO.popen("-") {|f| $stderr.puts "#{Process.pid} is here, f is #{f.inspect}"}
  4748. * p $?
  4749. * IO.popen(%w"sed -e s|^|<foo>| -e s&$&;zot;&", "r+") {|f|
  4750. * f.puts "bar"; f.close_write; puts f.gets
  4751. * }
  4752. *
  4753. * <em>produces:</em>
  4754. *
  4755. * ["Linux\n"]
  4756. * Parent is 21346
  4757. * Thu Jan 15 22:41:19 JST 2009
  4758. * 21346 is here, f is #<IO:fd 3>
  4759. * 21352 is here, f is nil
  4760. * #<Process::Status: pid 21352 exit 0>
  4761. * <foo>bar;zot;
  4762. */
  4763. static VALUE
  4764. rb_io_s_popen(int argc, VALUE *argv, VALUE klass)
  4765. {
  4766. const char *modestr;
  4767. VALUE pname, pmode, port, tmp, opt;
  4768. int oflags, fmode;
  4769. convconfig_t convconfig;
  4770. opt = pop_last_hash(&argc, argv);
  4771. rb_scan_args(argc, argv, "11", &pname, &pmode);
  4772. rb_io_extract_modeenc(&pmode, 0, opt, &oflags, &fmode, &convconfig);
  4773. modestr = rb_io_oflags_modestr(oflags);
  4774. tmp = rb_check_array_type(pname);
  4775. if (!NIL_P(tmp)) {
  4776. long len = RARRAY_LEN(tmp);
  4777. #if SIZEOF_LONG > SIZEOF_INT
  4778. if (len > INT_MAX) {
  4779. rb_raise(rb_eArgError, "too many arguments");
  4780. }
  4781. #endif
  4782. tmp = rb_ary_dup(tmp);
  4783. RBASIC(tmp)->klass = 0;
  4784. port = pipe_open_v((int)len, RARRAY_PTR(tmp), modestr, fmode, &convconfig);
  4785. rb_ary_clear(tmp);
  4786. }
  4787. else {
  4788. SafeStringValue(pname);
  4789. port = pipe_open_s(pname, modestr, fmode, &convconfig);
  4790. }
  4791. if (NIL_P(port)) {
  4792. /* child */
  4793. if (rb_block_given_p()) {
  4794. rb_yield(Qnil);
  4795. rb_io_flush(rb_stdout);
  4796. rb_io_flush(rb_stderr);
  4797. _exit(0);
  4798. }
  4799. return Qnil;
  4800. }
  4801. RBASIC(port)->klass = klass;
  4802. if (rb_block_given_p()) {
  4803. return rb_ensure(rb_yield, port, io_close, port);
  4804. }
  4805. return port;
  4806. }
  4807. static void
  4808. rb_scan_open_args(int argc, VALUE *argv,
  4809. VALUE *fname_p, int *oflags_p, int *fmode_p,
  4810. convconfig_t *convconfig_p, mode_t *perm_p)
  4811. {
  4812. VALUE opt=Qnil, fname, vmode, vperm;
  4813. int oflags, fmode;
  4814. mode_t perm;
  4815. opt = pop_last_hash(&argc, argv);
  4816. rb_scan_args(argc, argv, "12", &fname, &vmode, &vperm);
  4817. FilePathValue(fname);
  4818. rb_io_extract_modeenc(&vmode, &vperm, opt, &oflags, &fmode, convconfig_p);
  4819. perm = NIL_P(vperm) ? 0666 : NUM2UINT(vperm);
  4820. *fname_p = fname;
  4821. *oflags_p = oflags;
  4822. *fmode_p = fmode;
  4823. *perm_p = perm;
  4824. }
  4825. static VALUE
  4826. rb_open_file(int argc, VALUE *argv, VALUE io)
  4827. {
  4828. VALUE fname;
  4829. int oflags, fmode;
  4830. convconfig_t convconfig;
  4831. mode_t perm;
  4832. rb_scan_open_args(argc, argv, &fname, &oflags, &fmode, &convconfig, &perm);
  4833. rb_file_open_generic(io, fname, oflags, fmode, &convconfig, perm);
  4834. return io;
  4835. }
  4836. /*
  4837. * Document-method: File::open
  4838. *
  4839. * call-seq:
  4840. * File.open(filename, mode="r" [, opt]) -> file
  4841. * File.open(filename [, mode [, perm]] [, opt]) -> file
  4842. * File.open(filename, mode="r" [, opt]) {|file| block } -> obj
  4843. * File.open(filename [, mode [, perm]] [, opt]) {|file| block } -> obj
  4844. *
  4845. * With no associated block, <code>open</code> is a synonym for
  4846. * <code>File.new</code>. If the optional code block is given, it will
  4847. * be passed <i>file</i> as an argument, and the File object will
  4848. * automatically be closed when the block terminates. In this instance,
  4849. * <code>File.open</code> returns the value of the block.
  4850. */
  4851. /*
  4852. * Document-method: IO::open
  4853. *
  4854. * call-seq:
  4855. * IO.open(fd, mode_string="r" [, opt] ) -> io
  4856. * IO.open(fd, mode_string="r" [, opt] ) {|io| block } -> obj
  4857. *
  4858. * With no associated block, <code>open</code> is a synonym for
  4859. * <code>IO.new</code>. If the optional code block is given, it will
  4860. * be passed <i>io</i> as an argument, and the IO object will
  4861. * automatically be closed when the block terminates. In this instance,
  4862. * <code>IO.open</code> returns the value of the block.
  4863. *
  4864. */
  4865. static VALUE
  4866. rb_io_s_open(int argc, VALUE *argv, VALUE klass)
  4867. {
  4868. VALUE io = rb_class_new_instance(argc, argv, klass);
  4869. if (rb_block_given_p()) {
  4870. return rb_ensure(rb_yield, io, io_close, io);
  4871. }
  4872. return io;
  4873. }
  4874. /*
  4875. * call-seq:
  4876. * IO.sysopen(path, [mode, [perm]]) -> fixnum
  4877. *
  4878. * Opens the given path, returning the underlying file descriptor as a
  4879. * <code>Fixnum</code>.
  4880. *
  4881. * IO.sysopen("testfile") #=> 3
  4882. *
  4883. */
  4884. static VALUE
  4885. rb_io_s_sysopen(int argc, VALUE *argv)
  4886. {
  4887. VALUE fname, vmode, vperm;
  4888. VALUE intmode;
  4889. int oflags, fd;
  4890. mode_t perm;
  4891. rb_scan_args(argc, argv, "12", &fname, &vmode, &vperm);
  4892. FilePathValue(fname);
  4893. if (NIL_P(vmode))
  4894. oflags = O_RDONLY;
  4895. else if (!NIL_P(intmode = rb_check_to_integer(vmode, "to_int")))
  4896. oflags = NUM2INT(intmode);
  4897. else {
  4898. SafeStringValue(vmode);
  4899. oflags = rb_io_modestr_oflags(StringValueCStr(vmode));
  4900. }
  4901. if (NIL_P(vperm)) perm = 0666;
  4902. else perm = NUM2UINT(vperm);
  4903. RB_GC_GUARD(fname) = rb_str_new4(fname);
  4904. fd = rb_sysopen(fname, oflags, perm);
  4905. return INT2NUM(fd);
  4906. }
  4907. static VALUE
  4908. check_pipe_command(VALUE filename_or_command)
  4909. {
  4910. char *s = RSTRING_PTR(filename_or_command);
  4911. long l = RSTRING_LEN(filename_or_command);
  4912. char *e = s + l;
  4913. int chlen;
  4914. if (rb_enc_ascget(s, e, &chlen, rb_enc_get(filename_or_command)) == '|') {
  4915. VALUE cmd = rb_str_new(s+chlen, l-chlen);
  4916. OBJ_INFECT(cmd, filename_or_command);
  4917. return cmd;
  4918. }
  4919. return Qnil;
  4920. }
  4921. /*
  4922. * call-seq:
  4923. * open(path [, mode_enc [, perm]] [, opt] ) -> io or nil
  4924. * open(path [, mode_enc [, perm]] [, opt] ) {|io| block } -> obj
  4925. *
  4926. * Creates an <code>IO</code> object connected to the given stream,
  4927. * file, or subprocess.
  4928. *
  4929. * If <i>path</i> does not start with a pipe character
  4930. * (``<code>|</code>''), treat it as the name of a file to open using
  4931. * the specified mode (defaulting to ``<code>r</code>'').
  4932. *
  4933. * The mode_enc is
  4934. * either a string or an integer. If it is an integer, it must be
  4935. * bitwise-or of open(2) flags, such as File::RDWR or File::EXCL.
  4936. * If it is a string, it is either "mode", "mode:ext_enc", or
  4937. * "mode:ext_enc:int_enc".
  4938. * The mode is one of the following:
  4939. *
  4940. * r: read (default)
  4941. * w: write
  4942. * a: append
  4943. *
  4944. * The mode can be followed by "b" (means binary-mode), or "+"
  4945. * (means both reading and writing allowed) or both.
  4946. * If ext_enc (external encoding) is specified,
  4947. * read string will be tagged by the encoding in reading,
  4948. * and output string will be converted
  4949. * to the specified encoding in writing.
  4950. * If ext_enc starts with 'BOM|', check whether the input has a BOM. If
  4951. * there is a BOM, strip it and set external encoding as
  4952. * what the BOM tells. If there is no BOM, use ext_enc without 'BOM|'.
  4953. * If two encoding names,
  4954. * ext_enc and int_enc (external encoding and internal encoding),
  4955. * are specified, the read string is converted from ext_enc
  4956. * to int_enc then tagged with the int_enc in read mode,
  4957. * and in write mode, the output string will be
  4958. * converted from int_enc to ext_enc before writing.
  4959. *
  4960. * If a file is being created, its initial permissions may be
  4961. * set using the integer third parameter.
  4962. *
  4963. * If a block is specified, it will be invoked with the
  4964. * <code>File</code> object as a parameter, and the file will be
  4965. * automatically closed when the block terminates. The call
  4966. * returns the value of the block.
  4967. *
  4968. * If <i>path</i> starts with a pipe character, a subprocess is
  4969. * created, connected to the caller by a pair of pipes. The returned
  4970. * <code>IO</code> object may be used to write to the standard input
  4971. * and read from the standard output of this subprocess. If the command
  4972. * following the ``<code>|</code>'' is a single minus sign, Ruby forks,
  4973. * and this subprocess is connected to the parent. In the subprocess,
  4974. * the <code>open</code> call returns <code>nil</code>. If the command
  4975. * is not ``<code>-</code>'', the subprocess runs the command. If a
  4976. * block is associated with an <code>open("|-")</code> call, that block
  4977. * will be run twice---once in the parent and once in the child. The
  4978. * block parameter will be an <code>IO</code> object in the parent and
  4979. * <code>nil</code> in the child. The parent's <code>IO</code> object
  4980. * will be connected to the child's <code>$stdin</code> and
  4981. * <code>$stdout</code>. The subprocess will be terminated at the end
  4982. * of the block.
  4983. *
  4984. * open("testfile") do |f|
  4985. * print f.gets
  4986. * end
  4987. *
  4988. * <em>produces:</em>
  4989. *
  4990. * This is line one
  4991. *
  4992. * Open a subprocess and read its output:
  4993. *
  4994. * cmd = open("|date")
  4995. * print cmd.gets
  4996. * cmd.close
  4997. *
  4998. * <em>produces:</em>
  4999. *
  5000. * Wed Apr 9 08:56:31 CDT 2003
  5001. *
  5002. * Open a subprocess running the same Ruby program:
  5003. *
  5004. * f = open("|-", "w+")
  5005. * if f == nil
  5006. * puts "in Child"
  5007. * exit
  5008. * else
  5009. * puts "Got: #{f.gets}"
  5010. * end
  5011. *
  5012. * <em>produces:</em>
  5013. *
  5014. * Got: in Child
  5015. *
  5016. * Open a subprocess using a block to receive the I/O object:
  5017. *
  5018. * open("|-") do |f|
  5019. * if f == nil
  5020. * puts "in Child"
  5021. * else
  5022. * puts "Got: #{f.gets}"
  5023. * end
  5024. * end
  5025. *
  5026. * <em>produces:</em>
  5027. *
  5028. * Got: in Child
  5029. */
  5030. static VALUE
  5031. rb_f_open(int argc, VALUE *argv)
  5032. {
  5033. ID to_open = 0;
  5034. int redirect = FALSE;
  5035. if (argc >= 1) {
  5036. CONST_ID(to_open, "to_open");
  5037. if (rb_respond_to(argv[0], to_open)) {
  5038. redirect = TRUE;
  5039. }
  5040. else {
  5041. VALUE tmp = argv[0];
  5042. FilePathValue(tmp);
  5043. if (NIL_P(tmp)) {
  5044. redirect = TRUE;
  5045. }
  5046. else {
  5047. VALUE cmd = check_pipe_command(tmp);
  5048. if (!NIL_P(cmd)) {
  5049. argv[0] = cmd;
  5050. return rb_io_s_popen(argc, argv, rb_cIO);
  5051. }
  5052. }
  5053. }
  5054. }
  5055. if (redirect) {
  5056. VALUE io = rb_funcall2(argv[0], to_open, argc-1, argv+1);
  5057. if (rb_block_given_p()) {
  5058. return rb_ensure(rb_yield, io, io_close, io);
  5059. }
  5060. return io;
  5061. }
  5062. return rb_io_s_open(argc, argv, rb_cFile);
  5063. }
  5064. static VALUE
  5065. rb_io_open(VALUE filename, VALUE vmode, VALUE vperm, VALUE opt)
  5066. {
  5067. VALUE cmd;
  5068. int oflags, fmode;
  5069. convconfig_t convconfig;
  5070. mode_t perm;
  5071. rb_io_extract_modeenc(&vmode, &vperm, opt, &oflags, &fmode, &convconfig);
  5072. perm = NIL_P(vperm) ? 0666 : NUM2UINT(vperm);
  5073. if (!NIL_P(cmd = check_pipe_command(filename))) {
  5074. return pipe_open_s(cmd, rb_io_oflags_modestr(oflags), fmode, &convconfig);
  5075. }
  5076. else {
  5077. return rb_file_open_generic(io_alloc(rb_cFile), filename,
  5078. oflags, fmode, &convconfig, perm);
  5079. }
  5080. }
  5081. static VALUE
  5082. rb_io_open_with_args(int argc, VALUE *argv)
  5083. {
  5084. VALUE io;
  5085. io = io_alloc(rb_cFile);
  5086. rb_open_file(argc, argv, io);
  5087. return io;
  5088. }
  5089. static VALUE
  5090. io_reopen(VALUE io, VALUE nfile)
  5091. {
  5092. rb_io_t *fptr, *orig;
  5093. int fd, fd2;
  5094. off_t pos = 0;
  5095. nfile = rb_io_get_io(nfile);
  5096. if (rb_safe_level() >= 4 &&
  5097. (!OBJ_UNTRUSTED(io) || !OBJ_UNTRUSTED(nfile))) {
  5098. rb_raise(rb_eSecurityError, "Insecure: can't reopen");
  5099. }
  5100. GetOpenFile(io, fptr);
  5101. GetOpenFile(nfile, orig);
  5102. if (fptr == orig) return io;
  5103. if (IS_PREP_STDIO(fptr)) {
  5104. if ((fptr->stdio_file == stdin && !(orig->mode & FMODE_READABLE)) ||
  5105. (fptr->stdio_file == stdout && !(orig->mode & FMODE_WRITABLE)) ||
  5106. (fptr->stdio_file == stderr && !(orig->mode & FMODE_WRITABLE))) {
  5107. rb_raise(rb_eArgError,
  5108. "%s can't change access mode from \"%s\" to \"%s\"",
  5109. PREP_STDIO_NAME(fptr), rb_io_fmode_modestr(fptr->mode),
  5110. rb_io_fmode_modestr(orig->mode));
  5111. }
  5112. }
  5113. if (fptr->mode & FMODE_WRITABLE) {
  5114. if (io_fflush(fptr) < 0)
  5115. rb_sys_fail(0);
  5116. }
  5117. else {
  5118. io_tell(fptr);
  5119. }
  5120. if (orig->mode & FMODE_READABLE) {
  5121. pos = io_tell(orig);
  5122. }
  5123. if (orig->mode & FMODE_WRITABLE) {
  5124. if (io_fflush(orig) < 0)
  5125. rb_sys_fail(0);
  5126. }
  5127. /* copy rb_io_t structure */
  5128. fptr->mode = orig->mode | (fptr->mode & FMODE_PREP);
  5129. fptr->pid = orig->pid;
  5130. fptr->lineno = orig->lineno;
  5131. if (RTEST(orig->pathv)) fptr->pathv = orig->pathv;
  5132. else if (!IS_PREP_STDIO(fptr)) fptr->pathv = Qnil;
  5133. fptr->finalize = orig->finalize;
  5134. #if defined (__CYGWIN__) || !defined(HAVE_FORK)
  5135. if (fptr->finalize == pipe_finalize)
  5136. pipe_add_fptr(fptr);
  5137. #endif
  5138. fd = fptr->fd;
  5139. fd2 = orig->fd;
  5140. if (fd != fd2) {
  5141. if (IS_PREP_STDIO(fptr) || fd <= 2 || !fptr->stdio_file) {
  5142. /* need to keep FILE objects of stdin, stdout and stderr */
  5143. if (dup2(fd2, fd) < 0)
  5144. rb_sys_fail_path(orig->pathv);
  5145. }
  5146. else {
  5147. fclose(fptr->stdio_file);
  5148. fptr->stdio_file = 0;
  5149. fptr->fd = -1;
  5150. if (dup2(fd2, fd) < 0)
  5151. rb_sys_fail_path(orig->pathv);
  5152. fptr->fd = fd;
  5153. }
  5154. rb_thread_fd_close(fd);
  5155. if ((orig->mode & FMODE_READABLE) && pos >= 0) {
  5156. if (io_seek(fptr, pos, SEEK_SET) < 0 && errno) {
  5157. rb_sys_fail_path(fptr->pathv);
  5158. }
  5159. if (io_seek(orig, pos, SEEK_SET) < 0 && errno) {
  5160. rb_sys_fail_path(orig->pathv);
  5161. }
  5162. }
  5163. }
  5164. if (fptr->mode & FMODE_BINMODE) {
  5165. rb_io_binmode(io);
  5166. }
  5167. RBASIC(io)->klass = rb_obj_class(nfile);
  5168. return io;
  5169. }
  5170. /*
  5171. * call-seq:
  5172. * ios.reopen(other_IO) -> ios
  5173. * ios.reopen(path, mode_str) -> ios
  5174. *
  5175. * Reassociates <em>ios</em> with the I/O stream given in
  5176. * <i>other_IO</i> or to a new stream opened on <i>path</i>. This may
  5177. * dynamically change the actual class of this stream.
  5178. *
  5179. * f1 = File.new("testfile")
  5180. * f2 = File.new("testfile")
  5181. * f2.readlines[0] #=> "This is line one\n"
  5182. * f2.reopen(f1) #=> #<File:testfile>
  5183. * f2.readlines[0] #=> "This is line one\n"
  5184. */
  5185. static VALUE
  5186. rb_io_reopen(int argc, VALUE *argv, VALUE file)
  5187. {
  5188. VALUE fname, nmode;
  5189. int oflags;
  5190. rb_io_t *fptr;
  5191. rb_secure(4);
  5192. if (rb_scan_args(argc, argv, "11", &fname, &nmode) == 1) {
  5193. VALUE tmp = rb_io_check_io(fname);
  5194. if (!NIL_P(tmp)) {
  5195. return io_reopen(file, tmp);
  5196. }
  5197. }
  5198. FilePathValue(fname);
  5199. rb_io_taint_check(file);
  5200. fptr = RFILE(file)->fptr;
  5201. if (!fptr) {
  5202. fptr = RFILE(file)->fptr = ALLOC(rb_io_t);
  5203. MEMZERO(fptr, rb_io_t, 1);
  5204. }
  5205. if (!NIL_P(nmode)) {
  5206. int fmode = rb_io_modestr_fmode(StringValueCStr(nmode));
  5207. if (IS_PREP_STDIO(fptr) &&
  5208. ((fptr->mode & FMODE_READWRITE) & (fmode & FMODE_READWRITE)) !=
  5209. (fptr->mode & FMODE_READWRITE)) {
  5210. rb_raise(rb_eArgError,
  5211. "%s can't change access mode from \"%s\" to \"%s\"",
  5212. PREP_STDIO_NAME(fptr), rb_io_fmode_modestr(fptr->mode),
  5213. rb_io_fmode_modestr(fmode));
  5214. }
  5215. fptr->mode = fmode;
  5216. rb_io_mode_enc(fptr, StringValueCStr(nmode));
  5217. fptr->encs.ecflags = 0;
  5218. fptr->encs.ecopts = Qnil;
  5219. }
  5220. fptr->pathv = rb_str_new_frozen(fname);
  5221. oflags = rb_io_fmode_oflags(fptr->mode);
  5222. if (fptr->fd < 0) {
  5223. fptr->fd = rb_sysopen(fptr->pathv, oflags, 0666);
  5224. fptr->stdio_file = 0;
  5225. return file;
  5226. }
  5227. if (fptr->mode & FMODE_WRITABLE) {
  5228. if (io_fflush(fptr) < 0)
  5229. rb_sys_fail(0);
  5230. }
  5231. fptr->rbuf_off = fptr->rbuf_len = 0;
  5232. if (fptr->stdio_file) {
  5233. if (freopen(RSTRING_PTR(fptr->pathv), rb_io_oflags_modestr(oflags), fptr->stdio_file) == 0) {
  5234. rb_sys_fail_path(fptr->pathv);
  5235. }
  5236. fptr->fd = fileno(fptr->stdio_file);
  5237. #ifdef USE_SETVBUF
  5238. if (setvbuf(fptr->stdio_file, NULL, _IOFBF, 0) != 0)
  5239. rb_warn("setvbuf() can't be honoured for %s", RSTRING_PTR(fptr->pathv));
  5240. #endif
  5241. }
  5242. else {
  5243. if (close(fptr->fd) < 0)
  5244. rb_sys_fail_path(fptr->pathv);
  5245. fptr->fd = -1;
  5246. fptr->fd = rb_sysopen(fptr->pathv, oflags, 0666);
  5247. }
  5248. return file;
  5249. }
  5250. /* :nodoc: */
  5251. static VALUE
  5252. rb_io_init_copy(VALUE dest, VALUE io)
  5253. {
  5254. rb_io_t *fptr, *orig;
  5255. int fd;
  5256. VALUE write_io;
  5257. off_t pos;
  5258. io = rb_io_get_io(io);
  5259. if (dest == io) return dest;
  5260. GetOpenFile(io, orig);
  5261. MakeOpenFile(dest, fptr);
  5262. rb_io_flush(io);
  5263. /* copy rb_io_t structure */
  5264. fptr->mode = orig->mode & ~FMODE_PREP;
  5265. fptr->encs = orig->encs;
  5266. fptr->pid = orig->pid;
  5267. fptr->lineno = orig->lineno;
  5268. if (!NIL_P(orig->pathv)) fptr->pathv = orig->pathv;
  5269. fptr->finalize = orig->finalize;
  5270. #if defined (__CYGWIN__) || !defined(HAVE_FORK)
  5271. if (fptr->finalize == pipe_finalize)
  5272. pipe_add_fptr(fptr);
  5273. #endif
  5274. fd = ruby_dup(orig->fd);
  5275. fptr->fd = fd;
  5276. pos = io_tell(orig);
  5277. if (0 <= pos)
  5278. io_seek(fptr, pos, SEEK_SET);
  5279. if (fptr->mode & FMODE_BINMODE) {
  5280. rb_io_binmode(dest);
  5281. }
  5282. write_io = GetWriteIO(io);
  5283. if (io != write_io) {
  5284. write_io = rb_obj_dup(write_io);
  5285. fptr->tied_io_for_writing = write_io;
  5286. rb_ivar_set(dest, rb_intern("@tied_io_for_writing"), write_io);
  5287. }
  5288. return dest;
  5289. }
  5290. /*
  5291. * call-seq:
  5292. * ios.printf(format_string [, obj, ...] ) -> nil
  5293. *
  5294. * Formats and writes to <em>ios</em>, converting parameters under
  5295. * control of the format string. See <code>Kernel#sprintf</code>
  5296. * for details.
  5297. */
  5298. VALUE
  5299. rb_io_printf(int argc, VALUE *argv, VALUE out)
  5300. {
  5301. rb_io_write(out, rb_f_sprintf(argc, argv));
  5302. return Qnil;
  5303. }
  5304. /*
  5305. * call-seq:
  5306. * printf(io, string [, obj ... ] ) -> nil
  5307. * printf(string [, obj ... ] ) -> nil
  5308. *
  5309. * Equivalent to:
  5310. * io.write(sprintf(string, obj, ...)
  5311. * or
  5312. * $stdout.write(sprintf(string, obj, ...)
  5313. */
  5314. static VALUE
  5315. rb_f_printf(int argc, VALUE *argv)
  5316. {
  5317. VALUE out;
  5318. if (argc == 0) return Qnil;
  5319. if (TYPE(argv[0]) == T_STRING) {
  5320. out = rb_stdout;
  5321. }
  5322. else {
  5323. out = argv[0];
  5324. argv++;
  5325. argc--;
  5326. }
  5327. rb_io_write(out, rb_f_sprintf(argc, argv));
  5328. return Qnil;
  5329. }
  5330. /*
  5331. * call-seq:
  5332. * ios.print() -> nil
  5333. * ios.print(obj, ...) -> nil
  5334. *
  5335. * Writes the given object(s) to <em>ios</em>. The stream must be
  5336. * opened for writing. If the output field separator (<code>$,</code>)
  5337. * is not <code>nil</code>, it will be inserted between each object.
  5338. * If the output record separator (<code>$\\</code>)
  5339. * is not <code>nil</code>, it will be appended to the output. If no
  5340. * arguments are given, prints <code>$_</code>. Objects that aren't
  5341. * strings will be converted by calling their <code>to_s</code> method.
  5342. * With no argument, prints the contents of the variable <code>$_</code>.
  5343. * Returns <code>nil</code>.
  5344. *
  5345. * $stdout.print("This is ", 100, " percent.\n")
  5346. *
  5347. * <em>produces:</em>
  5348. *
  5349. * This is 100 percent.
  5350. */
  5351. VALUE
  5352. rb_io_print(int argc, VALUE *argv, VALUE out)
  5353. {
  5354. int i;
  5355. VALUE line;
  5356. /* if no argument given, print `$_' */
  5357. if (argc == 0) {
  5358. argc = 1;
  5359. line = rb_lastline_get();
  5360. argv = &line;
  5361. }
  5362. for (i=0; i<argc; i++) {
  5363. if (!NIL_P(rb_output_fs) && i>0) {
  5364. rb_io_write(out, rb_output_fs);
  5365. }
  5366. rb_io_write(out, argv[i]);
  5367. }
  5368. if (argc > 0 && !NIL_P(rb_output_rs)) {
  5369. rb_io_write(out, rb_output_rs);
  5370. }
  5371. return Qnil;
  5372. }
  5373. /*
  5374. * call-seq:
  5375. * print(obj, ...) -> nil
  5376. *
  5377. * Prints each object in turn to <code>$stdout</code>. If the output
  5378. * field separator (<code>$,</code>) is not +nil+, its
  5379. * contents will appear between each field. If the output record
  5380. * separator (<code>$\\</code>) is not +nil+, it will be
  5381. * appended to the output. If no arguments are given, prints
  5382. * <code>$_</code>. Objects that aren't strings will be converted by
  5383. * calling their <code>to_s</code> method.
  5384. *
  5385. * print "cat", [1,2,3], 99, "\n"
  5386. * $, = ", "
  5387. * $\ = "\n"
  5388. * print "cat", [1,2,3], 99
  5389. *
  5390. * <em>produces:</em>
  5391. *
  5392. * cat12399
  5393. * cat, 1, 2, 3, 99
  5394. */
  5395. static VALUE
  5396. rb_f_print(int argc, VALUE *argv)
  5397. {
  5398. rb_io_print(argc, argv, rb_stdout);
  5399. return Qnil;
  5400. }
  5401. /*
  5402. * call-seq:
  5403. * ios.putc(obj) -> obj
  5404. *
  5405. * If <i>obj</i> is <code>Numeric</code>, write the character whose code is
  5406. * the least-significant byte of <i>obj</i>, otherwise write the first byte
  5407. * of the string representation of <i>obj</i> to <em>ios</em>. Note: This
  5408. * method is not safe for use with multi-byte characters as it will truncate
  5409. * them.
  5410. *
  5411. * $stdout.putc "A"
  5412. * $stdout.putc 65
  5413. *
  5414. * <em>produces:</em>
  5415. *
  5416. * AA
  5417. */
  5418. static VALUE
  5419. rb_io_putc(VALUE io, VALUE ch)
  5420. {
  5421. char c = NUM2CHR(ch);
  5422. rb_io_write(io, rb_str_new(&c, 1));
  5423. return ch;
  5424. }
  5425. /*
  5426. * call-seq:
  5427. * putc(int) -> int
  5428. *
  5429. * Equivalent to:
  5430. *
  5431. * $stdout.putc(int)
  5432. *
  5433. * Refer to the documentation for IO#putc for important information regarding
  5434. * multi-byte characters.
  5435. */
  5436. static VALUE
  5437. rb_f_putc(VALUE recv, VALUE ch)
  5438. {
  5439. if (recv == rb_stdout) {
  5440. return rb_io_putc(recv, ch);
  5441. }
  5442. return rb_funcall2(rb_stdout, rb_intern("putc"), 1, &ch);
  5443. }
  5444. static VALUE
  5445. io_puts_ary(VALUE ary, VALUE out, int recur)
  5446. {
  5447. VALUE tmp;
  5448. long i;
  5449. if (recur) {
  5450. tmp = rb_str_new2("[...]");
  5451. rb_io_puts(1, &tmp, out);
  5452. return Qnil;
  5453. }
  5454. for (i=0; i<RARRAY_LEN(ary); i++) {
  5455. tmp = RARRAY_PTR(ary)[i];
  5456. rb_io_puts(1, &tmp, out);
  5457. }
  5458. return Qnil;
  5459. }
  5460. /*
  5461. * call-seq:
  5462. * ios.puts(obj, ...) -> nil
  5463. *
  5464. * Writes the given objects to <em>ios</em> as with
  5465. * <code>IO#print</code>. Writes a record separator (typically a
  5466. * newline) after any that do not already end with a newline sequence.
  5467. * If called with an array argument, writes each element on a new line.
  5468. * If called without arguments, outputs a single record separator.
  5469. *
  5470. * $stdout.puts("this", "is", "a", "test")
  5471. *
  5472. * <em>produces:</em>
  5473. *
  5474. * this
  5475. * is
  5476. * a
  5477. * test
  5478. */
  5479. VALUE
  5480. rb_io_puts(int argc, VALUE *argv, VALUE out)
  5481. {
  5482. int i;
  5483. VALUE line;
  5484. /* if no argument given, print newline. */
  5485. if (argc == 0) {
  5486. rb_io_write(out, rb_default_rs);
  5487. return Qnil;
  5488. }
  5489. for (i=0; i<argc; i++) {
  5490. if (TYPE(argv[i]) == T_STRING) {
  5491. line = argv[i];
  5492. goto string;
  5493. }
  5494. line = rb_check_array_type(argv[i]);
  5495. if (!NIL_P(line)) {
  5496. rb_exec_recursive(io_puts_ary, line, out);
  5497. continue;
  5498. }
  5499. line = rb_obj_as_string(argv[i]);
  5500. string:
  5501. rb_io_write(out, line);
  5502. if (RSTRING_LEN(line) == 0 ||
  5503. RSTRING_PTR(line)[RSTRING_LEN(line)-1] != '\n') {
  5504. rb_io_write(out, rb_default_rs);
  5505. }
  5506. }
  5507. return Qnil;
  5508. }
  5509. /*
  5510. * call-seq:
  5511. * puts(obj, ...) -> nil
  5512. *
  5513. * Equivalent to
  5514. *
  5515. * $stdout.puts(obj, ...)
  5516. */
  5517. static VALUE
  5518. rb_f_puts(int argc, VALUE *argv, VALUE recv)
  5519. {
  5520. if (recv == rb_stdout) {
  5521. return rb_io_puts(argc, argv, recv);
  5522. }
  5523. return rb_funcall2(rb_stdout, rb_intern("puts"), argc, argv);
  5524. }
  5525. void
  5526. rb_p(VALUE obj) /* for debug print within C code */
  5527. {
  5528. VALUE str = rb_obj_as_string(rb_inspect(obj));
  5529. if (TYPE(rb_stdout) == T_FILE &&
  5530. rb_method_basic_definition_p(CLASS_OF(rb_stdout), id_write)) {
  5531. io_write(rb_stdout, str, 1);
  5532. io_write(rb_stdout, rb_default_rs, 0);
  5533. }
  5534. else {
  5535. rb_io_write(rb_stdout, str);
  5536. rb_io_write(rb_stdout, rb_default_rs);
  5537. }
  5538. }
  5539. /*
  5540. * call-seq:
  5541. * p(obj) -> obj
  5542. * p(obj1, obj2, ...) -> [obj, ...]
  5543. * p() -> nil
  5544. *
  5545. * For each object, directly writes
  5546. * _obj_.+inspect+ followed by the current output
  5547. * record separator to the program's standard output.
  5548. *
  5549. * S = Struct.new(:name, :state)
  5550. * s = S['dave', 'TX']
  5551. * p s
  5552. *
  5553. * <em>produces:</em>
  5554. *
  5555. * #<S name="dave", state="TX">
  5556. */
  5557. static VALUE
  5558. rb_f_p(int argc, VALUE *argv, VALUE self)
  5559. {
  5560. int i;
  5561. VALUE ret = Qnil;
  5562. for (i=0; i<argc; i++) {
  5563. rb_p(argv[i]);
  5564. }
  5565. if (argc == 1) {
  5566. ret = argv[0];
  5567. }
  5568. else if (argc > 1) {
  5569. ret = rb_ary_new4(argc, argv);
  5570. }
  5571. if (TYPE(rb_stdout) == T_FILE) {
  5572. rb_io_flush(rb_stdout);
  5573. }
  5574. return ret;
  5575. }
  5576. /*
  5577. * call-seq:
  5578. * obj.display(port=$>) -> nil
  5579. *
  5580. * Prints <i>obj</i> on the given port (default <code>$></code>).
  5581. * Equivalent to:
  5582. *
  5583. * def display(port=$>)
  5584. * port.write self
  5585. * end
  5586. *
  5587. * For example:
  5588. *
  5589. * 1.display
  5590. * "cat".display
  5591. * [ 4, 5, 6 ].display
  5592. * puts
  5593. *
  5594. * <em>produces:</em>
  5595. *
  5596. * 1cat456
  5597. */
  5598. static VALUE
  5599. rb_obj_display(int argc, VALUE *argv, VALUE self)
  5600. {
  5601. VALUE out;
  5602. if (argc == 0) {
  5603. out = rb_stdout;
  5604. }
  5605. else {
  5606. rb_scan_args(argc, argv, "01", &out);
  5607. }
  5608. rb_io_write(out, self);
  5609. return Qnil;
  5610. }
  5611. void
  5612. rb_write_error2(const char *mesg, long len)
  5613. {
  5614. if (rb_stderr == orig_stderr || RFILE(orig_stderr)->fptr->fd < 0) {
  5615. (void)fwrite(mesg, sizeof(char), len, stderr);
  5616. }
  5617. else {
  5618. rb_io_write(rb_stderr, rb_str_new(mesg, len));
  5619. }
  5620. }
  5621. void
  5622. rb_write_error(const char *mesg)
  5623. {
  5624. rb_write_error2(mesg, strlen(mesg));
  5625. }
  5626. static void
  5627. must_respond_to(ID mid, VALUE val, ID id)
  5628. {
  5629. if (!rb_respond_to(val, mid)) {
  5630. rb_raise(rb_eTypeError, "%s must have %s method, %s given",
  5631. rb_id2name(id), rb_id2name(mid),
  5632. rb_obj_classname(val));
  5633. }
  5634. }
  5635. static void
  5636. stdout_setter(VALUE val, ID id, VALUE *variable)
  5637. {
  5638. must_respond_to(id_write, val, id);
  5639. *variable = val;
  5640. }
  5641. static VALUE
  5642. prep_io(int fd, int fmode, VALUE klass, const char *path)
  5643. {
  5644. rb_io_t *fp;
  5645. VALUE io = io_alloc(klass);
  5646. MakeOpenFile(io, fp);
  5647. fp->fd = fd;
  5648. #ifdef __CYGWIN__
  5649. if (!isatty(fd)) {
  5650. fmode |= FMODE_BINMODE;
  5651. setmode(fd, O_BINARY);
  5652. }
  5653. #endif
  5654. fp->mode = fmode;
  5655. io_check_tty(fp);
  5656. if (path) fp->pathv = rb_obj_freeze(rb_str_new_cstr(path));
  5657. return io;
  5658. }
  5659. VALUE
  5660. rb_io_fdopen(int fd, int oflags, const char *path)
  5661. {
  5662. VALUE klass = rb_cIO;
  5663. if (path && strcmp(path, "-")) klass = rb_cFile;
  5664. return prep_io(fd, rb_io_oflags_fmode(oflags), klass, path);
  5665. }
  5666. static VALUE
  5667. prep_stdio(FILE *f, int fmode, VALUE klass, const char *path)
  5668. {
  5669. rb_io_t *fptr;
  5670. VALUE io = prep_io(fileno(f), fmode|FMODE_PREP, klass, path);
  5671. GetOpenFile(io, fptr);
  5672. fptr->stdio_file = f;
  5673. return io;
  5674. }
  5675. FILE *
  5676. rb_io_stdio_file(rb_io_t *fptr)
  5677. {
  5678. if (!fptr->stdio_file) {
  5679. int oflags = rb_io_fmode_oflags(fptr->mode);
  5680. fptr->stdio_file = rb_fdopen(fptr->fd, rb_io_oflags_modestr(oflags));
  5681. }
  5682. return fptr->stdio_file;
  5683. }
  5684. /*
  5685. * call-seq:
  5686. * IO.new(fd [, mode] [, opt]) -> io
  5687. *
  5688. * Returns a new <code>IO</code> object (a stream) for the given
  5689. * <code>IO</code> object or integer file descriptor and mode
  5690. * string. See also <code>IO.sysopen</code> and
  5691. * <code>IO.for_fd</code>.
  5692. *
  5693. * === Parameters
  5694. * fd:: numeric file descriptor
  5695. * mode:: file mode. a string or an integer
  5696. * opt:: hash for specifying mode by name.
  5697. *
  5698. * ==== Mode
  5699. * When <code>mode</code> is an integer it must be combination of
  5700. * the modes defined in <code>File::Constants</code>.
  5701. *
  5702. * When <code>mode</code> is a string it must be in one of the
  5703. * following forms:
  5704. * - "fmode",
  5705. * - "fmode:extern",
  5706. * - "fmode:extern:intern".
  5707. * <code>extern</code> is the external encoding name for the IO.
  5708. * <code>intern</code> is the internal encoding.
  5709. * <code>fmode</code> must be combination of the directives. See
  5710. * the description of class +IO+ for a description of the directives.
  5711. *
  5712. * When the mode of original IO is read only, the mode cannot be changed to
  5713. * be writable. Similarly, the mode cannot be changed from write only to
  5714. * readable.
  5715. * If such a wrong change is directed, timing where the error actually occurs
  5716. * is different according to the platform.
  5717. *
  5718. * ==== Options
  5719. * <code>opt</code> can have the following keys
  5720. * :mode ::
  5721. * same as <code>mode</code> parameter
  5722. * :external_encoding ::
  5723. * external encoding for the IO. "-" is a
  5724. * synonym for the default external encoding.
  5725. * :internal_encoding ::
  5726. * internal encoding for the IO.
  5727. * "-" is a synonym for the default internal encoding.
  5728. * If the value is nil no conversion occurs.
  5729. * :encoding ::
  5730. * specifies external and internal encodings as "extern:intern".
  5731. * :textmode ::
  5732. * If the value is truth value, same as "t" in argument <code>mode</code>.
  5733. * :binmode ::
  5734. * If the value is truth value, same as "b" in argument <code>mode</code>.
  5735. * :autoclose ::
  5736. * If the value is +false+, the _fd_ will be kept open after this
  5737. * +IO+ instance gets finalized.
  5738. *
  5739. * Also <code>opt</code> can have same keys in <code>String#encode</code> for
  5740. * controlling conversion between the external encoding and the internal encoding.
  5741. *
  5742. * === Example1
  5743. *
  5744. * fd = IO.sysopen("/dev/tty", "w")
  5745. * a = IO.new(fd,"w")
  5746. * $stderr.puts "Hello"
  5747. * a.puts "World"
  5748. *
  5749. * <em>produces:</em>
  5750. *
  5751. * Hello
  5752. * World
  5753. *
  5754. * === Example2
  5755. *
  5756. * require 'fcntl'
  5757. *
  5758. * fd = STDERR.fcntl(Fcntl::F_DUPFD)
  5759. * io = IO.new(fd, mode: 'w:UTF-16LE', cr_newline: true)
  5760. * io.puts "Hello, World!"
  5761. *
  5762. * fd = STDERR.fcntl(Fcntl::F_DUPFD)
  5763. * io = IO.new(fd, mode: 'w', cr_newline: true, external_encoding: Encoding::UTF_16LE)
  5764. * io.puts "Hello, World!"
  5765. *
  5766. * both of above print "Hello, World!" in UTF-16LE to standard error output with
  5767. * converting EOL generated by <code>puts</code> to CR.
  5768. */
  5769. static VALUE
  5770. rb_io_initialize(int argc, VALUE *argv, VALUE io)
  5771. {
  5772. VALUE fnum, vmode;
  5773. rb_io_t *fp;
  5774. int fd, fmode, oflags = O_RDONLY;
  5775. convconfig_t convconfig;
  5776. VALUE opt;
  5777. #if defined(HAVE_FCNTL) && defined(F_GETFL)
  5778. int ofmode;
  5779. #else
  5780. struct stat st;
  5781. #endif
  5782. rb_secure(4);
  5783. opt = pop_last_hash(&argc, argv);
  5784. rb_scan_args(argc, argv, "11", &fnum, &vmode);
  5785. rb_io_extract_modeenc(&vmode, 0, opt, &oflags, &fmode, &convconfig);
  5786. fd = NUM2INT(fnum);
  5787. #if defined(HAVE_FCNTL) && defined(F_GETFL)
  5788. oflags = fcntl(fd, F_GETFL);
  5789. if (oflags == -1) rb_sys_fail(0);
  5790. #else
  5791. if (fstat(fd, &st) == -1) rb_sys_fail(0);
  5792. #endif
  5793. UPDATE_MAXFD(fd);
  5794. #if defined(HAVE_FCNTL) && defined(F_GETFL)
  5795. ofmode = rb_io_oflags_fmode(oflags);
  5796. if (NIL_P(vmode)) {
  5797. fmode = ofmode;
  5798. }
  5799. else if ((~ofmode & fmode) & FMODE_READWRITE) {
  5800. VALUE error = INT2FIX(EINVAL);
  5801. rb_exc_raise(rb_class_new_instance(1, &error, rb_eSystemCallError));
  5802. }
  5803. #endif
  5804. if (!NIL_P(opt) && rb_hash_aref(opt, sym_autoclose) == Qfalse) {
  5805. fmode |= FMODE_PREP;
  5806. }
  5807. MakeOpenFile(io, fp);
  5808. fp->fd = fd;
  5809. fp->mode = fmode;
  5810. fp->encs = convconfig;
  5811. clear_codeconv(fp);
  5812. io_check_tty(fp);
  5813. if (fileno(stdin) == fd)
  5814. fp->stdio_file = stdin;
  5815. else if (fileno(stdout) == fd)
  5816. fp->stdio_file = stdout;
  5817. else if (fileno(stderr) == fd)
  5818. fp->stdio_file = stderr;
  5819. if (fmode & FMODE_SETENC_BY_BOM) io_set_encoding_by_bom(io);
  5820. return io;
  5821. }
  5822. /*
  5823. * call-seq:
  5824. * File.new(filename, mode="r" [, opt]) -> file
  5825. * File.new(filename [, mode [, perm]] [, opt]) -> file
  5826. *
  5827. * Opens the file named by _filename_ according to
  5828. * _mode_ (default is ``r'') and returns a new
  5829. * <code>File</code> object.
  5830. *
  5831. * === Parameters
  5832. * See the description of class +IO+ for a description of _mode_.
  5833. * The file mode may optionally be specified as a +Fixnum+
  5834. * by _or_-ing together the flags (O_RDONLY etc,
  5835. * again described under +IO+).
  5836. *
  5837. * Optional permission bits may be given in _perm_.
  5838. * These mode and permission bits are platform dependent;
  5839. * on Unix systems, see <code>open(2)</code> for details.
  5840. *
  5841. * Optional _opt_ parameter is same as in <code.IO.open</code>.
  5842. *
  5843. * === Examples
  5844. *
  5845. * f = File.new("testfile", "r")
  5846. * f = File.new("newfile", "w+")
  5847. * f = File.new("newfile", File::CREAT|File::TRUNC|File::RDWR, 0644)
  5848. */
  5849. static VALUE
  5850. rb_file_initialize(int argc, VALUE *argv, VALUE io)
  5851. {
  5852. if (RFILE(io)->fptr) {
  5853. rb_raise(rb_eRuntimeError, "reinitializing File");
  5854. }
  5855. if (0 < argc && argc < 3) {
  5856. VALUE fd = rb_check_convert_type(argv[0], T_FIXNUM, "Fixnum", "to_int");
  5857. if (!NIL_P(fd)) {
  5858. argv[0] = fd;
  5859. return rb_io_initialize(argc, argv, io);
  5860. }
  5861. }
  5862. rb_open_file(argc, argv, io);
  5863. return io;
  5864. }
  5865. /* :nodoc: */
  5866. static VALUE
  5867. rb_io_s_new(int argc, VALUE *argv, VALUE klass)
  5868. {
  5869. if (rb_block_given_p()) {
  5870. const char *cname = rb_class2name(klass);
  5871. rb_warn("%s::new() does not take block; use %s::open() instead",
  5872. cname, cname);
  5873. }
  5874. return rb_class_new_instance(argc, argv, klass);
  5875. }
  5876. /*
  5877. * call-seq:
  5878. * IO.for_fd(fd, mode [, opt]) -> io
  5879. *
  5880. * Synonym for <code>IO.new</code>.
  5881. *
  5882. */
  5883. static VALUE
  5884. rb_io_s_for_fd(int argc, VALUE *argv, VALUE klass)
  5885. {
  5886. VALUE io = rb_obj_alloc(klass);
  5887. rb_io_initialize(argc, argv, io);
  5888. return io;
  5889. }
  5890. /*
  5891. * call-seq:
  5892. * ios.autoclose? -> true or false
  5893. *
  5894. * Returns +true+ if the underlying file descriptor of _ios_ will be
  5895. * closed automatically at its finalization, otherwise +false+.
  5896. */
  5897. static VALUE
  5898. rb_io_autoclose_p(VALUE io)
  5899. {
  5900. rb_io_t *fptr;
  5901. rb_secure(4);
  5902. GetOpenFile(io, fptr);
  5903. return (fptr->mode & FMODE_PREP) ? Qfalse : Qtrue;
  5904. }
  5905. /*
  5906. * call-seq:
  5907. * io.autoclose = bool -> true or false
  5908. *
  5909. * Sets auto-close flag.
  5910. *
  5911. * f = open("/dev/null")
  5912. * IO.for_fd(f.fileno)
  5913. * # ...
  5914. * f.gets # may cause IOError
  5915. *
  5916. * f = open("/dev/null")
  5917. * IO.for_fd(f.fileno).autoclose = true
  5918. * # ...
  5919. * f.gets # won't cause IOError
  5920. */
  5921. static VALUE
  5922. rb_io_set_autoclose(VALUE io, VALUE autoclose)
  5923. {
  5924. rb_io_t *fptr;
  5925. rb_secure(4);
  5926. GetOpenFile(io, fptr);
  5927. if (!RTEST(autoclose))
  5928. fptr->mode |= FMODE_PREP;
  5929. else
  5930. fptr->mode &= ~FMODE_PREP;
  5931. return io;
  5932. }
  5933. static void
  5934. argf_mark(void *ptr)
  5935. {
  5936. struct argf *p = ptr;
  5937. rb_gc_mark(p->filename);
  5938. rb_gc_mark(p->current_file);
  5939. rb_gc_mark(p->argv);
  5940. rb_gc_mark(p->encs.ecopts);
  5941. }
  5942. static void
  5943. argf_free(void *ptr)
  5944. {
  5945. struct argf *p = ptr;
  5946. xfree(p->inplace);
  5947. xfree(p);
  5948. }
  5949. static inline void
  5950. argf_init(struct argf *p, VALUE v)
  5951. {
  5952. p->filename = Qnil;
  5953. p->current_file = Qnil;
  5954. p->lineno = 0;
  5955. p->argv = v;
  5956. }
  5957. static VALUE
  5958. argf_alloc(VALUE klass)
  5959. {
  5960. struct argf *p;
  5961. VALUE argf = Data_Make_Struct(klass, struct argf, argf_mark, argf_free, p);
  5962. argf_init(p, Qnil);
  5963. return argf;
  5964. }
  5965. #undef rb_argv
  5966. /* :nodoc: */
  5967. static VALUE
  5968. argf_initialize(VALUE argf, VALUE argv)
  5969. {
  5970. memset(&ARGF, 0, sizeof(ARGF));
  5971. argf_init(&ARGF, argv);
  5972. return argf;
  5973. }
  5974. /* :nodoc: */
  5975. static VALUE
  5976. argf_initialize_copy(VALUE argf, VALUE orig)
  5977. {
  5978. ARGF = argf_of(orig);
  5979. ARGF.argv = rb_obj_dup(ARGF.argv);
  5980. if (ARGF.inplace) {
  5981. const char *inplace = ARGF.inplace;
  5982. ARGF.inplace = 0;
  5983. ARGF.inplace = ruby_strdup(inplace);
  5984. }
  5985. return argf;
  5986. }
  5987. /*
  5988. * call-seq:
  5989. * ARGF.lineno = number -> nil
  5990. *
  5991. * Sets the line number of +ARGF+ as a whole to the given +Integer+.
  5992. *
  5993. * +ARGF+ sets the line number automatically as you read data, so normally
  5994. * you will not need to set it explicitly. To access the current line number
  5995. * use +ARGF.lineno+.
  5996. *
  5997. * For example:
  5998. *
  5999. * ARGF.lineno #=> 0
  6000. * ARGF.readline #=> "This is line 1\n"
  6001. * ARGF.lineno #=> 1
  6002. * ARGF.lineno = 0 #=> nil
  6003. * ARGF.lineno #=> 0
  6004. */
  6005. static VALUE
  6006. argf_set_lineno(VALUE argf, VALUE val)
  6007. {
  6008. ARGF.lineno = NUM2INT(val);
  6009. ARGF.last_lineno = ARGF.lineno;
  6010. return Qnil;
  6011. }
  6012. /*
  6013. * call-seq:
  6014. * ARGF.lineno -> integer
  6015. *
  6016. * Returns the current line number of ARGF as a whole. This value
  6017. * can be set manually with +ARGF.lineno=+.
  6018. *
  6019. * For example:
  6020. *
  6021. * ARGF.lineno #=> 0
  6022. * ARGF.readline #=> "This is line 1\n"
  6023. * ARGF.lineno #=> 1
  6024. */
  6025. static VALUE
  6026. argf_lineno(VALUE argf)
  6027. {
  6028. return INT2FIX(ARGF.lineno);
  6029. }
  6030. static VALUE
  6031. argf_forward(int argc, VALUE *argv, VALUE argf)
  6032. {
  6033. return rb_funcall3(ARGF.current_file, rb_frame_this_func(), argc, argv);
  6034. }
  6035. #define next_argv() argf_next_argv(argf)
  6036. #define ARGF_GENERIC_INPUT_P() \
  6037. (ARGF.current_file == rb_stdin && TYPE(ARGF.current_file) != T_FILE)
  6038. #define ARGF_FORWARD(argc, argv) do {\
  6039. if (ARGF_GENERIC_INPUT_P())\
  6040. return argf_forward(argc, argv, argf);\
  6041. } while (0)
  6042. #define NEXT_ARGF_FORWARD(argc, argv) do {\
  6043. if (!next_argv()) return Qnil;\
  6044. ARGF_FORWARD(argc, argv);\
  6045. } while (0)
  6046. static void
  6047. argf_close(VALUE file)
  6048. {
  6049. rb_funcall3(file, rb_intern("close"), 0, 0);
  6050. }
  6051. static int
  6052. argf_next_argv(VALUE argf)
  6053. {
  6054. char *fn;
  6055. rb_io_t *fptr;
  6056. int stdout_binmode = 0;
  6057. if (TYPE(rb_stdout) == T_FILE) {
  6058. GetOpenFile(rb_stdout, fptr);
  6059. if (fptr->mode & FMODE_BINMODE)
  6060. stdout_binmode = 1;
  6061. }
  6062. if (ARGF.init_p == 0) {
  6063. if (!NIL_P(ARGF.argv) && RARRAY_LEN(ARGF.argv) > 0) {
  6064. ARGF.next_p = 1;
  6065. }
  6066. else {
  6067. ARGF.next_p = -1;
  6068. }
  6069. ARGF.init_p = 1;
  6070. }
  6071. if (ARGF.next_p == 1) {
  6072. ARGF.next_p = 0;
  6073. retry:
  6074. if (RARRAY_LEN(ARGF.argv) > 0) {
  6075. ARGF.filename = rb_ary_shift(ARGF.argv);
  6076. fn = StringValueCStr(ARGF.filename);
  6077. if (strlen(fn) == 1 && fn[0] == '-') {
  6078. ARGF.current_file = rb_stdin;
  6079. if (ARGF.inplace) {
  6080. rb_warn("Can't do inplace edit for stdio; skipping");
  6081. goto retry;
  6082. }
  6083. }
  6084. else {
  6085. int fr = rb_sysopen(ARGF.filename, O_RDONLY, 0);
  6086. if (ARGF.inplace) {
  6087. struct stat st;
  6088. #ifndef NO_SAFE_RENAME
  6089. struct stat st2;
  6090. #endif
  6091. VALUE str;
  6092. int fw;
  6093. if (TYPE(rb_stdout) == T_FILE && rb_stdout != orig_stdout) {
  6094. rb_io_close(rb_stdout);
  6095. }
  6096. fstat(fr, &st);
  6097. if (*ARGF.inplace) {
  6098. str = rb_str_new2(fn);
  6099. #ifdef NO_LONG_FNAME
  6100. ruby_add_suffix(str, ARGF.inplace);
  6101. #else
  6102. rb_str_cat2(str, ARGF.inplace);
  6103. #endif
  6104. #ifdef NO_SAFE_RENAME
  6105. (void)close(fr);
  6106. (void)unlink(RSTRING_PTR(str));
  6107. (void)rename(fn, RSTRING_PTR(str));
  6108. fr = rb_sysopen(str, O_RDONLY, 0);
  6109. #else
  6110. if (rename(fn, RSTRING_PTR(str)) < 0) {
  6111. rb_warn("Can't rename %s to %s: %s, skipping file",
  6112. fn, RSTRING_PTR(str), strerror(errno));
  6113. close(fr);
  6114. goto retry;
  6115. }
  6116. #endif
  6117. }
  6118. else {
  6119. #ifdef NO_SAFE_RENAME
  6120. rb_fatal("Can't do inplace edit without backup");
  6121. #else
  6122. if (unlink(fn) < 0) {
  6123. rb_warn("Can't remove %s: %s, skipping file",
  6124. fn, strerror(errno));
  6125. close(fr);
  6126. goto retry;
  6127. }
  6128. #endif
  6129. }
  6130. fw = rb_sysopen(ARGF.filename, O_WRONLY|O_CREAT|O_TRUNC, 0666);
  6131. #ifndef NO_SAFE_RENAME
  6132. fstat(fw, &st2);
  6133. #ifdef HAVE_FCHMOD
  6134. fchmod(fw, st.st_mode);
  6135. #else
  6136. chmod(fn, st.st_mode);
  6137. #endif
  6138. if (st.st_uid!=st2.st_uid || st.st_gid!=st2.st_gid) {
  6139. int err;
  6140. #ifdef HAVE_FCHOWN
  6141. err = fchown(fw, st.st_uid, st.st_gid);
  6142. #else
  6143. err = chown(fn, st.st_uid, st.st_gid);
  6144. #endif
  6145. if (err && getuid() == 0 && st2.st_uid == 0) {
  6146. const char *wkfn = RSTRING_PTR(ARGF.filename);
  6147. rb_warn("Can't set owner/group of %s to same as %s: %s, skipping file",
  6148. wkfn, fn, strerror(errno));
  6149. (void)close(fr);
  6150. (void)close(fw);
  6151. (void)unlink(wkfn);
  6152. goto retry;
  6153. }
  6154. }
  6155. #endif
  6156. rb_stdout = prep_io(fw, FMODE_WRITABLE, rb_cFile, fn);
  6157. if (stdout_binmode) rb_io_binmode(rb_stdout);
  6158. }
  6159. ARGF.current_file = prep_io(fr, FMODE_READABLE, rb_cFile, fn);
  6160. }
  6161. if (ARGF.binmode) rb_io_ascii8bit_binmode(ARGF.current_file);
  6162. if (ARGF.encs.enc) {
  6163. rb_io_t *fptr;
  6164. GetOpenFile(ARGF.current_file, fptr);
  6165. fptr->encs = ARGF.encs;
  6166. clear_codeconv(fptr);
  6167. }
  6168. }
  6169. else {
  6170. ARGF.next_p = 1;
  6171. return FALSE;
  6172. }
  6173. }
  6174. else if (ARGF.next_p == -1) {
  6175. ARGF.current_file = rb_stdin;
  6176. ARGF.filename = rb_str_new2("-");
  6177. if (ARGF.inplace) {
  6178. rb_warn("Can't do inplace edit for stdio");
  6179. rb_stdout = orig_stdout;
  6180. }
  6181. }
  6182. return TRUE;
  6183. }
  6184. static VALUE
  6185. argf_getline(int argc, VALUE *argv, VALUE argf)
  6186. {
  6187. VALUE line;
  6188. int lineno = ARGF.lineno;
  6189. retry:
  6190. if (!next_argv()) return Qnil;
  6191. if (ARGF_GENERIC_INPUT_P()) {
  6192. line = rb_funcall3(ARGF.current_file, rb_intern("gets"), argc, argv);
  6193. }
  6194. else {
  6195. if (argc == 0 && rb_rs == rb_default_rs) {
  6196. line = rb_io_gets(ARGF.current_file);
  6197. }
  6198. else {
  6199. line = rb_io_getline(argc, argv, ARGF.current_file);
  6200. }
  6201. if (NIL_P(line) && ARGF.next_p != -1) {
  6202. argf_close(ARGF.current_file);
  6203. ARGF.next_p = 1;
  6204. goto retry;
  6205. }
  6206. }
  6207. if (!NIL_P(line)) {
  6208. ARGF.lineno = ++lineno;
  6209. ARGF.last_lineno = ARGF.lineno;
  6210. }
  6211. return line;
  6212. }
  6213. static VALUE
  6214. argf_lineno_getter(ID id, VALUE *var)
  6215. {
  6216. VALUE argf = *var;
  6217. return INT2FIX(ARGF.last_lineno);
  6218. }
  6219. static void
  6220. argf_lineno_setter(VALUE val, ID id, VALUE *var)
  6221. {
  6222. VALUE argf = *var;
  6223. int n = NUM2INT(val);
  6224. ARGF.last_lineno = ARGF.lineno = n;
  6225. }
  6226. static VALUE argf_gets(int, VALUE *, VALUE);
  6227. /*
  6228. * call-seq:
  6229. * gets(sep=$/) -> string or nil
  6230. * gets(limit) -> string or nil
  6231. * gets(sep,limit) -> string or nil
  6232. *
  6233. * Returns (and assigns to <code>$_</code>) the next line from the list
  6234. * of files in +ARGV+ (or <code>$*</code>), or from standard input if
  6235. * no files are present on the command line. Returns +nil+ at end of
  6236. * file. The optional argument specifies the record separator. The
  6237. * separator is included with the contents of each record. A separator
  6238. * of +nil+ reads the entire contents, and a zero-length separator
  6239. * reads the input one paragraph at a time, where paragraphs are
  6240. * divided by two consecutive newlines. If the first argument is an
  6241. * integer, or optional second argument is given, the returning string
  6242. * would not be longer than the given value in bytes. If multiple
  6243. * filenames are present in +ARGV+, +gets(nil)+ will read the contents
  6244. * one file at a time.
  6245. *
  6246. * ARGV << "testfile"
  6247. * print while gets
  6248. *
  6249. * <em>produces:</em>
  6250. *
  6251. * This is line one
  6252. * This is line two
  6253. * This is line three
  6254. * And so on...
  6255. *
  6256. * The style of programming using <code>$_</code> as an implicit
  6257. * parameter is gradually losing favor in the Ruby community.
  6258. */
  6259. static VALUE
  6260. rb_f_gets(int argc, VALUE *argv, VALUE recv)
  6261. {
  6262. if (recv == argf) {
  6263. return argf_gets(argc, argv, argf);
  6264. }
  6265. return rb_funcall2(argf, rb_intern("gets"), argc, argv);
  6266. }
  6267. /*
  6268. * call-seq:
  6269. * ARGF.gets(sep=$/) -> string
  6270. * ARGF.gets(limit) -> string
  6271. * ARGF.gets(sep, limit) -> string
  6272. *
  6273. * Returns the next line from the current file in +ARGF+.
  6274. *
  6275. * By default lines are assumed to be separated by +$/+; to use a different
  6276. * character as a separator, supply it as a +String+ for the _sep_ argument.
  6277. *
  6278. * The optional _limit_ argument specifies how many characters of each line
  6279. * to return. By default all characters are returned.
  6280. *
  6281. */
  6282. static VALUE
  6283. argf_gets(int argc, VALUE *argv, VALUE argf)
  6284. {
  6285. VALUE line;
  6286. line = argf_getline(argc, argv, argf);
  6287. rb_lastline_set(line);
  6288. return line;
  6289. }
  6290. VALUE
  6291. rb_gets(void)
  6292. {
  6293. VALUE line;
  6294. if (rb_rs != rb_default_rs) {
  6295. return rb_f_gets(0, 0, argf);
  6296. }
  6297. retry:
  6298. if (!next_argv()) return Qnil;
  6299. line = rb_io_gets(ARGF.current_file);
  6300. if (NIL_P(line) && ARGF.next_p != -1) {
  6301. rb_io_close(ARGF.current_file);
  6302. ARGF.next_p = 1;
  6303. goto retry;
  6304. }
  6305. rb_lastline_set(line);
  6306. if (!NIL_P(line)) {
  6307. ARGF.lineno++;
  6308. ARGF.last_lineno = ARGF.lineno;
  6309. }
  6310. return line;
  6311. }
  6312. static VALUE argf_readline(int, VALUE *, VALUE);
  6313. /*
  6314. * call-seq:
  6315. * readline(sep=$/) -> string
  6316. * readline(limit) -> string
  6317. * readline(sep, limit) -> string
  6318. *
  6319. * Equivalent to <code>Kernel::gets</code>, except
  6320. * +readline+ raises +EOFError+ at end of file.
  6321. */
  6322. static VALUE
  6323. rb_f_readline(int argc, VALUE *argv, VALUE recv)
  6324. {
  6325. if (recv == argf) {
  6326. return argf_readline(argc, argv, argf);
  6327. }
  6328. return rb_funcall2(argf, rb_intern("readline"), argc, argv);
  6329. }
  6330. /*
  6331. * call-seq:
  6332. * ARGF.readline(sep=$/) -> string
  6333. * ARGF.readline(limit) -> string
  6334. * ARGF.readline(sep, limit) -> string
  6335. *
  6336. * Returns the next line from the current file in +ARGF+.
  6337. *
  6338. * By default lines are assumed to be separated by +$/+; to use a different
  6339. * character as a separator, supply it as a +String+ for the _sep_ argument.
  6340. *
  6341. * The optional _limit_ argument specifies how many characters of each line
  6342. * to return. By default all characters are returned.
  6343. *
  6344. * An +EOFError+ is raised at the end of the file.
  6345. */
  6346. static VALUE
  6347. argf_readline(int argc, VALUE *argv, VALUE argf)
  6348. {
  6349. VALUE line;
  6350. if (!next_argv()) rb_eof_error();
  6351. ARGF_FORWARD(argc, argv);
  6352. line = argf_gets(argc, argv, argf);
  6353. if (NIL_P(line)) {
  6354. rb_eof_error();
  6355. }
  6356. return line;
  6357. }
  6358. static VALUE argf_readlines(int, VALUE *, VALUE);
  6359. /*
  6360. * call-seq:
  6361. * readlines(sep=$/) -> array
  6362. * readlines(limit) -> array
  6363. * readlines(sep,limit) -> array
  6364. *
  6365. * Returns an array containing the lines returned by calling
  6366. * <code>Kernel.gets(<i>sep</i>)</code> until the end of file.
  6367. */
  6368. static VALUE
  6369. rb_f_readlines(int argc, VALUE *argv, VALUE recv)
  6370. {
  6371. if (recv == argf) {
  6372. return argf_readlines(argc, argv, argf);
  6373. }
  6374. return rb_funcall2(argf, rb_intern("readlines"), argc, argv);
  6375. }
  6376. /*
  6377. * call-seq:
  6378. * ARGF.readlines(sep=$/) -> array
  6379. * ARGF.readlines(limit) -> array
  6380. * ARGF.readlines(sep, limit) -> array
  6381. *
  6382. * ARGF.to_a(sep=$/) -> array
  6383. * ARGF.to_a(limit) -> array
  6384. * ARGF.to_a(sep, limit) -> array
  6385. *
  6386. * Reads +ARGF+'s current file in its entirety, returning an +Array+ of its
  6387. * lines, one line per element. Lines are assumed to be separated by _sep_.
  6388. *
  6389. * lines = ARGF.readlines
  6390. * lines[0] #=> "This is line one\n"
  6391. */
  6392. static VALUE
  6393. argf_readlines(int argc, VALUE *argv, VALUE argf)
  6394. {
  6395. VALUE line, ary;
  6396. ary = rb_ary_new();
  6397. while (!NIL_P(line = argf_getline(argc, argv, argf))) {
  6398. rb_ary_push(ary, line);
  6399. }
  6400. return ary;
  6401. }
  6402. /*
  6403. * call-seq:
  6404. * `cmd` -> string
  6405. *
  6406. * Returns the standard output of running _cmd_ in a subshell.
  6407. * The built-in syntax <code>%x{...}</code> uses
  6408. * this method. Sets <code>$?</code> to the process status.
  6409. *
  6410. * `date` #=> "Wed Apr 9 08:56:30 CDT 2003\n"
  6411. * `ls testdir`.split[1] #=> "main.rb"
  6412. * `echo oops && exit 99` #=> "oops\n"
  6413. * $?.exitstatus #=> 99
  6414. */
  6415. static VALUE
  6416. rb_f_backquote(VALUE obj, VALUE str)
  6417. {
  6418. volatile VALUE port;
  6419. VALUE result;
  6420. rb_io_t *fptr;
  6421. SafeStringValue(str);
  6422. port = pipe_open_s(str, "r", FMODE_READABLE, NULL);
  6423. if (NIL_P(port)) return rb_str_new(0,0);
  6424. GetOpenFile(port, fptr);
  6425. result = read_all(fptr, remain_size(fptr), Qnil);
  6426. rb_io_close(port);
  6427. return result;
  6428. }
  6429. #ifdef HAVE_SYS_SELECT_H
  6430. #include <sys/select.h>
  6431. #endif
  6432. static VALUE
  6433. select_internal(VALUE read, VALUE write, VALUE except, struct timeval *tp, rb_fdset_t *fds)
  6434. {
  6435. VALUE res, list;
  6436. rb_fdset_t *rp, *wp, *ep;
  6437. rb_io_t *fptr;
  6438. long i;
  6439. int max = 0, n;
  6440. int interrupt_flag = 0;
  6441. int pending = 0;
  6442. struct timeval timerec;
  6443. if (!NIL_P(read)) {
  6444. Check_Type(read, T_ARRAY);
  6445. for (i=0; i<RARRAY_LEN(read); i++) {
  6446. GetOpenFile(rb_io_get_io(RARRAY_PTR(read)[i]), fptr);
  6447. rb_fd_set(fptr->fd, &fds[0]);
  6448. if (READ_DATA_PENDING(fptr) || READ_CHAR_PENDING(fptr)) { /* check for buffered data */
  6449. pending++;
  6450. rb_fd_set(fptr->fd, &fds[3]);
  6451. }
  6452. if (max < fptr->fd) max = fptr->fd;
  6453. }
  6454. if (pending) { /* no blocking if there's buffered data */
  6455. timerec.tv_sec = timerec.tv_usec = 0;
  6456. tp = &timerec;
  6457. }
  6458. rp = &fds[0];
  6459. }
  6460. else
  6461. rp = 0;
  6462. if (!NIL_P(write)) {
  6463. Check_Type(write, T_ARRAY);
  6464. for (i=0; i<RARRAY_LEN(write); i++) {
  6465. VALUE write_io = GetWriteIO(rb_io_get_io(RARRAY_PTR(write)[i]));
  6466. GetOpenFile(write_io, fptr);
  6467. rb_fd_set(fptr->fd, &fds[1]);
  6468. if (max < fptr->fd) max = fptr->fd;
  6469. }
  6470. wp = &fds[1];
  6471. }
  6472. else
  6473. wp = 0;
  6474. if (!NIL_P(except)) {
  6475. Check_Type(except, T_ARRAY);
  6476. for (i=0; i<RARRAY_LEN(except); i++) {
  6477. VALUE io = rb_io_get_io(RARRAY_PTR(except)[i]);
  6478. VALUE write_io = GetWriteIO(io);
  6479. GetOpenFile(io, fptr);
  6480. rb_fd_set(fptr->fd, &fds[2]);
  6481. if (max < fptr->fd) max = fptr->fd;
  6482. if (io != write_io) {
  6483. GetOpenFile(write_io, fptr);
  6484. rb_fd_set(fptr->fd, &fds[2]);
  6485. if (max < fptr->fd) max = fptr->fd;
  6486. }
  6487. }
  6488. ep = &fds[2];
  6489. }
  6490. else {
  6491. ep = 0;
  6492. }
  6493. max++;
  6494. n = rb_thread_fd_select(max, rp, wp, ep, tp);
  6495. if (n < 0) {
  6496. rb_sys_fail(0);
  6497. }
  6498. if (!pending && n == 0) return Qnil; /* returns nil on timeout */
  6499. res = rb_ary_new2(3);
  6500. rb_ary_push(res, rp?rb_ary_new():rb_ary_new2(0));
  6501. rb_ary_push(res, wp?rb_ary_new():rb_ary_new2(0));
  6502. rb_ary_push(res, ep?rb_ary_new():rb_ary_new2(0));
  6503. if (interrupt_flag == 0) {
  6504. if (rp) {
  6505. list = RARRAY_PTR(res)[0];
  6506. for (i=0; i< RARRAY_LEN(read); i++) {
  6507. VALUE obj = rb_ary_entry(read, i);
  6508. VALUE io = rb_io_get_io(obj);
  6509. GetOpenFile(io, fptr);
  6510. if (rb_fd_isset(fptr->fd, &fds[0]) ||
  6511. rb_fd_isset(fptr->fd, &fds[3])) {
  6512. rb_ary_push(list, obj);
  6513. }
  6514. }
  6515. }
  6516. if (wp) {
  6517. list = RARRAY_PTR(res)[1];
  6518. for (i=0; i< RARRAY_LEN(write); i++) {
  6519. VALUE obj = rb_ary_entry(write, i);
  6520. VALUE io = rb_io_get_io(obj);
  6521. VALUE write_io = GetWriteIO(io);
  6522. GetOpenFile(write_io, fptr);
  6523. if (rb_fd_isset(fptr->fd, &fds[1])) {
  6524. rb_ary_push(list, obj);
  6525. }
  6526. }
  6527. }
  6528. if (ep) {
  6529. list = RARRAY_PTR(res)[2];
  6530. for (i=0; i< RARRAY_LEN(except); i++) {
  6531. VALUE obj = rb_ary_entry(except, i);
  6532. VALUE io = rb_io_get_io(obj);
  6533. VALUE write_io = GetWriteIO(io);
  6534. GetOpenFile(io, fptr);
  6535. if (rb_fd_isset(fptr->fd, &fds[2])) {
  6536. rb_ary_push(list, obj);
  6537. }
  6538. else if (io != write_io) {
  6539. GetOpenFile(write_io, fptr);
  6540. if (rb_fd_isset(fptr->fd, &fds[2])) {
  6541. rb_ary_push(list, obj);
  6542. }
  6543. }
  6544. }
  6545. }
  6546. }
  6547. return res; /* returns an empty array on interrupt */
  6548. }
  6549. struct select_args {
  6550. VALUE read, write, except;
  6551. struct timeval *timeout;
  6552. rb_fdset_t fdsets[4];
  6553. };
  6554. #ifdef HAVE_RB_FD_INIT
  6555. static VALUE
  6556. select_call(VALUE arg)
  6557. {
  6558. struct select_args *p = (struct select_args *)arg;
  6559. return select_internal(p->read, p->write, p->except, p->timeout, p->fdsets);
  6560. }
  6561. static VALUE
  6562. select_end(VALUE arg)
  6563. {
  6564. struct select_args *p = (struct select_args *)arg;
  6565. int i;
  6566. for (i = 0; i < numberof(p->fdsets); ++i)
  6567. rb_fd_term(&p->fdsets[i]);
  6568. return Qnil;
  6569. }
  6570. #endif
  6571. /*
  6572. * call-seq:
  6573. * IO.select(read_array
  6574. * [, write_array
  6575. * [, error_array
  6576. * [, timeout]]] )-> array or nil
  6577. *
  6578. * See <code>Kernel#select</code>.
  6579. */
  6580. static VALUE
  6581. rb_f_select(int argc, VALUE *argv, VALUE obj)
  6582. {
  6583. VALUE timeout;
  6584. struct select_args args;
  6585. struct timeval timerec;
  6586. int i;
  6587. rb_scan_args(argc, argv, "13", &args.read, &args.write, &args.except, &timeout);
  6588. if (NIL_P(timeout)) {
  6589. args.timeout = 0;
  6590. }
  6591. else {
  6592. timerec = rb_time_interval(timeout);
  6593. args.timeout = &timerec;
  6594. }
  6595. for (i = 0; i < numberof(args.fdsets); ++i)
  6596. rb_fd_init(&args.fdsets[i]);
  6597. #ifdef HAVE_RB_FD_INIT
  6598. return rb_ensure(select_call, (VALUE)&args, select_end, (VALUE)&args);
  6599. #else
  6600. return select_internal(args.read, args.write, args.except,
  6601. args.timeout, args.fdsets);
  6602. #endif
  6603. }
  6604. static int
  6605. io_cntl(int fd, unsigned long cmd, long narg, int io_p)
  6606. {
  6607. int retval;
  6608. #ifdef HAVE_FCNTL
  6609. # if defined(__CYGWIN__)
  6610. retval = io_p?ioctl(fd, cmd, (void*)narg):fcntl(fd, cmd, narg);
  6611. # else
  6612. retval = io_p?ioctl(fd, cmd, narg):fcntl(fd, (int)cmd, narg);
  6613. # endif
  6614. # if defined(F_DUPFD)
  6615. if (!io_p && retval != -1 && cmd == F_DUPFD) {
  6616. UPDATE_MAXFD(retval);
  6617. }
  6618. # endif
  6619. #else
  6620. if (!io_p) {
  6621. rb_notimplement();
  6622. }
  6623. retval = ioctl(fd, cmd, narg);
  6624. #endif
  6625. return retval;
  6626. }
  6627. static VALUE
  6628. rb_io_ctl(VALUE io, VALUE req, VALUE arg, int io_p)
  6629. {
  6630. unsigned long cmd = NUM2ULONG(req);
  6631. rb_io_t *fptr;
  6632. long len = 0;
  6633. long narg = 0;
  6634. int retval;
  6635. rb_secure(2);
  6636. if (NIL_P(arg) || arg == Qfalse) {
  6637. narg = 0;
  6638. }
  6639. else if (FIXNUM_P(arg)) {
  6640. narg = FIX2LONG(arg);
  6641. }
  6642. else if (arg == Qtrue) {
  6643. narg = 1;
  6644. }
  6645. else {
  6646. VALUE tmp = rb_check_string_type(arg);
  6647. if (NIL_P(tmp)) {
  6648. narg = NUM2LONG(arg);
  6649. }
  6650. else {
  6651. arg = tmp;
  6652. #ifdef IOCPARM_MASK
  6653. #ifndef IOCPARM_LEN
  6654. #define IOCPARM_LEN(x) (((x) >> 16) & IOCPARM_MASK)
  6655. #endif
  6656. #endif
  6657. #ifdef IOCPARM_LEN
  6658. len = IOCPARM_LEN(cmd); /* on BSDish systems we're safe */
  6659. #else
  6660. len = 256; /* otherwise guess at what's safe */
  6661. #endif
  6662. rb_str_modify(arg);
  6663. if (len <= RSTRING_LEN(arg)) {
  6664. len = RSTRING_LEN(arg);
  6665. }
  6666. if (RSTRING_LEN(arg) < len) {
  6667. rb_str_resize(arg, len+1);
  6668. }
  6669. RSTRING_PTR(arg)[len] = 17; /* a little sanity check here */
  6670. narg = (long)RSTRING_PTR(arg);
  6671. }
  6672. }
  6673. GetOpenFile(io, fptr);
  6674. retval = io_cntl(fptr->fd, cmd, narg, io_p);
  6675. if (retval < 0) rb_sys_fail_path(fptr->pathv);
  6676. if (TYPE(arg) == T_STRING && RSTRING_PTR(arg)[len] != 17) {
  6677. rb_raise(rb_eArgError, "return value overflowed string");
  6678. }
  6679. if (!io_p && cmd == F_SETFL) {
  6680. if (narg & O_NONBLOCK) {
  6681. fptr->mode |= FMODE_WSPLIT_INITIALIZED;
  6682. fptr->mode &= ~FMODE_WSPLIT;
  6683. }
  6684. else {
  6685. fptr->mode &= ~(FMODE_WSPLIT_INITIALIZED|FMODE_WSPLIT);
  6686. }
  6687. }
  6688. return INT2NUM(retval);
  6689. }
  6690. /*
  6691. * call-seq:
  6692. * ios.ioctl(integer_cmd, arg) -> integer
  6693. *
  6694. * Provides a mechanism for issuing low-level commands to control or
  6695. * query I/O devices. Arguments and results are platform dependent. If
  6696. * <i>arg</i> is a number, its value is passed directly. If it is a
  6697. * string, it is interpreted as a binary sequence of bytes. On Unix
  6698. * platforms, see <code>ioctl(2)</code> for details. Not implemented on
  6699. * all platforms.
  6700. */
  6701. static VALUE
  6702. rb_io_ioctl(int argc, VALUE *argv, VALUE io)
  6703. {
  6704. VALUE req, arg;
  6705. rb_scan_args(argc, argv, "11", &req, &arg);
  6706. return rb_io_ctl(io, req, arg, 1);
  6707. }
  6708. #ifdef HAVE_FCNTL
  6709. /*
  6710. * call-seq:
  6711. * ios.fcntl(integer_cmd, arg) -> integer
  6712. *
  6713. * Provides a mechanism for issuing low-level commands to control or
  6714. * query file-oriented I/O streams. Arguments and results are platform
  6715. * dependent. If <i>arg</i> is a number, its value is passed
  6716. * directly. If it is a string, it is interpreted as a binary sequence
  6717. * of bytes (<code>Array#pack</code> might be a useful way to build this
  6718. * string). On Unix platforms, see <code>fcntl(2)</code> for details.
  6719. * Not implemented on all platforms.
  6720. */
  6721. static VALUE
  6722. rb_io_fcntl(int argc, VALUE *argv, VALUE io)
  6723. {
  6724. VALUE req, arg;
  6725. rb_scan_args(argc, argv, "11", &req, &arg);
  6726. return rb_io_ctl(io, req, arg, 0);
  6727. }
  6728. #else
  6729. #define rb_io_fcntl rb_f_notimplement
  6730. #endif
  6731. #if defined(HAVE_SYSCALL) && SIZEOF_LONG == SIZEOF_INT
  6732. /*
  6733. * call-seq:
  6734. * syscall(fixnum [, args...]) -> integer
  6735. *
  6736. * Calls the operating system function identified by _fixnum_,
  6737. * passing in the arguments, which must be either +String+
  6738. * objects, or +Integer+ objects that ultimately fit within
  6739. * a native +long+. Up to nine parameters may be passed (14
  6740. * on the Atari-ST). The function identified by _fixnum_ is system
  6741. * dependent. On some Unix systems, the numbers may be obtained from a
  6742. * header file called <code>syscall.h</code>.
  6743. *
  6744. * syscall 4, 1, "hello\n", 6 # '4' is write(2) on our box
  6745. *
  6746. * <em>produces:</em>
  6747. *
  6748. * hello
  6749. */
  6750. static VALUE
  6751. rb_f_syscall(int argc, VALUE *argv)
  6752. {
  6753. #ifdef atarist
  6754. unsigned long arg[14]; /* yes, we really need that many ! */
  6755. #else
  6756. unsigned long arg[8];
  6757. #endif
  6758. int retval = -1;
  6759. int i = 1;
  6760. int items = argc - 1;
  6761. /* This probably won't work on machines where sizeof(long) != sizeof(int)
  6762. * or where sizeof(long) != sizeof(char*). But such machines will
  6763. * not likely have syscall implemented either, so who cares?
  6764. */
  6765. rb_secure(2);
  6766. if (argc == 0)
  6767. rb_raise(rb_eArgError, "too few arguments for syscall");
  6768. if (argc > numberof(arg))
  6769. rb_raise(rb_eArgError, "too many arguments for syscall");
  6770. arg[0] = NUM2LONG(argv[0]); argv++;
  6771. while (items--) {
  6772. VALUE v = rb_check_string_type(*argv);
  6773. if (!NIL_P(v)) {
  6774. SafeStringValue(v);
  6775. rb_str_modify(v);
  6776. arg[i] = (unsigned long)StringValueCStr(v);
  6777. }
  6778. else {
  6779. arg[i] = (unsigned long)NUM2LONG(*argv);
  6780. }
  6781. argv++;
  6782. i++;
  6783. }
  6784. switch (argc) {
  6785. case 1:
  6786. retval = syscall(arg[0]);
  6787. break;
  6788. case 2:
  6789. retval = syscall(arg[0],arg[1]);
  6790. break;
  6791. case 3:
  6792. retval = syscall(arg[0],arg[1],arg[2]);
  6793. break;
  6794. case 4:
  6795. retval = syscall(arg[0],arg[1],arg[2],arg[3]);
  6796. break;
  6797. case 5:
  6798. retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4]);
  6799. break;
  6800. case 6:
  6801. retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5]);
  6802. break;
  6803. case 7:
  6804. retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6]);
  6805. break;
  6806. case 8:
  6807. retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
  6808. arg[7]);
  6809. break;
  6810. #ifdef atarist
  6811. case 9:
  6812. retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
  6813. arg[7], arg[8]);
  6814. break;
  6815. case 10:
  6816. retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
  6817. arg[7], arg[8], arg[9]);
  6818. break;
  6819. case 11:
  6820. retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
  6821. arg[7], arg[8], arg[9], arg[10]);
  6822. break;
  6823. case 12:
  6824. retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
  6825. arg[7], arg[8], arg[9], arg[10], arg[11]);
  6826. break;
  6827. case 13:
  6828. retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
  6829. arg[7], arg[8], arg[9], arg[10], arg[11], arg[12]);
  6830. break;
  6831. case 14:
  6832. retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
  6833. arg[7], arg[8], arg[9], arg[10], arg[11], arg[12], arg[13]);
  6834. break;
  6835. #endif /* atarist */
  6836. }
  6837. if (retval < 0) rb_sys_fail(0);
  6838. return INT2NUM(retval);
  6839. }
  6840. #else
  6841. #define rb_f_syscall rb_f_notimplement
  6842. #endif
  6843. static VALUE
  6844. io_new_instance(VALUE args)
  6845. {
  6846. return rb_class_new_instance(2, (VALUE*)args+1, *(VALUE*)args);
  6847. }
  6848. static void
  6849. io_encoding_set(rb_io_t *fptr, VALUE v1, VALUE v2, VALUE opt)
  6850. {
  6851. rb_encoding *enc, *enc2;
  6852. int ecflags;
  6853. VALUE ecopts, tmp;
  6854. if (!NIL_P(v2)) {
  6855. enc2 = rb_to_encoding(v1);
  6856. tmp = rb_check_string_type(v2);
  6857. if (!NIL_P(tmp)) {
  6858. if (RSTRING_LEN(tmp) == 1 && RSTRING_PTR(tmp)[0] == '-') {
  6859. /* Special case - "-" => no transcoding */
  6860. enc = enc2;
  6861. enc2 = NULL;
  6862. }
  6863. else
  6864. enc = rb_to_encoding(v2);
  6865. if (enc == enc2) {
  6866. /* Special case - "-" => no transcoding */
  6867. enc2 = NULL;
  6868. }
  6869. }
  6870. else
  6871. enc = rb_to_encoding(v2);
  6872. ecflags = rb_econv_prepare_opts(opt, &ecopts);
  6873. }
  6874. else {
  6875. if (NIL_P(v1)) {
  6876. /* Set to default encodings */
  6877. rb_io_ext_int_to_encs(NULL, NULL, &enc, &enc2);
  6878. ecflags = 0;
  6879. ecopts = Qnil;
  6880. }
  6881. else {
  6882. tmp = rb_check_string_type(v1);
  6883. if (!NIL_P(tmp) && rb_enc_asciicompat(rb_enc_get(tmp))) {
  6884. parse_mode_enc(RSTRING_PTR(tmp), &enc, &enc2, NULL);
  6885. ecflags = rb_econv_prepare_opts(opt, &ecopts);
  6886. }
  6887. else {
  6888. rb_io_ext_int_to_encs(rb_to_encoding(v1), NULL, &enc, &enc2);
  6889. ecflags = 0;
  6890. ecopts = Qnil;
  6891. }
  6892. }
  6893. }
  6894. validate_enc_binmode(fptr->mode, enc, enc2);
  6895. fptr->encs.enc = enc;
  6896. fptr->encs.enc2 = enc2;
  6897. fptr->encs.ecflags = ecflags;
  6898. fptr->encs.ecopts = ecopts;
  6899. clear_codeconv(fptr);
  6900. }
  6901. static VALUE
  6902. pipe_pair_close(VALUE rw)
  6903. {
  6904. VALUE *rwp = (VALUE *)rw;
  6905. return rb_ensure(io_close, rwp[0], io_close, rwp[1]);
  6906. }
  6907. /*
  6908. * call-seq:
  6909. * IO.pipe -> [read_io, write_io]
  6910. * IO.pipe(ext_enc) -> [read_io, write_io]
  6911. * IO.pipe("ext_enc:int_enc" [, opt]) -> [read_io, write_io]
  6912. * IO.pipe(ext_enc, int_enc [, opt]) -> [read_io, write_io]
  6913. *
  6914. * IO.pipe(...) {|read_io, write_io| ... }
  6915. *
  6916. * Creates a pair of pipe endpoints (connected to each other) and
  6917. * returns them as a two-element array of <code>IO</code> objects:
  6918. * <code>[</code> <i>read_io</i>, <i>write_io</i> <code>]</code>.
  6919. *
  6920. * If a block is given, the block is called and
  6921. * returns the value of the block.
  6922. * <i>read_io</i> and <i>write_io</i> are sent to the block as arguments.
  6923. * If read_io and write_io are not closed when the block exits, they are closed.
  6924. * i.e. closing read_io and/or write_io doesn't cause an error.
  6925. *
  6926. * Not available on all platforms.
  6927. *
  6928. * If an encoding (encoding name or encoding object) is specified as an optional argument,
  6929. * read string from pipe is tagged with the encoding specified.
  6930. * If the argument is a colon separated two encoding names "A:B",
  6931. * the read string is converted from encoding A (external encoding)
  6932. * to encoding B (internal encoding), then tagged with B.
  6933. * If two optional arguments are specified, those must be
  6934. * encoding objects or encoding names,
  6935. * and the first one is the external encoding,
  6936. * and the second one is the internal encoding.
  6937. * If the external encoding and the internal encoding is specified,
  6938. * optional hash argument specify the conversion option.
  6939. *
  6940. * In the example below, the two processes close the ends of the pipe
  6941. * that they are not using. This is not just a cosmetic nicety. The
  6942. * read end of a pipe will not generate an end of file condition if
  6943. * there are any writers with the pipe still open. In the case of the
  6944. * parent process, the <code>rd.read</code> will never return if it
  6945. * does not first issue a <code>wr.close</code>.
  6946. *
  6947. * rd, wr = IO.pipe
  6948. *
  6949. * if fork
  6950. * wr.close
  6951. * puts "Parent got: <#{rd.read}>"
  6952. * rd.close
  6953. * Process.wait
  6954. * else
  6955. * rd.close
  6956. * puts "Sending message to parent"
  6957. * wr.write "Hi Dad"
  6958. * wr.close
  6959. * end
  6960. *
  6961. * <em>produces:</em>
  6962. *
  6963. * Sending message to parent
  6964. * Parent got: <Hi Dad>
  6965. */
  6966. static VALUE
  6967. rb_io_s_pipe(int argc, VALUE *argv, VALUE klass)
  6968. {
  6969. int pipes[2], state;
  6970. VALUE r, w, args[3], v1, v2;
  6971. VALUE opt;
  6972. rb_io_t *fptr, *fptr2;
  6973. int fmode = 0;
  6974. VALUE ret;
  6975. opt = pop_last_hash(&argc, argv);
  6976. rb_scan_args(argc, argv, "02", &v1, &v2);
  6977. if (rb_pipe(pipes) == -1)
  6978. rb_sys_fail(0);
  6979. args[0] = klass;
  6980. args[1] = INT2NUM(pipes[0]);
  6981. args[2] = INT2FIX(O_RDONLY);
  6982. r = rb_protect(io_new_instance, (VALUE)args, &state);
  6983. if (state) {
  6984. close(pipes[0]);
  6985. close(pipes[1]);
  6986. rb_jump_tag(state);
  6987. }
  6988. GetOpenFile(r, fptr);
  6989. io_encoding_set(fptr, v1, v2, opt);
  6990. args[1] = INT2NUM(pipes[1]);
  6991. args[2] = INT2FIX(O_WRONLY);
  6992. w = rb_protect(io_new_instance, (VALUE)args, &state);
  6993. if (state) {
  6994. close(pipes[1]);
  6995. if (!NIL_P(r)) rb_io_close(r);
  6996. rb_jump_tag(state);
  6997. }
  6998. GetOpenFile(w, fptr2);
  6999. rb_io_synchronized(fptr2);
  7000. extract_binmode(opt, &fmode);
  7001. fptr->mode |= fmode;
  7002. fptr2->mode |= fmode;
  7003. ret = rb_assoc_new(r, w);
  7004. if (rb_block_given_p()) {
  7005. VALUE rw[2];
  7006. rw[0] = r;
  7007. rw[1] = w;
  7008. return rb_ensure(rb_yield, ret, pipe_pair_close, (VALUE)rw);
  7009. }
  7010. return ret;
  7011. }
  7012. struct foreach_arg {
  7013. int argc;
  7014. VALUE *argv;
  7015. VALUE io;
  7016. };
  7017. static void
  7018. open_key_args(int argc, VALUE *argv, struct foreach_arg *arg)
  7019. {
  7020. VALUE opt, v;
  7021. FilePathValue(argv[0]);
  7022. arg->io = 0;
  7023. arg->argc = argc - 1;
  7024. arg->argv = argv + 1;
  7025. if (argc == 1) {
  7026. no_key:
  7027. arg->io = rb_io_open(argv[0], INT2NUM(O_RDONLY), INT2FIX(0666), Qnil);
  7028. return;
  7029. }
  7030. opt = pop_last_hash(&arg->argc, arg->argv);
  7031. if (NIL_P(opt)) goto no_key;
  7032. v = rb_hash_aref(opt, sym_open_args);
  7033. if (!NIL_P(v)) {
  7034. VALUE args;
  7035. long n;
  7036. v = rb_convert_type(v, T_ARRAY, "Array", "to_ary");
  7037. n = RARRAY_LEN(v) + 1;
  7038. #if SIZEOF_LONG > SIZEOF_INT
  7039. if (n > INT_MAX) {
  7040. rb_raise(rb_eArgError, "too many arguments");
  7041. }
  7042. #endif
  7043. args = rb_ary_tmp_new(n);
  7044. rb_ary_push(args, argv[0]);
  7045. rb_ary_concat(args, v);
  7046. arg->io = rb_io_open_with_args((int)n, RARRAY_PTR(args));
  7047. rb_ary_clear(args); /* prevent from GC */
  7048. return;
  7049. }
  7050. arg->io = rb_io_open(argv[0], Qnil, Qnil, opt);
  7051. }
  7052. static VALUE
  7053. io_s_foreach(struct foreach_arg *arg)
  7054. {
  7055. VALUE str;
  7056. while (!NIL_P(str = rb_io_gets_m(arg->argc, arg->argv, arg->io))) {
  7057. rb_yield(str);
  7058. }
  7059. return Qnil;
  7060. }
  7061. /*
  7062. * call-seq:
  7063. * IO.foreach(name, sep=$/ [, open_args]) {|line| block } -> nil
  7064. * IO.foreach(name, limit [, open_args]) {|line| block } -> nil
  7065. * IO.foreach(name, sep, limit [, open_args]) {|line| block } -> nil
  7066. * IO.foreach(...) -> an_enumerator
  7067. *
  7068. * Executes the block for every line in the named I/O port, where lines
  7069. * are separated by <em>sep</em>.
  7070. *
  7071. * If no block is given, an enumerator is returned instead.
  7072. *
  7073. * IO.foreach("testfile") {|x| print "GOT ", x }
  7074. *
  7075. * <em>produces:</em>
  7076. *
  7077. * GOT This is line one
  7078. * GOT This is line two
  7079. * GOT This is line three
  7080. * GOT And so on...
  7081. *
  7082. * If the last argument is a hash, it's the keyword argument to open.
  7083. * See <code>IO.read</code> for detail.
  7084. *
  7085. */
  7086. static VALUE
  7087. rb_io_s_foreach(int argc, VALUE *argv, VALUE self)
  7088. {
  7089. struct foreach_arg arg;
  7090. rb_scan_args(argc, argv, "13", NULL, NULL, NULL, NULL);
  7091. RETURN_ENUMERATOR(self, argc, argv);
  7092. open_key_args(argc, argv, &arg);
  7093. if (NIL_P(arg.io)) return Qnil;
  7094. return rb_ensure(io_s_foreach, (VALUE)&arg, rb_io_close, arg.io);
  7095. }
  7096. static VALUE
  7097. io_s_readlines(struct foreach_arg *arg)
  7098. {
  7099. return rb_io_readlines(arg->argc, arg->argv, arg->io);
  7100. }
  7101. /*
  7102. * call-seq:
  7103. * IO.readlines(name, sep=$/ [, open_args]) -> array
  7104. * IO.readlines(name, limit [, open_args]) -> array
  7105. * IO.readlines(name, sep, limit [, open_args]) -> array
  7106. *
  7107. * Reads the entire file specified by <i>name</i> as individual
  7108. * lines, and returns those lines in an array. Lines are separated by
  7109. * <i>sep</i>.
  7110. *
  7111. * a = IO.readlines("testfile")
  7112. * a[0] #=> "This is line one\n"
  7113. *
  7114. * If the last argument is a hash, it's the keyword argument to open.
  7115. * See <code>IO.read</code> for detail.
  7116. *
  7117. */
  7118. static VALUE
  7119. rb_io_s_readlines(int argc, VALUE *argv, VALUE io)
  7120. {
  7121. struct foreach_arg arg;
  7122. rb_scan_args(argc, argv, "13", NULL, NULL, NULL, NULL);
  7123. open_key_args(argc, argv, &arg);
  7124. if (NIL_P(arg.io)) return Qnil;
  7125. return rb_ensure(io_s_readlines, (VALUE)&arg, rb_io_close, arg.io);
  7126. }
  7127. static VALUE
  7128. io_s_read(struct foreach_arg *arg)
  7129. {
  7130. return io_read(arg->argc, arg->argv, arg->io);
  7131. }
  7132. struct seek_arg {
  7133. VALUE io;
  7134. VALUE offset;
  7135. int mode;
  7136. };
  7137. static VALUE
  7138. seek_before_access(VALUE argp)
  7139. {
  7140. struct seek_arg *arg = (struct seek_arg *)argp;
  7141. rb_io_binmode(arg->io);
  7142. return rb_io_seek(arg->io, arg->offset, arg->mode);
  7143. }
  7144. /*
  7145. * call-seq:
  7146. * IO.read(name, [length [, offset]] ) -> string
  7147. * IO.read(name, [length [, offset]], open_args) -> string
  7148. *
  7149. * Opens the file, optionally seeks to the given <i>offset</i>, then returns
  7150. * <i>length</i> bytes (defaulting to the rest of the file).
  7151. * <code>read</code> ensures the file is closed before returning.
  7152. *
  7153. * If the last argument is a hash, it specifies option for internal
  7154. * open(). The key would be the following. open_args: is exclusive
  7155. * to others.
  7156. *
  7157. * encoding: string or encoding
  7158. *
  7159. * specifies encoding of the read string. encoding will be ignored
  7160. * if length is specified.
  7161. *
  7162. * mode: string
  7163. *
  7164. * specifies mode argument for open(). it should start with "r"
  7165. * otherwise it would cause error.
  7166. *
  7167. * open_args: array of strings
  7168. *
  7169. * specifies arguments for open() as an array.
  7170. *
  7171. * IO.read("testfile") #=> "This is line one\nThis is line two\nThis is line three\nAnd so on...\n"
  7172. * IO.read("testfile", 20) #=> "This is line one\nThi"
  7173. * IO.read("testfile", 20, 10) #=> "ne one\nThis is line "
  7174. */
  7175. static VALUE
  7176. rb_io_s_read(int argc, VALUE *argv, VALUE io)
  7177. {
  7178. VALUE offset;
  7179. struct foreach_arg arg;
  7180. rb_scan_args(argc, argv, "13", NULL, NULL, &offset, NULL);
  7181. open_key_args(argc, argv, &arg);
  7182. if (NIL_P(arg.io)) return Qnil;
  7183. if (!NIL_P(offset)) {
  7184. struct seek_arg sarg;
  7185. int state = 0;
  7186. sarg.io = arg.io;
  7187. sarg.offset = offset;
  7188. sarg.mode = SEEK_SET;
  7189. rb_protect(seek_before_access, (VALUE)&sarg, &state);
  7190. if (state) {
  7191. rb_io_close(arg.io);
  7192. rb_jump_tag(state);
  7193. }
  7194. if (arg.argc == 2) arg.argc = 1;
  7195. }
  7196. return rb_ensure(io_s_read, (VALUE)&arg, rb_io_close, arg.io);
  7197. }
  7198. /*
  7199. * call-seq:
  7200. * IO.binread(name, [length [, offset]] ) -> string
  7201. *
  7202. * Opens the file, optionally seeks to the given <i>offset</i>, then returns
  7203. * <i>length</i> bytes (defaulting to the rest of the file).
  7204. * <code>binread</code> ensures the file is closed before returning.
  7205. * The open mode would be "rb:ASCII-8BIT".
  7206. *
  7207. * IO.binread("testfile") #=> "This is line one\nThis is line two\nThis is line three\nAnd so on...\n"
  7208. * IO.binread("testfile", 20) #=> "This is line one\nThi"
  7209. * IO.binread("testfile", 20, 10) #=> "ne one\nThis is line "
  7210. */
  7211. static VALUE
  7212. rb_io_s_binread(int argc, VALUE *argv, VALUE io)
  7213. {
  7214. VALUE offset;
  7215. struct foreach_arg arg;
  7216. rb_scan_args(argc, argv, "12", NULL, NULL, &offset);
  7217. FilePathValue(argv[0]);
  7218. arg.io = rb_io_open(argv[0], rb_str_new_cstr("rb:ASCII-8BIT"), Qnil, Qnil);
  7219. if (NIL_P(arg.io)) return Qnil;
  7220. arg.argv = argv+1;
  7221. arg.argc = (argc > 1) ? 1 : 0;
  7222. if (!NIL_P(offset)) {
  7223. rb_io_seek(arg.io, offset, SEEK_SET);
  7224. }
  7225. return rb_ensure(io_s_read, (VALUE)&arg, rb_io_close, arg.io);
  7226. }
  7227. struct copy_stream_struct {
  7228. VALUE src;
  7229. VALUE dst;
  7230. off_t copy_length; /* (off_t)-1 if not specified */
  7231. off_t src_offset; /* (off_t)-1 if not specified */
  7232. int src_fd;
  7233. int dst_fd;
  7234. int close_src;
  7235. int close_dst;
  7236. off_t total;
  7237. const char *syserr;
  7238. int error_no;
  7239. const char *notimp;
  7240. rb_fdset_t fds;
  7241. VALUE th;
  7242. };
  7243. static int
  7244. maygvl_copy_stream_wait_read(struct copy_stream_struct *stp)
  7245. {
  7246. int ret;
  7247. rb_fd_zero(&stp->fds);
  7248. rb_fd_set(stp->src_fd, &stp->fds);
  7249. ret = rb_fd_select(rb_fd_max(&stp->fds), &stp->fds, NULL, NULL, NULL);
  7250. if (ret == -1) {
  7251. stp->syserr = "select";
  7252. stp->error_no = errno;
  7253. return -1;
  7254. }
  7255. return 0;
  7256. }
  7257. static int
  7258. nogvl_copy_stream_wait_write(struct copy_stream_struct *stp)
  7259. {
  7260. int ret;
  7261. rb_fd_zero(&stp->fds);
  7262. rb_fd_set(stp->dst_fd, &stp->fds);
  7263. ret = rb_fd_select(rb_fd_max(&stp->fds), NULL, &stp->fds, NULL, NULL);
  7264. if (ret == -1) {
  7265. stp->syserr = "select";
  7266. stp->error_no = errno;
  7267. return -1;
  7268. }
  7269. return 0;
  7270. }
  7271. #ifdef HAVE_SENDFILE
  7272. #ifdef __linux__
  7273. #define USE_SENDFILE
  7274. #ifdef HAVE_SYS_SENDFILE_H
  7275. #include <sys/sendfile.h>
  7276. #endif
  7277. static ssize_t
  7278. simple_sendfile(int out_fd, int in_fd, off_t *offset, off_t count)
  7279. {
  7280. #if SIZEOF_OFF_T > SIZEOF_SIZE_T
  7281. /* we are limited by the 32-bit ssize_t return value on 32-bit */
  7282. if (count > (off_t)SSIZE_MAX)
  7283. count = SSIZE_MAX;
  7284. #endif
  7285. return sendfile(out_fd, in_fd, offset, (size_t)count);
  7286. }
  7287. #endif
  7288. #endif
  7289. #ifdef USE_SENDFILE
  7290. static int
  7291. nogvl_copy_stream_sendfile(struct copy_stream_struct *stp)
  7292. {
  7293. struct stat src_stat, dst_stat;
  7294. ssize_t ss;
  7295. int ret;
  7296. off_t copy_length;
  7297. off_t src_offset;
  7298. int use_pread;
  7299. ret = fstat(stp->src_fd, &src_stat);
  7300. if (ret == -1) {
  7301. stp->syserr = "fstat";
  7302. stp->error_no = errno;
  7303. return -1;
  7304. }
  7305. if (!S_ISREG(src_stat.st_mode))
  7306. return 0;
  7307. ret = fstat(stp->dst_fd, &dst_stat);
  7308. if (ret == -1) {
  7309. stp->syserr = "fstat";
  7310. stp->error_no = errno;
  7311. return -1;
  7312. }
  7313. if ((dst_stat.st_mode & S_IFMT) != S_IFSOCK)
  7314. return 0;
  7315. src_offset = stp->src_offset;
  7316. use_pread = src_offset != (off_t)-1;
  7317. copy_length = stp->copy_length;
  7318. if (copy_length == (off_t)-1) {
  7319. if (use_pread)
  7320. copy_length = src_stat.st_size - src_offset;
  7321. else {
  7322. off_t cur;
  7323. errno = 0;
  7324. cur = lseek(stp->src_fd, 0, SEEK_CUR);
  7325. if (cur == (off_t)-1 && errno) {
  7326. stp->syserr = "lseek";
  7327. stp->error_no = errno;
  7328. return -1;
  7329. }
  7330. copy_length = src_stat.st_size - cur;
  7331. }
  7332. }
  7333. retry_sendfile:
  7334. if (use_pread) {
  7335. ss = simple_sendfile(stp->dst_fd, stp->src_fd, &src_offset, copy_length);
  7336. }
  7337. else {
  7338. ss = simple_sendfile(stp->dst_fd, stp->src_fd, NULL, copy_length);
  7339. }
  7340. if (0 < ss) {
  7341. stp->total += ss;
  7342. copy_length -= ss;
  7343. if (0 < copy_length) {
  7344. goto retry_sendfile;
  7345. }
  7346. }
  7347. if (ss == -1) {
  7348. switch (errno) {
  7349. case EINVAL:
  7350. #ifdef ENOSYS
  7351. case ENOSYS:
  7352. #endif
  7353. return 0;
  7354. case EAGAIN:
  7355. #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
  7356. case EWOULDBLOCK:
  7357. #endif
  7358. if (nogvl_copy_stream_wait_write(stp) == -1)
  7359. return -1;
  7360. if (rb_thread_interrupted(stp->th))
  7361. return -1;
  7362. goto retry_sendfile;
  7363. }
  7364. stp->syserr = "sendfile";
  7365. stp->error_no = errno;
  7366. return -1;
  7367. }
  7368. return 1;
  7369. }
  7370. #endif
  7371. static ssize_t
  7372. maygvl_copy_stream_read(struct copy_stream_struct *stp, char *buf, size_t len, off_t offset)
  7373. {
  7374. ssize_t ss;
  7375. retry_read:
  7376. if (offset == (off_t)-1)
  7377. ss = read(stp->src_fd, buf, len);
  7378. else {
  7379. #ifdef HAVE_PREAD
  7380. ss = pread(stp->src_fd, buf, len, offset);
  7381. #else
  7382. stp->notimp = "pread";
  7383. return -1;
  7384. #endif
  7385. }
  7386. if (ss == 0) {
  7387. return 0;
  7388. }
  7389. if (ss == -1) {
  7390. switch (errno) {
  7391. case EAGAIN:
  7392. #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
  7393. case EWOULDBLOCK:
  7394. #endif
  7395. if (maygvl_copy_stream_wait_read(stp) == -1)
  7396. return -1;
  7397. goto retry_read;
  7398. #ifdef ENOSYS
  7399. case ENOSYS:
  7400. #endif
  7401. stp->notimp = "pread";
  7402. return -1;
  7403. }
  7404. stp->syserr = offset == (off_t)-1 ? "read" : "pread";
  7405. stp->error_no = errno;
  7406. return -1;
  7407. }
  7408. return ss;
  7409. }
  7410. static int
  7411. nogvl_copy_stream_write(struct copy_stream_struct *stp, char *buf, size_t len)
  7412. {
  7413. ssize_t ss;
  7414. int off = 0;
  7415. while (len) {
  7416. ss = write(stp->dst_fd, buf+off, len);
  7417. if (ss == -1) {
  7418. if (errno == EAGAIN || errno == EWOULDBLOCK) {
  7419. if (nogvl_copy_stream_wait_write(stp) == -1)
  7420. return -1;
  7421. continue;
  7422. }
  7423. stp->syserr = "write";
  7424. stp->error_no = errno;
  7425. return -1;
  7426. }
  7427. off += (int)ss;
  7428. len -= (int)ss;
  7429. stp->total += ss;
  7430. }
  7431. return 0;
  7432. }
  7433. static void
  7434. nogvl_copy_stream_read_write(struct copy_stream_struct *stp)
  7435. {
  7436. char buf[1024*16];
  7437. size_t len;
  7438. ssize_t ss;
  7439. int ret;
  7440. off_t copy_length;
  7441. int use_eof;
  7442. off_t src_offset;
  7443. int use_pread;
  7444. copy_length = stp->copy_length;
  7445. use_eof = copy_length == (off_t)-1;
  7446. src_offset = stp->src_offset;
  7447. use_pread = src_offset != (off_t)-1;
  7448. if (use_pread && stp->close_src) {
  7449. off_t r;
  7450. errno = 0;
  7451. r = lseek(stp->src_fd, src_offset, SEEK_SET);
  7452. if (r == (off_t)-1 && errno) {
  7453. stp->syserr = "lseek";
  7454. stp->error_no = errno;
  7455. return;
  7456. }
  7457. src_offset = (off_t)-1;
  7458. use_pread = 0;
  7459. }
  7460. while (use_eof || 0 < copy_length) {
  7461. if (!use_eof && copy_length < (off_t)sizeof(buf)) {
  7462. len = (size_t)copy_length;
  7463. }
  7464. else {
  7465. len = sizeof(buf);
  7466. }
  7467. if (use_pread) {
  7468. ss = maygvl_copy_stream_read(stp, buf, len, src_offset);
  7469. if (0 < ss)
  7470. src_offset += ss;
  7471. }
  7472. else {
  7473. ss = maygvl_copy_stream_read(stp, buf, len, (off_t)-1);
  7474. }
  7475. if (ss <= 0) /* EOF or error */
  7476. return;
  7477. ret = nogvl_copy_stream_write(stp, buf, ss);
  7478. if (ret < 0)
  7479. return;
  7480. if (!use_eof)
  7481. copy_length -= ss;
  7482. if (rb_thread_interrupted(stp->th))
  7483. return;
  7484. }
  7485. }
  7486. static VALUE
  7487. nogvl_copy_stream_func(void *arg)
  7488. {
  7489. struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
  7490. #ifdef USE_SENDFILE
  7491. int ret;
  7492. #endif
  7493. #ifdef USE_SENDFILE
  7494. ret = nogvl_copy_stream_sendfile(stp);
  7495. if (ret != 0)
  7496. goto finish; /* error or success */
  7497. #endif
  7498. nogvl_copy_stream_read_write(stp);
  7499. #ifdef USE_SENDFILE
  7500. finish:
  7501. #endif
  7502. return Qnil;
  7503. }
  7504. static VALUE
  7505. copy_stream_fallback_body(VALUE arg)
  7506. {
  7507. struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
  7508. const int buflen = 16*1024;
  7509. VALUE n;
  7510. VALUE buf = rb_str_buf_new(buflen);
  7511. off_t rest = stp->copy_length;
  7512. off_t off = stp->src_offset;
  7513. ID read_method = id_readpartial;
  7514. if (stp->src_fd == -1) {
  7515. if (!rb_respond_to(stp->src, read_method)) {
  7516. read_method = id_read;
  7517. }
  7518. }
  7519. while (1) {
  7520. long numwrote;
  7521. long l;
  7522. if (stp->copy_length == (off_t)-1) {
  7523. l = buflen;
  7524. }
  7525. else {
  7526. if (rest == 0)
  7527. break;
  7528. l = buflen < rest ? buflen : (long)rest;
  7529. }
  7530. if (stp->src_fd == -1) {
  7531. rb_funcall(stp->src, read_method, 2, INT2FIX(l), buf);
  7532. }
  7533. else {
  7534. ssize_t ss;
  7535. rb_thread_wait_fd(stp->src_fd);
  7536. rb_str_resize(buf, buflen);
  7537. ss = maygvl_copy_stream_read(stp, RSTRING_PTR(buf), l, off);
  7538. if (ss == -1)
  7539. return Qnil;
  7540. if (ss == 0)
  7541. rb_eof_error();
  7542. rb_str_resize(buf, ss);
  7543. if (off != (off_t)-1)
  7544. off += ss;
  7545. }
  7546. n = rb_io_write(stp->dst, buf);
  7547. numwrote = NUM2LONG(n);
  7548. stp->total += numwrote;
  7549. rest -= numwrote;
  7550. if (read_method == id_read && RSTRING_LEN(buf) == 0) {
  7551. break;
  7552. }
  7553. }
  7554. return Qnil;
  7555. }
  7556. static VALUE
  7557. copy_stream_fallback(struct copy_stream_struct *stp)
  7558. {
  7559. if (stp->src_fd == -1 && stp->src_offset != (off_t)-1) {
  7560. rb_raise(rb_eArgError, "cannot specify src_offset for non-IO");
  7561. }
  7562. rb_rescue2(copy_stream_fallback_body, (VALUE)stp,
  7563. (VALUE (*) (ANYARGS))0, (VALUE)0,
  7564. rb_eEOFError, (VALUE)0);
  7565. return Qnil;
  7566. }
  7567. static VALUE
  7568. copy_stream_body(VALUE arg)
  7569. {
  7570. struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
  7571. VALUE src_io, dst_io;
  7572. rb_io_t *src_fptr = 0, *dst_fptr = 0;
  7573. int src_fd, dst_fd;
  7574. stp->th = rb_thread_current();
  7575. stp->total = 0;
  7576. if (stp->src == argf ||
  7577. !(TYPE(stp->src) == T_FILE ||
  7578. TYPE(stp->src) == T_STRING ||
  7579. rb_respond_to(stp->src, rb_intern("to_path")))) {
  7580. src_fd = -1;
  7581. }
  7582. else {
  7583. src_io = TYPE(stp->src) == T_FILE ? stp->src : Qnil;
  7584. if (NIL_P(src_io)) {
  7585. VALUE args[2];
  7586. int oflags = O_RDONLY;
  7587. #ifdef O_NOCTTY
  7588. oflags |= O_NOCTTY;
  7589. #endif
  7590. FilePathValue(stp->src);
  7591. args[0] = stp->src;
  7592. args[1] = INT2NUM(oflags);
  7593. src_io = rb_class_new_instance(2, args, rb_cFile);
  7594. stp->src = src_io;
  7595. stp->close_src = 1;
  7596. }
  7597. GetOpenFile(src_io, src_fptr);
  7598. rb_io_check_byte_readable(src_fptr);
  7599. src_fd = src_fptr->fd;
  7600. }
  7601. stp->src_fd = src_fd;
  7602. if (stp->dst == argf ||
  7603. !(TYPE(stp->dst) == T_FILE ||
  7604. TYPE(stp->dst) == T_STRING ||
  7605. rb_respond_to(stp->dst, rb_intern("to_path")))) {
  7606. dst_fd = -1;
  7607. }
  7608. else {
  7609. dst_io = TYPE(stp->dst) == T_FILE ? stp->dst : Qnil;
  7610. if (NIL_P(dst_io)) {
  7611. VALUE args[3];
  7612. int oflags = O_WRONLY|O_CREAT|O_TRUNC;
  7613. #ifdef O_NOCTTY
  7614. oflags |= O_NOCTTY;
  7615. #endif
  7616. FilePathValue(stp->dst);
  7617. args[0] = stp->dst;
  7618. args[1] = INT2NUM(oflags);
  7619. args[2] = INT2FIX(0600);
  7620. dst_io = rb_class_new_instance(3, args, rb_cFile);
  7621. stp->dst = dst_io;
  7622. stp->close_dst = 1;
  7623. }
  7624. else {
  7625. dst_io = GetWriteIO(dst_io);
  7626. stp->dst = dst_io;
  7627. }
  7628. GetOpenFile(dst_io, dst_fptr);
  7629. rb_io_check_writable(dst_fptr);
  7630. dst_fd = dst_fptr->fd;
  7631. }
  7632. stp->dst_fd = dst_fd;
  7633. if (stp->src_offset == (off_t)-1 && src_fptr && src_fptr->rbuf_len) {
  7634. size_t len = src_fptr->rbuf_len;
  7635. VALUE str;
  7636. if (stp->copy_length != (off_t)-1 && stp->copy_length < (off_t)len) {
  7637. len = (size_t)stp->copy_length;
  7638. }
  7639. str = rb_str_buf_new(len);
  7640. rb_str_resize(str,len);
  7641. read_buffered_data(RSTRING_PTR(str), len, src_fptr);
  7642. if (dst_fptr) { /* IO or filename */
  7643. if (io_binwrite(str, dst_fptr, 0) < 0)
  7644. rb_sys_fail(0);
  7645. }
  7646. else /* others such as StringIO */
  7647. rb_io_write(stp->dst, str);
  7648. stp->total += len;
  7649. if (stp->copy_length != (off_t)-1)
  7650. stp->copy_length -= len;
  7651. }
  7652. if (dst_fptr && io_fflush(dst_fptr) < 0) {
  7653. rb_raise(rb_eIOError, "flush failed");
  7654. }
  7655. if (stp->copy_length == 0)
  7656. return Qnil;
  7657. if (src_fd == -1 || dst_fd == -1) {
  7658. return copy_stream_fallback(stp);
  7659. }
  7660. rb_fd_init(&stp->fds);
  7661. rb_fd_set(src_fd, &stp->fds);
  7662. rb_fd_set(dst_fd, &stp->fds);
  7663. return rb_thread_blocking_region(nogvl_copy_stream_func, (void*)stp, RUBY_UBF_IO, 0);
  7664. }
  7665. static VALUE
  7666. copy_stream_finalize(VALUE arg)
  7667. {
  7668. struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
  7669. if (stp->close_src) {
  7670. rb_io_close_m(stp->src);
  7671. }
  7672. if (stp->close_dst) {
  7673. rb_io_close_m(stp->dst);
  7674. }
  7675. rb_fd_term(&stp->fds);
  7676. if (stp->syserr) {
  7677. errno = stp->error_no;
  7678. rb_sys_fail(stp->syserr);
  7679. }
  7680. if (stp->notimp) {
  7681. rb_raise(rb_eNotImpError, "%s() not implemented", stp->notimp);
  7682. }
  7683. return Qnil;
  7684. }
  7685. /*
  7686. * call-seq:
  7687. * IO.copy_stream(src, dst)
  7688. * IO.copy_stream(src, dst, copy_length)
  7689. * IO.copy_stream(src, dst, copy_length, src_offset)
  7690. *
  7691. * IO.copy_stream copies <i>src</i> to <i>dst</i>.
  7692. * <i>src</i> and <i>dst</i> is either a filename or an IO.
  7693. *
  7694. * This method returns the number of bytes copied.
  7695. *
  7696. * If optional arguments are not given,
  7697. * the start position of the copy is
  7698. * the beginning of the filename or
  7699. * the current file offset of the IO.
  7700. * The end position of the copy is the end of file.
  7701. *
  7702. * If <i>copy_length</i> is given,
  7703. * No more than <i>copy_length</i> bytes are copied.
  7704. *
  7705. * If <i>src_offset</i> is given,
  7706. * it specifies the start position of the copy.
  7707. *
  7708. * When <i>src_offset</i> is specified and
  7709. * <i>src</i> is an IO,
  7710. * IO.copy_stream doesn't move the current file offset.
  7711. *
  7712. */
  7713. static VALUE
  7714. rb_io_s_copy_stream(int argc, VALUE *argv, VALUE io)
  7715. {
  7716. VALUE src, dst, length, src_offset;
  7717. struct copy_stream_struct st;
  7718. MEMZERO(&st, struct copy_stream_struct, 1);
  7719. rb_scan_args(argc, argv, "22", &src, &dst, &length, &src_offset);
  7720. st.src = src;
  7721. st.dst = dst;
  7722. if (NIL_P(length))
  7723. st.copy_length = (off_t)-1;
  7724. else
  7725. st.copy_length = NUM2OFFT(length);
  7726. if (NIL_P(src_offset))
  7727. st.src_offset = (off_t)-1;
  7728. else
  7729. st.src_offset = NUM2OFFT(src_offset);
  7730. rb_ensure(copy_stream_body, (VALUE)&st, copy_stream_finalize, (VALUE)&st);
  7731. return OFFT2NUM(st.total);
  7732. }
  7733. /*
  7734. * call-seq:
  7735. * io.external_encoding -> encoding
  7736. *
  7737. * Returns the Encoding object that represents the encoding of the file.
  7738. * If io is write mode and no encoding is specified, returns <code>nil</code>.
  7739. */
  7740. static VALUE
  7741. rb_io_external_encoding(VALUE io)
  7742. {
  7743. rb_io_t *fptr;
  7744. GetOpenFile(io, fptr);
  7745. if (fptr->encs.enc2) {
  7746. return rb_enc_from_encoding(fptr->encs.enc2);
  7747. }
  7748. if (fptr->mode & FMODE_WRITABLE) {
  7749. if (fptr->encs.enc)
  7750. return rb_enc_from_encoding(fptr->encs.enc);
  7751. return Qnil;
  7752. }
  7753. return rb_enc_from_encoding(io_read_encoding(fptr));
  7754. }
  7755. /*
  7756. * call-seq:
  7757. * io.internal_encoding -> encoding
  7758. *
  7759. * Returns the Encoding of the internal string if conversion is
  7760. * specified. Otherwise returns nil.
  7761. */
  7762. static VALUE
  7763. rb_io_internal_encoding(VALUE io)
  7764. {
  7765. rb_io_t *fptr;
  7766. GetOpenFile(io, fptr);
  7767. if (!fptr->encs.enc2) return Qnil;
  7768. return rb_enc_from_encoding(io_read_encoding(fptr));
  7769. }
  7770. /*
  7771. * call-seq:
  7772. * io.set_encoding(ext_enc) -> io
  7773. * io.set_encoding("ext_enc:int_enc") -> io
  7774. * io.set_encoding(ext_enc, int_enc) -> io
  7775. * io.set_encoding("ext_enc:int_enc", opt) -> io
  7776. * io.set_encoding(ext_enc, int_enc, opt) -> io
  7777. *
  7778. * If single argument is specified, read string from io is tagged
  7779. * with the encoding specified. If encoding is a colon separated two
  7780. * encoding names "A:B", the read string is converted from encoding A
  7781. * (external encoding) to encoding B (internal encoding), then tagged
  7782. * with B. If two arguments are specified, those must be encoding
  7783. * objects or encoding names, and the first one is the external encoding, and the
  7784. * second one is the internal encoding.
  7785. * If the external encoding and the internal encoding is specified,
  7786. * optional hash argument specify the conversion option.
  7787. */
  7788. static VALUE
  7789. rb_io_set_encoding(int argc, VALUE *argv, VALUE io)
  7790. {
  7791. rb_io_t *fptr;
  7792. VALUE v1, v2, opt;
  7793. opt = pop_last_hash(&argc, argv);
  7794. rb_scan_args(argc, argv, "11", &v1, &v2);
  7795. GetOpenFile(io, fptr);
  7796. io_encoding_set(fptr, v1, v2, opt);
  7797. return io;
  7798. }
  7799. void
  7800. rb_stdio_set_default_encoding(void)
  7801. {
  7802. extern VALUE rb_stdin, rb_stdout, rb_stderr;
  7803. VALUE val = Qnil;
  7804. rb_io_set_encoding(1, &val, rb_stdin);
  7805. rb_io_set_encoding(1, &val, rb_stdout);
  7806. rb_io_set_encoding(1, &val, rb_stderr);
  7807. }
  7808. /*
  7809. * call-seq:
  7810. * ARGF.external_encoding -> encoding
  7811. *
  7812. * Returns the external encoding for files read from +ARGF+ as an +Encoding+
  7813. * object. The external encoding is the encoding of the text as stored in a
  7814. * file. Contrast with +ARGF.internal_encoding+, which is the encoding used
  7815. * to represent this text within Ruby.
  7816. *
  7817. * To set the external encoding use +ARGF.set_encoding+.
  7818. *
  7819. * For example:
  7820. *
  7821. * ARGF.external_encoding #=> #<Encoding:UTF-8>
  7822. *
  7823. */
  7824. static VALUE
  7825. argf_external_encoding(VALUE argf)
  7826. {
  7827. if (!RTEST(ARGF.current_file)) {
  7828. return rb_enc_from_encoding(rb_default_external_encoding());
  7829. }
  7830. return rb_io_external_encoding(rb_io_check_io(ARGF.current_file));
  7831. }
  7832. /*
  7833. * call-seq:
  7834. * ARGF.internal_encoding -> encoding
  7835. *
  7836. * Returns the internal encoding for strings read from +ARGF+ as an
  7837. * +Encoding+ object.
  7838. *
  7839. * If +ARGF.set_encoding+ has been called with two encoding names, the second
  7840. * is returned. Otherwise, if +Encoding.default_external+ has been set, that
  7841. * value is returned. Failing that, if a default external encoding was
  7842. * specified on the command-line, that value is used. If the encoding is
  7843. * unknown, nil is returned.
  7844. */
  7845. static VALUE
  7846. argf_internal_encoding(VALUE argf)
  7847. {
  7848. if (!RTEST(ARGF.current_file)) {
  7849. return rb_enc_from_encoding(rb_default_external_encoding());
  7850. }
  7851. return rb_io_internal_encoding(rb_io_check_io(ARGF.current_file));
  7852. }
  7853. /*
  7854. * call-seq:
  7855. * ARGF.set_encoding(ext_enc) -> ARGF
  7856. * ARGF.set_encoding("ext_enc:int_enc") -> ARGF
  7857. * ARGF.set_encoding(ext_enc, int_enc) -> ARGF
  7858. * ARGF.set_encoding("ext_enc:int_enc", opt) -> ARGF
  7859. * ARGF.set_encoding(ext_enc, int_enc, opt) -> ARGF
  7860. *
  7861. * If single argument is specified, strings read from ARGF are tagged with
  7862. * the encoding specified.
  7863. *
  7864. * If two encoding names separated by a colon are given, e.g. "ascii:utf-8",
  7865. * the read string is converted from the first encoding (external encoding)
  7866. * to the second encoding (internal encoding), then tagged with the second
  7867. * encoding.
  7868. *
  7869. * If two arguments are specified, they must be encoding objects or encoding
  7870. * names. Again, the first specifies the external encoding; the second
  7871. * specifies the internal encoding.
  7872. *
  7873. * If the external encoding and the internal encoding are specified, the
  7874. * optional +Hash+ argument can be used to adjust the conversion process. The
  7875. * structure of this hash is explained in the +String#encode+ documentation.
  7876. *
  7877. * For example:
  7878. *
  7879. * ARGF.set_encoding('ascii') # Tag the input as US-ASCII text
  7880. * ARGF.set_encoding(Encoding::UTF_8) # Tag the input as UTF-8 text
  7881. * ARGF.set_encoding('utf-8','ascii') # Transcode the input from US-ASCII
  7882. * # to UTF-8.
  7883. */
  7884. static VALUE
  7885. argf_set_encoding(int argc, VALUE *argv, VALUE argf)
  7886. {
  7887. rb_io_t *fptr;
  7888. if (!next_argv()) {
  7889. rb_raise(rb_eArgError, "no stream to set encoding");
  7890. }
  7891. rb_io_set_encoding(argc, argv, ARGF.current_file);
  7892. GetOpenFile(ARGF.current_file, fptr);
  7893. ARGF.encs = fptr->encs;
  7894. return argf;
  7895. }
  7896. /*
  7897. * call-seq:
  7898. * ARGF.tell -> Integer
  7899. * ARGF.pos -> Integer
  7900. *
  7901. * Returns the current offset (in bytes) of the current file in +ARGF+.
  7902. *
  7903. * ARGF.pos #=> 0
  7904. * ARGF.gets #=> "This is line one\n"
  7905. * ARGF.pos #=> 17
  7906. *
  7907. */
  7908. static VALUE
  7909. argf_tell(VALUE argf)
  7910. {
  7911. if (!next_argv()) {
  7912. rb_raise(rb_eArgError, "no stream to tell");
  7913. }
  7914. ARGF_FORWARD(0, 0);
  7915. return rb_io_tell(ARGF.current_file);
  7916. }
  7917. /*
  7918. * call-seq:
  7919. * ARGF.seek(amount, whence=IO::SEEK_SET) -> 0
  7920. *
  7921. * Seeks to offset _amount_ (an +Integer+) in the +ARGF+ stream according to
  7922. * the value of _whence_. See +IO#seek+ for further details.
  7923. */
  7924. static VALUE
  7925. argf_seek_m(int argc, VALUE *argv, VALUE argf)
  7926. {
  7927. if (!next_argv()) {
  7928. rb_raise(rb_eArgError, "no stream to seek");
  7929. }
  7930. ARGF_FORWARD(argc, argv);
  7931. return rb_io_seek_m(argc, argv, ARGF.current_file);
  7932. }
  7933. /*
  7934. * call-seq:
  7935. * ARGF.pos = position -> Integer
  7936. *
  7937. * Seeks to the position given by _position_ (in bytes) in +ARGF+.
  7938. *
  7939. * For example:
  7940. *
  7941. * ARGF.pos = 17
  7942. * ARGF.gets #=> "This is line two\n"
  7943. */
  7944. static VALUE
  7945. argf_set_pos(VALUE argf, VALUE offset)
  7946. {
  7947. if (!next_argv()) {
  7948. rb_raise(rb_eArgError, "no stream to set position");
  7949. }
  7950. ARGF_FORWARD(1, &offset);
  7951. return rb_io_set_pos(ARGF.current_file, offset);
  7952. }
  7953. /*
  7954. * call-seq:
  7955. * ARGF.rewind -> 0
  7956. *
  7957. * Positions the current file to the beginning of input, resetting
  7958. * +ARGF.lineno+ to zero.
  7959. *
  7960. * ARGF.readline #=> "This is line one\n"
  7961. * ARGF.rewind #=> 0
  7962. * ARGF.lineno #=> 0
  7963. * ARGF.readline #=> "This is line one\n"
  7964. */
  7965. static VALUE
  7966. argf_rewind(VALUE argf)
  7967. {
  7968. if (!next_argv()) {
  7969. rb_raise(rb_eArgError, "no stream to rewind");
  7970. }
  7971. ARGF_FORWARD(0, 0);
  7972. return rb_io_rewind(ARGF.current_file);
  7973. }
  7974. /*
  7975. * call-seq:
  7976. * ARGF.fileno -> fixnum
  7977. * ARGF.to_i -> fixnum
  7978. *
  7979. * Returns an integer representing the numeric file descriptor for
  7980. * the current file. Raises an +ArgumentError+ if there isn't a current file.
  7981. *
  7982. * ARGF.fileno #=> 3
  7983. */
  7984. static VALUE
  7985. argf_fileno(VALUE argf)
  7986. {
  7987. if (!next_argv()) {
  7988. rb_raise(rb_eArgError, "no stream");
  7989. }
  7990. ARGF_FORWARD(0, 0);
  7991. return rb_io_fileno(ARGF.current_file);
  7992. }
  7993. /*
  7994. * call-seq:
  7995. * ARGF.to_io -> IO
  7996. *
  7997. * Returns an +IO+ object representing the current file. This will be a
  7998. * +File+ object unless the current file is a stream such as STDIN.
  7999. *
  8000. * For example:
  8001. *
  8002. * ARGF.to_io #=> #<File:glark.txt>
  8003. * ARGF.to_io #=> #<IO:<STDIN>>
  8004. */
  8005. static VALUE
  8006. argf_to_io(VALUE argf)
  8007. {
  8008. next_argv();
  8009. ARGF_FORWARD(0, 0);
  8010. return ARGF.current_file;
  8011. }
  8012. /*
  8013. * call-seq:
  8014. * ARGF.eof? -> true or false
  8015. * ARGF.eof -> true or false
  8016. *
  8017. * Returns true if the current file in +ARGF+ is at end of file, i.e. it has
  8018. * no data to read. The stream must be opened for reading or an +IOError+
  8019. * will be raised.
  8020. *
  8021. * $ echo "eof" | ruby argf.rb
  8022. *
  8023. * ARGF.eof? #=> false
  8024. * 3.times { ARGF.readchar }
  8025. * ARGF.eof? #=> false
  8026. * ARGF.readchar #=> "\n"
  8027. * ARGF.eof? #=> true
  8028. */
  8029. static VALUE
  8030. argf_eof(VALUE argf)
  8031. {
  8032. next_argv();
  8033. if (RTEST(ARGF.current_file)) {
  8034. if (ARGF.init_p == 0) return Qtrue;
  8035. next_argv();
  8036. ARGF_FORWARD(0, 0);
  8037. if (rb_io_eof(ARGF.current_file)) {
  8038. return Qtrue;
  8039. }
  8040. }
  8041. return Qfalse;
  8042. }
  8043. /*
  8044. * call-seq:
  8045. * ARGF.read([length [, buffer]]) -> string, buffer, or nil
  8046. *
  8047. * Reads _length_ bytes from ARGF. The files named on the command line
  8048. * are concatenated and treated as a single file by this method, so when
  8049. * called without arguments the contents of this pseudo file are returned in
  8050. * their entirety.
  8051. *
  8052. * _length_ must be a non-negative integer or nil. If it is a positive
  8053. * integer, +read+ tries to read at most _length_ bytes. It returns nil
  8054. * if an EOF was encountered before anything could be read. Fewer than
  8055. * _length_ bytes may be returned if an EOF is encountered during the read.
  8056. *
  8057. * If _length_ is omitted or is _nil_, it reads until EOF. A String is
  8058. * returned even if EOF is encountered before any data is read.
  8059. *
  8060. * If _length_ is zero, it returns _""_.
  8061. *
  8062. * If the optional _buffer_ argument is present, it must reference a String,
  8063. * which will receive the data.
  8064. *
  8065. * For example:
  8066. *
  8067. * $ echo "small" > small.txt
  8068. * $ echo "large" > large.txt
  8069. * $ ./glark.rb small.txt large.txt
  8070. *
  8071. * ARGF.read #=> "small\nlarge"
  8072. * ARGF.read(200) #=> "small\nlarge"
  8073. * ARGF.read(2) #=> "sm"
  8074. * ARGF.read(0) #=> ""
  8075. *
  8076. * Note that this method behaves like fread() function in C. If you need the
  8077. * behavior like read(2) system call, consider +ARGF.readpartial+.
  8078. */
  8079. static VALUE
  8080. argf_read(int argc, VALUE *argv, VALUE argf)
  8081. {
  8082. VALUE tmp, str, length;
  8083. long len = 0;
  8084. rb_scan_args(argc, argv, "02", &length, &str);
  8085. if (!NIL_P(length)) {
  8086. len = NUM2LONG(argv[0]);
  8087. }
  8088. if (!NIL_P(str)) {
  8089. StringValue(str);
  8090. rb_str_resize(str,0);
  8091. argv[1] = Qnil;
  8092. }
  8093. retry:
  8094. if (!next_argv()) {
  8095. return str;
  8096. }
  8097. if (ARGF_GENERIC_INPUT_P()) {
  8098. tmp = argf_forward(argc, argv, argf);
  8099. }
  8100. else {
  8101. tmp = io_read(argc, argv, ARGF.current_file);
  8102. }
  8103. if (NIL_P(str)) str = tmp;
  8104. else if (!NIL_P(tmp)) rb_str_append(str, tmp);
  8105. if (NIL_P(tmp) || NIL_P(length)) {
  8106. if (ARGF.next_p != -1) {
  8107. argf_close(ARGF.current_file);
  8108. ARGF.next_p = 1;
  8109. goto retry;
  8110. }
  8111. }
  8112. else if (argc >= 1) {
  8113. if (RSTRING_LEN(str) < len) {
  8114. len -= RSTRING_LEN(str);
  8115. argv[0] = INT2NUM(len);
  8116. goto retry;
  8117. }
  8118. }
  8119. return str;
  8120. }
  8121. struct argf_call_arg {
  8122. int argc;
  8123. VALUE *argv;
  8124. VALUE argf;
  8125. };
  8126. static VALUE
  8127. argf_forward_call(VALUE arg)
  8128. {
  8129. struct argf_call_arg *p = (struct argf_call_arg *)arg;
  8130. argf_forward(p->argc, p->argv, p->argf);
  8131. return Qnil;
  8132. }
  8133. /*
  8134. * call-seq:
  8135. * ARGF.readpartial(maxlen) -> string
  8136. * ARGF.readpartial(maxlen, outbuf) -> outbuf
  8137. *
  8138. * Reads at most _maxlen_ bytes from the ARGF stream. It blocks only if
  8139. * +ARGF+ has no data immediately available. If the optional _outbuf_
  8140. * argument is present, it must reference a String, which will receive the
  8141. * data. It raises <code>EOFError</code> on end of file.
  8142. *
  8143. * +readpartial+ is designed for streams such as pipes, sockets, and ttys. It
  8144. * blocks only when no data is immediately available. This means that it
  8145. * blocks only when following all conditions hold:
  8146. *
  8147. * * The byte buffer in the +IO+ object is empty.
  8148. * * The content of the stream is empty.
  8149. * * The stream has not reached EOF.
  8150. *
  8151. * When +readpartial+ blocks, it waits for data or EOF. If some data is read,
  8152. * +readpartial+ returns with the data. If EOF is reached, readpartial raises
  8153. * an +EOFError+.
  8154. *
  8155. * When +readpartial+ doesn't block, it returns or raises immediately. If
  8156. * the byte buffer is not empty, it returns the data in the buffer. Otherwise, if
  8157. * the stream has some content, it returns the data in the stream. If the
  8158. * stream reaches EOF an +EOFError+ is raised.
  8159. */
  8160. static VALUE
  8161. argf_readpartial(int argc, VALUE *argv, VALUE argf)
  8162. {
  8163. VALUE tmp, str, length;
  8164. rb_scan_args(argc, argv, "11", &length, &str);
  8165. if (!NIL_P(str)) {
  8166. StringValue(str);
  8167. argv[1] = str;
  8168. }
  8169. if (!next_argv()) {
  8170. rb_str_resize(str, 0);
  8171. rb_eof_error();
  8172. }
  8173. if (ARGF_GENERIC_INPUT_P()) {
  8174. struct argf_call_arg arg;
  8175. arg.argc = argc;
  8176. arg.argv = argv;
  8177. arg.argf = argf;
  8178. tmp = rb_rescue2(argf_forward_call, (VALUE)&arg,
  8179. RUBY_METHOD_FUNC(0), Qnil, rb_eEOFError, (VALUE)0);
  8180. }
  8181. else {
  8182. tmp = io_getpartial(argc, argv, ARGF.current_file, 0);
  8183. }
  8184. if (NIL_P(tmp)) {
  8185. if (ARGF.next_p == -1) {
  8186. rb_eof_error();
  8187. }
  8188. argf_close(ARGF.current_file);
  8189. ARGF.next_p = 1;
  8190. if (RARRAY_LEN(ARGF.argv) == 0)
  8191. rb_eof_error();
  8192. if (NIL_P(str))
  8193. str = rb_str_new(NULL, 0);
  8194. return str;
  8195. }
  8196. return tmp;
  8197. }
  8198. /*
  8199. * call-seq:
  8200. * ARGF.getc -> String or nil
  8201. *
  8202. * Reads the next character from +ARGF+ and returns it as a +String+. Returns
  8203. * +nil+ at the end of the stream.
  8204. *
  8205. * +ARGF+ treats the files named on the command line as a single file created
  8206. * by concatenating their contents. After returning the last character of the
  8207. * first file, it returns the first character of the second file, and so on.
  8208. *
  8209. * For example:
  8210. *
  8211. * $ echo "foo" > file
  8212. * $ ruby argf.rb file
  8213. *
  8214. * ARGF.getc #=> "f"
  8215. * ARGF.getc #=> "o"
  8216. * ARGF.getc #=> "o"
  8217. * ARGF.getc #=> "\n"
  8218. * ARGF.getc #=> nil
  8219. * ARGF.getc #=> nil
  8220. */
  8221. static VALUE
  8222. argf_getc(VALUE argf)
  8223. {
  8224. VALUE ch;
  8225. retry:
  8226. if (!next_argv()) return Qnil;
  8227. if (ARGF_GENERIC_INPUT_P()) {
  8228. ch = rb_funcall3(ARGF.current_file, rb_intern("getc"), 0, 0);
  8229. }
  8230. else {
  8231. ch = rb_io_getc(ARGF.current_file);
  8232. }
  8233. if (NIL_P(ch) && ARGF.next_p != -1) {
  8234. argf_close(ARGF.current_file);
  8235. ARGF.next_p = 1;
  8236. goto retry;
  8237. }
  8238. return ch;
  8239. }
  8240. /*
  8241. * call-seq:
  8242. * ARGF.getbyte -> Fixnum or nil
  8243. *
  8244. * Gets the next 8-bit byte (0..255) from +ARGF+. Returns +nil+ if called at
  8245. * the end of the stream.
  8246. *
  8247. * For example:
  8248. *
  8249. * $ echo "foo" > file
  8250. * $ ruby argf.rb file
  8251. *
  8252. * ARGF.getbyte #=> 102
  8253. * ARGF.getbyte #=> 111
  8254. * ARGF.getbyte #=> 111
  8255. * ARGF.getbyte #=> 10
  8256. * ARGF.getbyte #=> nil
  8257. */
  8258. static VALUE
  8259. argf_getbyte(VALUE argf)
  8260. {
  8261. VALUE ch;
  8262. retry:
  8263. if (!next_argv()) return Qnil;
  8264. if (TYPE(ARGF.current_file) != T_FILE) {
  8265. ch = rb_funcall3(ARGF.current_file, rb_intern("getbyte"), 0, 0);
  8266. }
  8267. else {
  8268. ch = rb_io_getbyte(ARGF.current_file);
  8269. }
  8270. if (NIL_P(ch) && ARGF.next_p != -1) {
  8271. argf_close(ARGF.current_file);
  8272. ARGF.next_p = 1;
  8273. goto retry;
  8274. }
  8275. return ch;
  8276. }
  8277. /*
  8278. * call-seq:
  8279. * ARGF.readchar -> String or nil
  8280. *
  8281. * Reads the next character from +ARGF+ and returns it as a +String+. Raises
  8282. * an +EOFError+ after the last character of the last file has been read.
  8283. *
  8284. * For example:
  8285. *
  8286. * $ echo "foo" > file
  8287. * $ ruby argf.rb file
  8288. *
  8289. * ARGF.readchar #=> "f"
  8290. * ARGF.readchar #=> "o"
  8291. * ARGF.readchar #=> "o"
  8292. * ARGF.readchar #=> "\n"
  8293. * ARGF.readchar #=> end of file reached (EOFError)
  8294. */
  8295. static VALUE
  8296. argf_readchar(VALUE argf)
  8297. {
  8298. VALUE ch;
  8299. retry:
  8300. if (!next_argv()) rb_eof_error();
  8301. if (TYPE(ARGF.current_file) != T_FILE) {
  8302. ch = rb_funcall3(ARGF.current_file, rb_intern("getc"), 0, 0);
  8303. }
  8304. else {
  8305. ch = rb_io_getc(ARGF.current_file);
  8306. }
  8307. if (NIL_P(ch) && ARGF.next_p != -1) {
  8308. argf_close(ARGF.current_file);
  8309. ARGF.next_p = 1;
  8310. goto retry;
  8311. }
  8312. return ch;
  8313. }
  8314. /*
  8315. * call-seq:
  8316. * ARGF.readbyte -> Fixnum
  8317. *
  8318. * Reads the next 8-bit byte from ARGF and returns it as a +Fixnum+. Raises
  8319. * an +EOFError+ after the last byte of the last file has been read.
  8320. *
  8321. * For example:
  8322. *
  8323. * $ echo "foo" > file
  8324. * $ ruby argf.rb file
  8325. *
  8326. * ARGF.readbyte #=> 102
  8327. * ARGF.readbyte #=> 111
  8328. * ARGF.readbyte #=> 111
  8329. * ARGF.readbyte #=> 10
  8330. * ARGF.readbyte #=> end of file reached (EOFError)
  8331. */
  8332. static VALUE
  8333. argf_readbyte(VALUE argf)
  8334. {
  8335. VALUE c;
  8336. NEXT_ARGF_FORWARD(0, 0);
  8337. c = argf_getbyte(argf);
  8338. if (NIL_P(c)) {
  8339. rb_eof_error();
  8340. }
  8341. return c;
  8342. }
  8343. /*
  8344. * call-seq:
  8345. * ARGF.each(sep=$/) {|line| block } -> ARGF
  8346. * ARGF.each(sep=$/,limit) {|line| block } -> ARGF
  8347. * ARGF.each(...) -> an_enumerator
  8348. *
  8349. * ARGF.each_line(sep=$/) {|line| block } -> ARGF
  8350. * ARGF.each_line(sep=$/,limit) {|line| block } -> ARGF
  8351. * ARGF.each_line(...) -> an_enumerator
  8352. *
  8353. * ARGF.lines(sep=$/) {|line| block } -> ARGF
  8354. * ARGF.lines(sep=$/,limit) {|line| block } -> ARGF
  8355. * ARGF.lines(...) -> an_enumerator
  8356. *
  8357. * Returns an enumerator which iterates over each line (separated by _sep_,
  8358. * which defaults to your platform's newline character) of each file in
  8359. * +ARGV+. If a block is supplied, each line in turn will be yielded to the
  8360. * block, otherwise an enumerator is returned.
  8361. * The optional _limit_ argument is a +Fixnum+ specifying the maximum
  8362. * length of each line; longer lines will be split according to this limit.
  8363. *
  8364. * This method allows you to treat the files supplied on the command line as
  8365. * a single file consisting of the concatenation of each named file. After
  8366. * the last line of the first file has been returned, the first line of the
  8367. * second file is returned. The +ARGF.filename+ and +ARGF.lineno+ methods can
  8368. * be used to determine the filename and line number, respectively, of the
  8369. * current line.
  8370. *
  8371. * For example, the following code prints out each line of each named file
  8372. * prefixed with its line number, displaying the filename once per file:
  8373. *
  8374. * ARGF.lines do |line|
  8375. * puts ARGF.filename if ARGF.lineno == 1
  8376. * puts "#{ARGF.lineno}: #{line}"
  8377. * end
  8378. */
  8379. static VALUE
  8380. argf_each_line(int argc, VALUE *argv, VALUE argf)
  8381. {
  8382. RETURN_ENUMERATOR(argf, argc, argv);
  8383. for (;;) {
  8384. if (!next_argv()) return argf;
  8385. rb_block_call(ARGF.current_file, rb_intern("each_line"), argc, argv, 0, 0);
  8386. ARGF.next_p = 1;
  8387. }
  8388. }
  8389. /*
  8390. * call-seq:
  8391. * ARGF.bytes {|byte| block } -> ARGF
  8392. * ARGF.bytes -> an_enumerator
  8393. *
  8394. * ARGF.each_byte {|byte| block } -> ARGF
  8395. * ARGF.each_byte -> an_enumerator
  8396. *
  8397. * Iterates over each byte of each file in +ARGV+.
  8398. * A byte is returned as a +Fixnum+ in the range 0..255.
  8399. *
  8400. * This method allows you to treat the files supplied on the command line as
  8401. * a single file consisting of the concatenation of each named file. After
  8402. * the last byte of the first file has been returned, the first byte of the
  8403. * second file is returned. The +ARGF.filename+ method can be used to
  8404. * determine the filename of the current byte.
  8405. *
  8406. * If no block is given, an enumerator is returned instead.
  8407. *
  8408. * For example:
  8409. *
  8410. * ARGF.bytes.to_a #=> [35, 32, ... 95, 10]
  8411. *
  8412. */
  8413. static VALUE
  8414. argf_each_byte(VALUE argf)
  8415. {
  8416. RETURN_ENUMERATOR(argf, 0, 0);
  8417. for (;;) {
  8418. if (!next_argv()) return argf;
  8419. rb_block_call(ARGF.current_file, rb_intern("each_byte"), 0, 0, 0, 0);
  8420. ARGF.next_p = 1;
  8421. }
  8422. }
  8423. /*
  8424. * call-seq:
  8425. * ARGF.chars {|char| block } -> ARGF
  8426. * ARGF.chars -> an_enumerator
  8427. *
  8428. * ARGF.each_char {|char| block } -> ARGF
  8429. * ARGF.each_char -> an_enumerator
  8430. *
  8431. * Iterates over each character of each file in +ARGF+.
  8432. *
  8433. * This method allows you to treat the files supplied on the command line as
  8434. * a single file consisting of the concatenation of each named file. After
  8435. * the last character of the first file has been returned, the first
  8436. * character of the second file is returned. The +ARGF.filename+ method can
  8437. * be used to determine the name of the file in which the current character
  8438. * appears.
  8439. *
  8440. * If no block is given, an enumerator is returned instead.
  8441. */
  8442. static VALUE
  8443. argf_each_char(VALUE argf)
  8444. {
  8445. RETURN_ENUMERATOR(argf, 0, 0);
  8446. for (;;) {
  8447. if (!next_argv()) return argf;
  8448. rb_block_call(ARGF.current_file, rb_intern("each_char"), 0, 0, 0, 0);
  8449. ARGF.next_p = 1;
  8450. }
  8451. }
  8452. /*
  8453. * call-seq:
  8454. * ARGF.filename -> String
  8455. * ARGF.path -> String
  8456. *
  8457. * Returns the current filename. "-" is returned when the current file is
  8458. * STDIN.
  8459. *
  8460. * For example:
  8461. *
  8462. * $ echo "foo" > foo
  8463. * $ echo "bar" > bar
  8464. * $ echo "glark" > glark
  8465. *
  8466. * $ ruby argf.rb foo bar glark
  8467. *
  8468. * ARGF.filename #=> "foo"
  8469. * ARGF.read(5) #=> "foo\nb"
  8470. * ARGF.filename #=> "bar"
  8471. * ARGF.skip
  8472. * ARGF.filename #=> "glark"
  8473. */
  8474. static VALUE
  8475. argf_filename(VALUE argf)
  8476. {
  8477. next_argv();
  8478. return ARGF.filename;
  8479. }
  8480. static VALUE
  8481. argf_filename_getter(ID id, VALUE *var)
  8482. {
  8483. return argf_filename(*var);
  8484. }
  8485. /*
  8486. * call-seq:
  8487. * ARGF.file -> IO or File object
  8488. *
  8489. * Returns the current file as an +IO+ or +File+ object. #<IO:<STDIN>> is
  8490. * returned when the current file is STDIN.
  8491. *
  8492. * For example:
  8493. *
  8494. * $ echo "foo" > foo
  8495. * $ echo "bar" > bar
  8496. *
  8497. * $ ruby argf.rb foo bar
  8498. *
  8499. * ARGF.file #=> #<File:foo>
  8500. * ARGF.read(5) #=> "foo\nb"
  8501. * ARGF.file #=> #<File:bar>
  8502. */
  8503. static VALUE
  8504. argf_file(VALUE argf)
  8505. {
  8506. next_argv();
  8507. return ARGF.current_file;
  8508. }
  8509. /*
  8510. * call-seq:
  8511. * ARGF.binmode -> ARGF
  8512. *
  8513. * Puts +ARGF+ into binary mode. Once a stream is in binary mode, it cannot
  8514. * be reset to non-binary mode. This option has the following effects:
  8515. *
  8516. * * Newline conversion is disabled.
  8517. * * Encoding conversion is disabled.
  8518. * * Content is treated as ASCII-8BIT.
  8519. */
  8520. static VALUE
  8521. argf_binmode_m(VALUE argf)
  8522. {
  8523. ARGF.binmode = 1;
  8524. next_argv();
  8525. ARGF_FORWARD(0, 0);
  8526. rb_io_ascii8bit_binmode(ARGF.current_file);
  8527. return argf;
  8528. }
  8529. /*
  8530. * call-seq:
  8531. * ARGF.binmode? -> true or false
  8532. *
  8533. * Returns true if +ARGF+ is being read in binary mode; false otherwise. (To
  8534. * enable binary mode use +ARGF.binmode+.
  8535. *
  8536. * For example:
  8537. *
  8538. * ARGF.binmode? #=> false
  8539. * ARGF.binmode
  8540. * ARGF.binmode? #=> true
  8541. */
  8542. static VALUE
  8543. argf_binmode_p(VALUE argf)
  8544. {
  8545. return ARGF.binmode ? Qtrue : Qfalse;
  8546. }
  8547. /*
  8548. * call-seq:
  8549. * ARGF.skip -> ARGF
  8550. *
  8551. * Sets the current file to the next file in ARGV. If there aren't any more
  8552. * files it has no effect.
  8553. *
  8554. * For example:
  8555. *
  8556. * $ ruby argf.rb foo bar
  8557. * ARGF.filename #=> "foo"
  8558. * ARGF.skip
  8559. * ARGF.filename #=> "bar"
  8560. */
  8561. static VALUE
  8562. argf_skip(VALUE argf)
  8563. {
  8564. if (ARGF.init_p && ARGF.next_p == 0) {
  8565. argf_close(ARGF.current_file);
  8566. ARGF.next_p = 1;
  8567. }
  8568. return argf;
  8569. }
  8570. /*
  8571. * call-seq:
  8572. * ARGF.close -> ARGF
  8573. *
  8574. * Closes the current file and skips to the next in the stream. Trying to
  8575. * close a file that has already been closed causes an +IOError+ to be
  8576. * raised.
  8577. *
  8578. * For example:
  8579. *
  8580. * $ ruby argf.rb foo bar
  8581. *
  8582. * ARGF.filename #=> "foo"
  8583. * ARGF.close
  8584. * ARGF.filename #=> "bar"
  8585. * ARGF.close
  8586. * ARGF.close #=> closed stream (IOError)
  8587. */
  8588. static VALUE
  8589. argf_close_m(VALUE argf)
  8590. {
  8591. next_argv();
  8592. argf_close(ARGF.current_file);
  8593. if (ARGF.next_p != -1) {
  8594. ARGF.next_p = 1;
  8595. }
  8596. ARGF.lineno = 0;
  8597. return argf;
  8598. }
  8599. /*
  8600. * call-seq:
  8601. * ARGF.closed? -> true or false
  8602. *
  8603. * Returns _true_ if the current file has been closed; _false_ otherwise. Use
  8604. * +ARGF.close+ to actually close the current file.
  8605. */
  8606. static VALUE
  8607. argf_closed(VALUE argf)
  8608. {
  8609. next_argv();
  8610. ARGF_FORWARD(0, 0);
  8611. return rb_io_closed(ARGF.current_file);
  8612. }
  8613. /*
  8614. * call-seq:
  8615. * ARGF.to_s -> String
  8616. *
  8617. * Returns "ARGF".
  8618. */
  8619. static VALUE
  8620. argf_to_s(VALUE argf)
  8621. {
  8622. return rb_str_new2("ARGF");
  8623. }
  8624. /*
  8625. * call-seq:
  8626. * ARGF.inplace_mode -> String
  8627. *
  8628. * Returns the file extension appended to the names of modified files under
  8629. * inplace-edit mode. This value can be set using +ARGF.inplace_mode=+ or
  8630. * passing the +-i+ switch to the Ruby binary.
  8631. */
  8632. static VALUE
  8633. argf_inplace_mode_get(VALUE argf)
  8634. {
  8635. if (!ARGF.inplace) return Qnil;
  8636. return rb_str_new2(ARGF.inplace);
  8637. }
  8638. static VALUE
  8639. opt_i_get(ID id, VALUE *var)
  8640. {
  8641. return argf_inplace_mode_get(*var);
  8642. }
  8643. /*
  8644. * call-seq:
  8645. * ARGF.inplace_mode = ext -> ARGF
  8646. *
  8647. * Sets the filename extension for inplace editing mode to the given String.
  8648. * Each file being edited has this value appended to its filename. The
  8649. * modified file is saved under this new name.
  8650. *
  8651. * For example:
  8652. *
  8653. * $ ruby argf.rb file.txt
  8654. *
  8655. * ARGF.inplace_mode = '.bak'
  8656. * ARGF.lines do |line|
  8657. * print line.sub("foo","bar")
  8658. * end
  8659. *
  8660. * Each line of _file.txt_ has the first occurrence of "foo" replaced with
  8661. * "bar", then the new line is written out to _file.txt.bak_.
  8662. */
  8663. static VALUE
  8664. argf_inplace_mode_set(VALUE argf, VALUE val)
  8665. {
  8666. if (rb_safe_level() >= 1 && OBJ_TAINTED(val))
  8667. rb_insecure_operation();
  8668. if (!RTEST(val)) {
  8669. if (ARGF.inplace) free(ARGF.inplace);
  8670. ARGF.inplace = 0;
  8671. }
  8672. else {
  8673. StringValue(val);
  8674. if (ARGF.inplace) free(ARGF.inplace);
  8675. ARGF.inplace = 0;
  8676. ARGF.inplace = strdup(RSTRING_PTR(val));
  8677. }
  8678. return argf;
  8679. }
  8680. static void
  8681. opt_i_set(VALUE val, ID id, VALUE *var)
  8682. {
  8683. argf_inplace_mode_set(*var, val);
  8684. }
  8685. const char *
  8686. ruby_get_inplace_mode(void)
  8687. {
  8688. return ARGF.inplace;
  8689. }
  8690. void
  8691. ruby_set_inplace_mode(const char *suffix)
  8692. {
  8693. if (ARGF.inplace) free(ARGF.inplace);
  8694. ARGF.inplace = 0;
  8695. if (suffix) ARGF.inplace = strdup(suffix);
  8696. }
  8697. /*
  8698. * call-seq:
  8699. * ARGF.argv -> ARGV
  8700. *
  8701. * Returns the +ARGV+ array, which contains the arguments passed to your
  8702. * script, one per element.
  8703. *
  8704. * For example:
  8705. *
  8706. * $ ruby argf.rb -v glark.txt
  8707. *
  8708. * ARGF.argv #=> ["-v", "glark.txt"]
  8709. *
  8710. */
  8711. static VALUE
  8712. argf_argv(VALUE argf)
  8713. {
  8714. return ARGF.argv;
  8715. }
  8716. static VALUE
  8717. argf_argv_getter(ID id, VALUE *var)
  8718. {
  8719. return argf_argv(*var);
  8720. }
  8721. VALUE
  8722. rb_get_argv(void)
  8723. {
  8724. return ARGF.argv;
  8725. }
  8726. /*
  8727. * Document-class: IOError
  8728. *
  8729. * Raised when an IO operation fails.
  8730. *
  8731. * File.open("/etc/hosts") {|f| f << "example"}
  8732. * #=> IOError: not opened for writing
  8733. *
  8734. * File.open("/etc/hosts") {|f| f.close; f.read }
  8735. * #=> IOError: closed stream
  8736. *
  8737. * Note that some IO failures raise +SystemCallError+s and these are not
  8738. * subclasses of IOError:
  8739. *
  8740. * File.open("does/not/exist")
  8741. * #=> Errno::ENOENT: No such file or directory - does/not/exist
  8742. */
  8743. /*
  8744. * Document-class: EOFError
  8745. *
  8746. * Raised by some IO operations when reaching the end of file. Many IO
  8747. * methods exist in two forms,
  8748. *
  8749. * one that returns +nil+ when the end of file is reached, the other
  8750. * raises EOFError +EOFError+.
  8751. *
  8752. * +EOFError+ is a subclass of +IOError+.
  8753. *
  8754. * file = File.open("/etc/hosts")
  8755. * file.read
  8756. * file.gets #=> nil
  8757. * file.readline #=> EOFError: end of file reached
  8758. */
  8759. /*
  8760. * Document-class: ARGF
  8761. *
  8762. * +ARGF+ is a stream designed for use in scripts that process files given as
  8763. * command-line arguments, or passed in via STDIN.
  8764. *
  8765. * The arguments passed to your script are stored in the +ARGV+ Array, one
  8766. * argument per element. +ARGF+ assumes that any arguments that aren't
  8767. * filenames have been removed from +ARGV+. For example:
  8768. *
  8769. * $ ruby argf.rb --verbose file1 file2
  8770. *
  8771. * ARGV #=> ["--verbose", "file1", "file2"]
  8772. * option = ARGV.shift #=> "--verbose"
  8773. * ARGV #=> ["file1", "file2"]
  8774. *
  8775. * You can now use +ARGF+ to work with a concatenation of each of these named
  8776. * files. For instance, +ARGF.read+ will return the contents of _file1_
  8777. * followed by the contents of _file2_.
  8778. *
  8779. * After a file in +ARGV+ has been read, +ARGF+ removes it from the Array.
  8780. * Thus, after all files have been read +ARGV+ will be empty.
  8781. *
  8782. * You can manipulate +ARGV+ yourself to control what +ARGF+ operates on. If
  8783. * you remove a file from +ARGV+, it is ignored by +ARGF+; if you add files to
  8784. * +ARGV+, they are treated as if they were named on the command line. For
  8785. * example:
  8786. *
  8787. * ARGV.replace ["file1"]
  8788. * ARGF.readlines # Returns the contents of file1 as an Array
  8789. * ARGV #=> []
  8790. * ARGV.replace ["file2", "file3"]
  8791. * ARGF.read # Returns the contents of file2 and file3
  8792. *
  8793. * If +ARGV+ is empty, +ARGF+ acts as if it contained STDIN, i.e. the data
  8794. * piped to your script. For example:
  8795. *
  8796. * $ echo "glark" | ruby -e 'p ARGF.read'
  8797. * "glark\n"
  8798. */
  8799. /*
  8800. * Class <code>IO</code> is the basis for all input and output in Ruby.
  8801. * An I/O stream may be <em>duplexed</em> (that is, bidirectional), and
  8802. * so may use more than one native operating system stream.
  8803. *
  8804. * Many of the examples in this section use class <code>File</code>,
  8805. * the only standard subclass of <code>IO</code>. The two classes are
  8806. * closely associated.
  8807. *
  8808. * As used in this section, <em>portname</em> may take any of the
  8809. * following forms.
  8810. *
  8811. * * A plain string represents a filename suitable for the underlying
  8812. * operating system.
  8813. *
  8814. * * A string starting with ``<code>|</code>'' indicates a subprocess.
  8815. * The remainder of the string following the ``<code>|</code>'' is
  8816. * invoked as a process with appropriate input/output channels
  8817. * connected to it.
  8818. *
  8819. * * A string equal to ``<code>|-</code>'' will create another Ruby
  8820. * instance as a subprocess.
  8821. *
  8822. * Ruby will convert pathnames between different operating system
  8823. * conventions if possible. For instance, on a Windows system the
  8824. * filename ``<code>/gumby/ruby/test.rb</code>'' will be opened as
  8825. * ``<code>\gumby\ruby\test.rb</code>''. When specifying a
  8826. * Windows-style filename in a Ruby string, remember to escape the
  8827. * backslashes:
  8828. *
  8829. * "c:\\gumby\\ruby\\test.rb"
  8830. *
  8831. * Our examples here will use the Unix-style forward slashes;
  8832. * <code>File::SEPARATOR</code> can be used to get the
  8833. * platform-specific separator character.
  8834. *
  8835. * I/O ports may be opened in any one of several different modes, which
  8836. * are shown in this section as <em>mode</em>. The mode may
  8837. * either be a Fixnum or a String. If numeric, it should be
  8838. * one of the operating system specific constants (O_RDONLY,
  8839. * O_WRONLY, O_RDWR, O_APPEND and so on). See man open(2) for
  8840. * more information.
  8841. *
  8842. * If the mode is given as a String, it must be one of the
  8843. * values listed in the following table.
  8844. *
  8845. * Mode | Meaning
  8846. * -----+--------------------------------------------------------
  8847. * "r" | Read-only, starts at beginning of file (default mode).
  8848. * -----+--------------------------------------------------------
  8849. * "r+" | Read-write, starts at beginning of file.
  8850. * -----+--------------------------------------------------------
  8851. * "w" | Write-only, truncates existing file
  8852. * | to zero length or creates a new file for writing.
  8853. * -----+--------------------------------------------------------
  8854. * "w+" | Read-write, truncates existing file to zero length
  8855. * | or creates a new file for reading and writing.
  8856. * -----+--------------------------------------------------------
  8857. * "a" | Write-only, starts at end of file if file exists,
  8858. * | otherwise creates a new file for writing.
  8859. * -----+--------------------------------------------------------
  8860. * "a+" | Read-write, starts at end of file if file exists,
  8861. * | otherwise creates a new file for reading and
  8862. * | writing.
  8863. * -----+--------------------------------------------------------
  8864. * "b" | Binary file mode (may appear with
  8865. * | any of the key letters listed above).
  8866. * | Suppresses EOL <-> CRLF conversion on Windows. And
  8867. * | sets external encoding to ASCII-8BIT unless explicitly
  8868. * | specified.
  8869. * -----+--------------------------------------------------------
  8870. * "t" | Text file mode (may appear with
  8871. * | any of the key letters listed above except "b").
  8872. *
  8873. *
  8874. * The global constant ARGF (also accessible as $<) provides an
  8875. * IO-like stream which allows access to all files mentioned on the
  8876. * command line (or STDIN if no files are mentioned). ARGF provides
  8877. * the methods <code>#path</code> and <code>#filename</code> to access
  8878. * the name of the file currently being read.
  8879. */
  8880. void
  8881. Init_IO(void)
  8882. {
  8883. #undef rb_intern
  8884. #define rb_intern(str) rb_intern_const(str)
  8885. VALUE rb_cARGF;
  8886. #ifdef __CYGWIN__
  8887. #include <sys/cygwin.h>
  8888. static struct __cygwin_perfile pf[] =
  8889. {
  8890. {"", O_RDONLY | O_BINARY},
  8891. {"", O_WRONLY | O_BINARY},
  8892. {"", O_RDWR | O_BINARY},
  8893. {"", O_APPEND | O_BINARY},
  8894. {NULL, 0}
  8895. };
  8896. cygwin_internal(CW_PERFILE, pf);
  8897. #endif
  8898. rb_eIOError = rb_define_class("IOError", rb_eStandardError);
  8899. rb_eEOFError = rb_define_class("EOFError", rb_eIOError);
  8900. id_write = rb_intern("write");
  8901. id_read = rb_intern("read");
  8902. id_getc = rb_intern("getc");
  8903. id_flush = rb_intern("flush");
  8904. id_readpartial = rb_intern("readpartial");
  8905. rb_define_global_function("syscall", rb_f_syscall, -1);
  8906. rb_define_global_function("open", rb_f_open, -1);
  8907. rb_define_global_function("printf", rb_f_printf, -1);
  8908. rb_define_global_function("print", rb_f_print, -1);
  8909. rb_define_global_function("putc", rb_f_putc, 1);
  8910. rb_define_global_function("puts", rb_f_puts, -1);
  8911. rb_define_global_function("gets", rb_f_gets, -1);
  8912. rb_define_global_function("readline", rb_f_readline, -1);
  8913. rb_define_global_function("select", rb_f_select, -1);
  8914. rb_define_global_function("readlines", rb_f_readlines, -1);
  8915. rb_define_global_function("`", rb_f_backquote, 1);
  8916. rb_define_global_function("p", rb_f_p, -1);
  8917. rb_define_method(rb_mKernel, "display", rb_obj_display, -1);
  8918. rb_cIO = rb_define_class("IO", rb_cObject);
  8919. rb_include_module(rb_cIO, rb_mEnumerable);
  8920. rb_mWaitReadable = rb_define_module_under(rb_cIO, "WaitReadable");
  8921. rb_mWaitWritable = rb_define_module_under(rb_cIO, "WaitWritable");
  8922. #if 0
  8923. /* This is necessary only for forcing rdoc handle File::open */
  8924. rb_define_singleton_method(rb_cFile, "open", rb_io_s_open, -1);
  8925. #endif
  8926. rb_define_alloc_func(rb_cIO, io_alloc);
  8927. rb_define_singleton_method(rb_cIO, "new", rb_io_s_new, -1);
  8928. rb_define_singleton_method(rb_cIO, "open", rb_io_s_open, -1);
  8929. rb_define_singleton_method(rb_cIO, "sysopen", rb_io_s_sysopen, -1);
  8930. rb_define_singleton_method(rb_cIO, "for_fd", rb_io_s_for_fd, -1);
  8931. rb_define_singleton_method(rb_cIO, "popen", rb_io_s_popen, -1);
  8932. rb_define_singleton_method(rb_cIO, "foreach", rb_io_s_foreach, -1);
  8933. rb_define_singleton_method(rb_cIO, "readlines", rb_io_s_readlines, -1);
  8934. rb_define_singleton_method(rb_cIO, "read", rb_io_s_read, -1);
  8935. rb_define_singleton_method(rb_cIO, "binread", rb_io_s_binread, -1);
  8936. rb_define_singleton_method(rb_cIO, "select", rb_f_select, -1);
  8937. rb_define_singleton_method(rb_cIO, "pipe", rb_io_s_pipe, -1);
  8938. rb_define_singleton_method(rb_cIO, "try_convert", rb_io_s_try_convert, 1);
  8939. rb_define_singleton_method(rb_cIO, "copy_stream", rb_io_s_copy_stream, -1);
  8940. rb_define_method(rb_cIO, "initialize", rb_io_initialize, -1);
  8941. rb_output_fs = Qnil;
  8942. rb_define_hooked_variable("$,", &rb_output_fs, 0, rb_str_setter);
  8943. rb_rs = rb_default_rs = rb_usascii_str_new2("\n");
  8944. rb_gc_register_mark_object(rb_default_rs);
  8945. rb_output_rs = Qnil;
  8946. OBJ_FREEZE(rb_default_rs); /* avoid modifying RS_default */
  8947. rb_define_hooked_variable("$/", &rb_rs, 0, rb_str_setter);
  8948. rb_define_hooked_variable("$-0", &rb_rs, 0, rb_str_setter);
  8949. rb_define_hooked_variable("$\\", &rb_output_rs, 0, rb_str_setter);
  8950. rb_define_virtual_variable("$_", rb_lastline_get, rb_lastline_set);
  8951. rb_define_method(rb_cIO, "initialize_copy", rb_io_init_copy, 1);
  8952. rb_define_method(rb_cIO, "reopen", rb_io_reopen, -1);
  8953. rb_define_method(rb_cIO, "print", rb_io_print, -1);
  8954. rb_define_method(rb_cIO, "putc", rb_io_putc, 1);
  8955. rb_define_method(rb_cIO, "puts", rb_io_puts, -1);
  8956. rb_define_method(rb_cIO, "printf", rb_io_printf, -1);
  8957. rb_define_method(rb_cIO, "each", rb_io_each_line, -1);
  8958. rb_define_method(rb_cIO, "each_line", rb_io_each_line, -1);
  8959. rb_define_method(rb_cIO, "each_byte", rb_io_each_byte, 0);
  8960. rb_define_method(rb_cIO, "each_char", rb_io_each_char, 0);
  8961. rb_define_method(rb_cIO, "each_codepoint", rb_io_each_codepoint, 0);
  8962. rb_define_method(rb_cIO, "lines", rb_io_each_line, -1);
  8963. rb_define_method(rb_cIO, "bytes", rb_io_each_byte, 0);
  8964. rb_define_method(rb_cIO, "chars", rb_io_each_char, 0);
  8965. rb_define_method(rb_cIO, "codepoints", rb_io_each_codepoint, 0);
  8966. rb_define_method(rb_cIO, "syswrite", rb_io_syswrite, 1);
  8967. rb_define_method(rb_cIO, "sysread", rb_io_sysread, -1);
  8968. rb_define_method(rb_cIO, "fileno", rb_io_fileno, 0);
  8969. rb_define_alias(rb_cIO, "to_i", "fileno");
  8970. rb_define_method(rb_cIO, "to_io", rb_io_to_io, 0);
  8971. rb_define_method(rb_cIO, "fsync", rb_io_fsync, 0);
  8972. rb_define_method(rb_cIO, "fdatasync", rb_io_fdatasync, 0);
  8973. rb_define_method(rb_cIO, "sync", rb_io_sync, 0);
  8974. rb_define_method(rb_cIO, "sync=", rb_io_set_sync, 1);
  8975. rb_define_method(rb_cIO, "lineno", rb_io_lineno, 0);
  8976. rb_define_method(rb_cIO, "lineno=", rb_io_set_lineno, 1);
  8977. rb_define_method(rb_cIO, "readlines", rb_io_readlines, -1);
  8978. rb_define_method(rb_cIO, "read_nonblock", io_read_nonblock, -1);
  8979. rb_define_method(rb_cIO, "write_nonblock", rb_io_write_nonblock, 1);
  8980. rb_define_method(rb_cIO, "readpartial", io_readpartial, -1);
  8981. rb_define_method(rb_cIO, "read", io_read, -1);
  8982. rb_define_method(rb_cIO, "write", io_write_m, 1);
  8983. rb_define_method(rb_cIO, "gets", rb_io_gets_m, -1);
  8984. rb_define_method(rb_cIO, "readline", rb_io_readline, -1);
  8985. rb_define_method(rb_cIO, "getc", rb_io_getc, 0);
  8986. rb_define_method(rb_cIO, "getbyte", rb_io_getbyte, 0);
  8987. rb_define_method(rb_cIO, "readchar", rb_io_readchar, 0);
  8988. rb_define_method(rb_cIO, "readbyte", rb_io_readbyte, 0);
  8989. rb_define_method(rb_cIO, "ungetbyte",rb_io_ungetbyte, 1);
  8990. rb_define_method(rb_cIO, "ungetc",rb_io_ungetc, 1);
  8991. rb_define_method(rb_cIO, "<<", rb_io_addstr, 1);
  8992. rb_define_method(rb_cIO, "flush", rb_io_flush, 0);
  8993. rb_define_method(rb_cIO, "tell", rb_io_tell, 0);
  8994. rb_define_method(rb_cIO, "seek", rb_io_seek_m, -1);
  8995. rb_define_const(rb_cIO, "SEEK_SET", INT2FIX(SEEK_SET));
  8996. rb_define_const(rb_cIO, "SEEK_CUR", INT2FIX(SEEK_CUR));
  8997. rb_define_const(rb_cIO, "SEEK_END", INT2FIX(SEEK_END));
  8998. rb_define_method(rb_cIO, "rewind", rb_io_rewind, 0);
  8999. rb_define_method(rb_cIO, "pos", rb_io_tell, 0);
  9000. rb_define_method(rb_cIO, "pos=", rb_io_set_pos, 1);
  9001. rb_define_method(rb_cIO, "eof", rb_io_eof, 0);
  9002. rb_define_method(rb_cIO, "eof?", rb_io_eof, 0);
  9003. rb_define_method(rb_cIO, "close_on_exec?", rb_io_close_on_exec_p, 0);
  9004. rb_define_method(rb_cIO, "close_on_exec=", rb_io_set_close_on_exec, 1);
  9005. rb_define_method(rb_cIO, "close", rb_io_close_m, 0);
  9006. rb_define_method(rb_cIO, "closed?", rb_io_closed, 0);
  9007. rb_define_method(rb_cIO, "close_read", rb_io_close_read, 0);
  9008. rb_define_method(rb_cIO, "close_write", rb_io_close_write, 0);
  9009. rb_define_method(rb_cIO, "isatty", rb_io_isatty, 0);
  9010. rb_define_method(rb_cIO, "tty?", rb_io_isatty, 0);
  9011. rb_define_method(rb_cIO, "binmode", rb_io_binmode_m, 0);
  9012. rb_define_method(rb_cIO, "binmode?", rb_io_binmode_p, 0);
  9013. rb_define_method(rb_cIO, "sysseek", rb_io_sysseek, -1);
  9014. rb_define_method(rb_cIO, "ioctl", rb_io_ioctl, -1);
  9015. rb_define_method(rb_cIO, "fcntl", rb_io_fcntl, -1);
  9016. rb_define_method(rb_cIO, "pid", rb_io_pid, 0);
  9017. rb_define_method(rb_cIO, "inspect", rb_io_inspect, 0);
  9018. rb_define_method(rb_cIO, "external_encoding", rb_io_external_encoding, 0);
  9019. rb_define_method(rb_cIO, "internal_encoding", rb_io_internal_encoding, 0);
  9020. rb_define_method(rb_cIO, "set_encoding", rb_io_set_encoding, -1);
  9021. rb_define_method(rb_cIO, "autoclose?", rb_io_autoclose_p, 0);
  9022. rb_define_method(rb_cIO, "autoclose=", rb_io_set_autoclose, 1);
  9023. rb_define_variable("$stdin", &rb_stdin);
  9024. rb_stdin = prep_stdio(stdin, FMODE_READABLE, rb_cIO, "<STDIN>");
  9025. rb_define_hooked_variable("$stdout", &rb_stdout, 0, stdout_setter);
  9026. rb_stdout = prep_stdio(stdout, FMODE_WRITABLE, rb_cIO, "<STDOUT>");
  9027. rb_define_hooked_variable("$stderr", &rb_stderr, 0, stdout_setter);
  9028. rb_stderr = prep_stdio(stderr, FMODE_WRITABLE|FMODE_SYNC, rb_cIO, "<STDERR>");
  9029. rb_define_hooked_variable("$>", &rb_stdout, 0, stdout_setter);
  9030. orig_stdout = rb_stdout;
  9031. rb_deferr = orig_stderr = rb_stderr;
  9032. /* constants to hold original stdin/stdout/stderr */
  9033. rb_define_global_const("STDIN", rb_stdin);
  9034. rb_define_global_const("STDOUT", rb_stdout);
  9035. rb_define_global_const("STDERR", rb_stderr);
  9036. /*
  9037. * Hack to get rdoc to regard ARGF as a class:
  9038. * rb_cARGF = rb_define_class("ARGF", rb_cObject);
  9039. */
  9040. rb_cARGF = rb_class_new(rb_cObject);
  9041. rb_set_class_path(rb_cARGF, rb_cObject, "ARGF.class");
  9042. rb_define_alloc_func(rb_cARGF, argf_alloc);
  9043. rb_include_module(rb_cARGF, rb_mEnumerable);
  9044. rb_define_method(rb_cARGF, "initialize", argf_initialize, -2);
  9045. rb_define_method(rb_cARGF, "initialize_copy", argf_initialize_copy, 1);
  9046. rb_define_method(rb_cARGF, "to_s", argf_to_s, 0);
  9047. rb_define_method(rb_cARGF, "argv", argf_argv, 0);
  9048. rb_define_method(rb_cARGF, "fileno", argf_fileno, 0);
  9049. rb_define_method(rb_cARGF, "to_i", argf_fileno, 0);
  9050. rb_define_method(rb_cARGF, "to_io", argf_to_io, 0);
  9051. rb_define_method(rb_cARGF, "each", argf_each_line, -1);
  9052. rb_define_method(rb_cARGF, "each_line", argf_each_line, -1);
  9053. rb_define_method(rb_cARGF, "each_byte", argf_each_byte, 0);
  9054. rb_define_method(rb_cARGF, "each_char", argf_each_char, 0);
  9055. rb_define_method(rb_cARGF, "lines", argf_each_line, -1);
  9056. rb_define_method(rb_cARGF, "bytes", argf_each_byte, 0);
  9057. rb_define_method(rb_cARGF, "chars", argf_each_char, 0);
  9058. rb_define_method(rb_cARGF, "read", argf_read, -1);
  9059. rb_define_method(rb_cARGF, "readpartial", argf_readpartial, -1);
  9060. rb_define_method(rb_cARGF, "readlines", argf_readlines, -1);
  9061. rb_define_method(rb_cARGF, "to_a", argf_readlines, -1);
  9062. rb_define_method(rb_cARGF, "gets", argf_gets, -1);
  9063. rb_define_method(rb_cARGF, "readline", argf_readline, -1);
  9064. rb_define_method(rb_cARGF, "getc", argf_getc, 0);
  9065. rb_define_method(rb_cARGF, "getbyte", argf_getbyte, 0);
  9066. rb_define_method(rb_cARGF, "readchar", argf_readchar, 0);
  9067. rb_define_method(rb_cARGF, "readbyte", argf_readbyte, 0);
  9068. rb_define_method(rb_cARGF, "tell", argf_tell, 0);
  9069. rb_define_method(rb_cARGF, "seek", argf_seek_m, -1);
  9070. rb_define_method(rb_cARGF, "rewind", argf_rewind, 0);
  9071. rb_define_method(rb_cARGF, "pos", argf_tell, 0);
  9072. rb_define_method(rb_cARGF, "pos=", argf_set_pos, 1);
  9073. rb_define_method(rb_cARGF, "eof", argf_eof, 0);
  9074. rb_define_method(rb_cARGF, "eof?", argf_eof, 0);
  9075. rb_define_method(rb_cARGF, "binmode", argf_binmode_m, 0);
  9076. rb_define_method(rb_cARGF, "binmode?", argf_binmode_p, 0);
  9077. rb_define_method(rb_cARGF, "filename", argf_filename, 0);
  9078. rb_define_method(rb_cARGF, "path", argf_filename, 0);
  9079. rb_define_method(rb_cARGF, "file", argf_file, 0);
  9080. rb_define_method(rb_cARGF, "skip", argf_skip, 0);
  9081. rb_define_method(rb_cARGF, "close", argf_close_m, 0);
  9082. rb_define_method(rb_cARGF, "closed?", argf_closed, 0);
  9083. rb_define_method(rb_cARGF, "lineno", argf_lineno, 0);
  9084. rb_define_method(rb_cARGF, "lineno=", argf_set_lineno, 1);
  9085. rb_define_method(rb_cARGF, "inplace_mode", argf_inplace_mode_get, 0);
  9086. rb_define_method(rb_cARGF, "inplace_mode=", argf_inplace_mode_set, 1);
  9087. rb_define_method(rb_cARGF, "external_encoding", argf_external_encoding, 0);
  9088. rb_define_method(rb_cARGF, "internal_encoding", argf_internal_encoding, 0);
  9089. rb_define_method(rb_cARGF, "set_encoding", argf_set_encoding, -1);
  9090. argf = rb_class_new_instance(0, 0, rb_cARGF);
  9091. rb_define_readonly_variable("$<", &argf);
  9092. rb_define_global_const("ARGF", argf);
  9093. rb_define_hooked_variable("$.", &argf, argf_lineno_getter, argf_lineno_setter);
  9094. rb_define_hooked_variable("$FILENAME", &argf, argf_filename_getter, rb_gvar_readonly_setter);
  9095. ARGF.filename = rb_str_new2("-");
  9096. rb_define_hooked_variable("$-i", &argf, opt_i_get, opt_i_set);
  9097. rb_define_hooked_variable("$*", &argf, argf_argv_getter, rb_gvar_readonly_setter);
  9098. #if defined (_WIN32) || defined(__CYGWIN__)
  9099. atexit(pipe_atexit);
  9100. #endif
  9101. Init_File();
  9102. rb_define_method(rb_cFile, "initialize", rb_file_initialize, -1);
  9103. /* open for reading only */
  9104. rb_file_const("RDONLY", INT2FIX(O_RDONLY));
  9105. /* open for writing only */
  9106. rb_file_const("WRONLY", INT2FIX(O_WRONLY));
  9107. /* open for reading and writing */
  9108. rb_file_const("RDWR", INT2FIX(O_RDWR));
  9109. /* append on each write */
  9110. rb_file_const("APPEND", INT2FIX(O_APPEND));
  9111. /* create file if it does not exist */
  9112. rb_file_const("CREAT", INT2FIX(O_CREAT));
  9113. /* error if CREAT and the file exists */
  9114. rb_file_const("EXCL", INT2FIX(O_EXCL));
  9115. #if defined(O_NDELAY) || defined(O_NONBLOCK)
  9116. # ifndef O_NONBLOCK
  9117. # define O_NONBLOCK O_NDELAY
  9118. # endif
  9119. /* do not block on open or for data to become available */
  9120. rb_file_const("NONBLOCK", INT2FIX(O_NONBLOCK));
  9121. #endif
  9122. /* truncate size to 0 */
  9123. rb_file_const("TRUNC", INT2FIX(O_TRUNC));
  9124. #ifdef O_NOCTTY
  9125. /* not to make opened IO the controlling terminal device */
  9126. rb_file_const("NOCTTY", INT2FIX(O_NOCTTY));
  9127. #endif
  9128. #ifndef O_BINARY
  9129. # define O_BINARY 0
  9130. #endif
  9131. /* disable line code conversion and make ASCII-8BIT */
  9132. rb_file_const("BINARY", INT2FIX(O_BINARY));
  9133. #ifdef O_SYNC
  9134. rb_file_const("SYNC", INT2FIX(O_SYNC));
  9135. #endif
  9136. #ifdef O_DSYNC
  9137. rb_file_const("DSYNC", INT2FIX(O_DSYNC));
  9138. #endif
  9139. #ifdef O_RSYNC
  9140. rb_file_const("RSYNC", INT2FIX(O_RSYNC));
  9141. #endif
  9142. #ifdef O_NOFOLLOW
  9143. /* do not follow symlinks */
  9144. rb_file_const("NOFOLLOW", INT2FIX(O_NOFOLLOW)); /* FreeBSD, Linux */
  9145. #endif
  9146. #ifdef O_NOATIME
  9147. /* do not change atime */
  9148. rb_file_const("NOATIME", INT2FIX(O_NOATIME)); /* Linux */
  9149. #endif
  9150. sym_mode = ID2SYM(rb_intern("mode"));
  9151. sym_perm = ID2SYM(rb_intern("perm"));
  9152. sym_extenc = ID2SYM(rb_intern("external_encoding"));
  9153. sym_intenc = ID2SYM(rb_intern("internal_encoding"));
  9154. sym_encoding = ID2SYM(rb_intern("encoding"));
  9155. sym_open_args = ID2SYM(rb_intern("open_args"));
  9156. sym_textmode = ID2SYM(rb_intern("textmode"));
  9157. sym_binmode = ID2SYM(rb_intern("binmode"));
  9158. sym_autoclose = ID2SYM(rb_intern("autoclose"));
  9159. }