PageRenderTime 106ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 2ms

/io.c

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