00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #if defined(__VMS)
00016 #define _XOPEN_SOURCE
00017 #define _POSIX_C_SOURCE 2
00018 #endif
00019
00020 #include "ruby.h"
00021 #include "rubyio.h"
00022 #include "rubysig.h"
00023 #include "env.h"
00024 #include <ctype.h>
00025 #include <errno.h>
00026
00027 #if defined(MSDOS) || defined(__BOW__) || defined(__CYGWIN__) || defined(_WIN32) || defined(__human68k__) || defined(__EMX__) || defined(__BEOS__)
00028 # define NO_SAFE_RENAME
00029 #endif
00030
00031 #if defined(MSDOS) || defined(__CYGWIN__) || defined(_WIN32)
00032 # define NO_LONG_FNAME
00033 #endif
00034
00035 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(sun) || defined(_nec_ews)
00036 # define USE_SETVBUF
00037 #endif
00038
00039 #ifdef __QNXNTO__
00040 #include "unix.h"
00041 #endif
00042
00043 #include <sys/types.h>
00044 #if defined(HAVE_SYS_IOCTL_H) && !defined(DJGPP) && !defined(_WIN32) && !defined(__human68k__)
00045 #include <sys/ioctl.h>
00046 #endif
00047 #if defined(HAVE_FCNTL_H) || defined(_WIN32)
00048 #include <fcntl.h>
00049 #elif defined(HAVE_SYS_FCNTL_H)
00050 #include <sys/fcntl.h>
00051 #endif
00052
00053 #if !HAVE_OFF_T && !defined(off_t)
00054 # define off_t long
00055 #endif
00056 #if !HAVE_FSEEKO && !defined(fseeko)
00057 # define fseeko fseek
00058 #endif
00059 #if !HAVE_FTELLO && !defined(ftello)
00060 # define ftello ftell
00061 #endif
00062
00063 #include <sys/stat.h>
00064
00065
00066 #if defined(HAVE_SYS_PARAM_H) && !(defined(__EMX__) || defined(__HIUX_MPP__))
00067 # include <sys/param.h>
00068 #endif
00069
00070 #if !defined NOFILE
00071 # define NOFILE 64
00072 #endif
00073
00074 #ifdef HAVE_UNISTD_H
00075 #ifdef HAVE_SYSCALL_H
00076 #include <syscall.h>
00077 #elif defined HAVE_SYS_SYSCALL_H
00078 #include <sys/syscall.h>
00079 #endif
00080
00081 #include <unistd.h>
00082 #endif
00083
00084 extern void Init_File (void);
00085
00086 #ifdef __BEOS__
00087 # ifndef NOFILE
00088 # define NOFILE (OPEN_MAX)
00089 # endif
00090 #include <net/socket.h>
00091 #endif
00092
00093 #include "util.h"
00094
00095 #ifndef O_ACCMODE
00096 #define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR)
00097 #endif
00098
00099 #if SIZEOF_OFF_T > SIZEOF_LONG && !defined(HAVE_LONG_LONG)
00100 # error off_t is bigger than long, but you have no long long...
00101 #endif
00102
00103 #ifndef PIPE_BUF
00104 # ifdef _POSIX_PIPE_BUF
00105 # define PIPE_BUF _POSIX_PIPE_BUF
00106 # else
00107 # define PIPE_BUF 512
00108 # endif
00109 #endif
00110
00111 VALUE rb_cIO;
00112 VALUE rb_eEOFError;
00113 VALUE rb_eIOError;
00114
00115 VALUE rb_stdin, rb_stdout, rb_stderr;
00116 VALUE rb_deferr;
00117 static VALUE orig_stdout, orig_stderr;
00118
00119 VALUE rb_output_fs;
00120 VALUE rb_rs;
00121 VALUE rb_output_rs;
00122 VALUE rb_default_rs;
00123
00124 static VALUE argf;
00125
00126 static ID id_write, id_read, id_getc;
00127
00128 extern char *ruby_inplace_mode;
00129
00130 struct timeval rb_time_interval (VALUE);
00131
00132 static VALUE filename, current_file;
00133 static int gets_lineno;
00134 static int init_p = 0, next_p = 0;
00135 static VALUE lineno = INT2FIX(0);
00136
00137 #ifdef _STDIO_USES_IOSTREAM
00138 # ifdef _IO_fpos_t
00139 # define READ_DATA_PENDING(fp) ((fp)->_IO_read_ptr != (fp)->_IO_read_end)
00140 # define READ_DATA_PENDING_COUNT(fp) ((fp)->_IO_read_end - (fp)->_IO_read_ptr)
00141 # define READ_DATA_PENDING_PTR(fp) ((fp)->_IO_read_ptr)
00142 # else
00143 # define READ_DATA_PENDING(fp) ((fp)->_gptr < (fp)->_egptr)
00144 # define READ_DATA_PENDING_COUNT(fp) ((fp)->_egptr - (fp)->_gptr)
00145 # define READ_DATA_PENDING_PTR(fp) ((fp)->_gptr)
00146 # endif
00147 #elif defined(FILE_COUNT)
00148 # define READ_DATA_PENDING(fp) ((fp)->FILE_COUNT > 0)
00149 # define READ_DATA_PENDING_COUNT(fp) ((fp)->FILE_COUNT)
00150 #elif defined(FILE_READEND)
00151 # define READ_DATA_PENDING(fp) ((fp)->FILE_READPTR < (fp)->FILE_READEND)
00152 # define READ_DATA_PENDING_COUNT(fp) ((fp)->FILE_READEND - (fp)->FILE_READPTR)
00153 #elif defined(__BEOS__)
00154 # define READ_DATA_PENDING(fp) (fp->_state._eof == 0)
00155 #elif defined(__VMS)
00156 # define READ_DATA_PENDING_COUNT(fp) ((unsigned int)(*(fp))->_cnt)
00157 # define READ_DATA_PENDING(fp) (((unsigned int)(*(fp))->_cnt) > 0)
00158 # define READ_DATA_BUFFERED(fp) 0
00159 #else
00160
00161 extern int ReadDataPending();
00162 # define READ_DATA_PENDING(fp) (!feof(fp))
00163 # define READ_DATA_BUFFERED(fp) 0
00164 #endif
00165 #ifndef READ_DATA_BUFFERED
00166 # define READ_DATA_BUFFERED(fp) READ_DATA_PENDING(fp)
00167 #endif
00168
00169 #ifndef READ_DATA_PENDING_PTR
00170 # ifdef FILE_READPTR
00171 # define READ_DATA_PENDING_PTR(fp) ((char *)(fp)->FILE_READPTR)
00172 # endif
00173 #endif
00174
00175 #if defined __DJGPP__
00176 # undef READ_DATA_PENDING_COUNT
00177 # undef READ_DATA_PENDING_PTR
00178 #endif
00179
00180 #define READ_CHECK(fp) do {\
00181 if (!READ_DATA_PENDING(fp)) {\
00182 rb_thread_wait_fd(fileno(fp));\
00183 rb_io_check_closed(fptr);\
00184 }\
00185 } while(0)
00186
00187 void
00188 rb_eof_error()
00189 {
00190 rb_raise(rb_eEOFError, "end of file reached");
00191 }
00192
00193 VALUE
00194 rb_io_taint_check(io)
00195 VALUE io;
00196 {
00197 if (!OBJ_TAINTED(io) && rb_safe_level() >= 4)
00198 rb_raise(rb_eSecurityError, "Insecure: operation on untainted IO");
00199 rb_check_frozen(io);
00200 return io;
00201 }
00202
00203 void
00204 rb_io_check_initialized(fptr)
00205 OpenFile *fptr;
00206 {
00207 if (!fptr) {
00208 rb_raise(rb_eIOError, "uninitialized stream");
00209 }
00210 }
00211
00212 void
00213 rb_io_check_closed(fptr)
00214 OpenFile *fptr;
00215 {
00216 rb_io_check_initialized(fptr);
00217 if (!fptr->f && !fptr->f2) {
00218 rb_raise(rb_eIOError, "closed stream");
00219 }
00220 }
00221
00222 static void io_fflush (FILE *, OpenFile *);
00223
00224 static OpenFile *
00225 flush_before_seek(fptr)
00226 OpenFile *fptr;
00227 {
00228 if (fptr->mode & FMODE_WBUF) {
00229 io_fflush(GetWriteFile(fptr), fptr);
00230 }
00231 return fptr;
00232 }
00233
00234 #define io_seek(fptr, ofs, whence) fseeko(flush_before_seek(fptr)->f, ofs, whence)
00235 #define io_tell(fptr) ftello(flush_before_seek(fptr)->f)
00236
00237 #ifndef SEEK_CUR
00238 # define SEEK_SET 0
00239 # define SEEK_CUR 1
00240 # define SEEK_END 2
00241 #endif
00242
00243 #define FMODE_SYNCWRITE (FMODE_SYNC|FMODE_WRITABLE)
00244
00245 void
00246 rb_io_check_readable(fptr)
00247 OpenFile *fptr;
00248 {
00249 rb_io_check_closed(fptr);
00250 if (!(fptr->mode & FMODE_READABLE)) {
00251 rb_raise(rb_eIOError, "not opened for reading");
00252 }
00253 #if NEED_IO_SEEK_BETWEEN_RW
00254 if (((fptr->mode & FMODE_WBUF) ||
00255 (fptr->mode & (FMODE_SYNCWRITE|FMODE_RBUF)) == FMODE_SYNCWRITE) &&
00256 !feof(fptr->f) &&
00257 !fptr->f2) {
00258 io_seek(fptr, 0, SEEK_CUR);
00259 }
00260 #endif
00261 fptr->mode |= FMODE_RBUF;
00262 }
00263
00264 void
00265 rb_io_check_writable(fptr)
00266 OpenFile *fptr;
00267 {
00268 rb_io_check_closed(fptr);
00269 if (!(fptr->mode & FMODE_WRITABLE)) {
00270 rb_raise(rb_eIOError, "not opened for writing");
00271 }
00272 if ((fptr->mode & FMODE_RBUF) && !feof(fptr->f) && !fptr->f2) {
00273 io_seek(fptr, 0, SEEK_CUR);
00274 }
00275 if (!fptr->f2) {
00276 fptr->mode &= ~FMODE_RBUF;
00277 }
00278 }
00279
00280 int
00281 rb_read_pending(fp)
00282 FILE *fp;
00283 {
00284 return READ_DATA_PENDING(fp);
00285 }
00286
00287 void
00288 rb_read_check(fp)
00289 FILE *fp;
00290 {
00291 if (!READ_DATA_PENDING(fp)) {
00292 rb_thread_wait_fd(fileno(fp));
00293 }
00294 }
00295
00296 static int
00297 ruby_dup(orig)
00298 int orig;
00299 {
00300 int fd;
00301
00302 fd = dup(orig);
00303 if (fd < 0) {
00304 if (errno == EMFILE || errno == ENFILE) {
00305 rb_gc();
00306 fd = dup(orig);
00307 }
00308 if (fd < 0) {
00309 rb_sys_fail(0);
00310 }
00311 }
00312 return fd;
00313 }
00314
00315 static VALUE io_alloc (VALUE);
00316 static VALUE
00317 io_alloc(klass)
00318 VALUE klass;
00319 {
00320 NEWOBJ(io, struct RFile);
00321 OBJSETUP(io, klass, T_FILE);
00322
00323 io->fptr = 0;
00324
00325 return (VALUE)io;
00326 }
00327
00328 static void
00329 io_fflush(f, fptr)
00330 FILE *f;
00331 OpenFile *fptr;
00332 {
00333 int n;
00334
00335 if (!rb_thread_fd_writable(fileno(f))) {
00336 rb_io_check_closed(fptr);
00337 }
00338 for (;;) {
00339 TRAP_BEG;
00340 n = fflush(f);
00341 TRAP_END;
00342 if (n != EOF) break;
00343 if (!rb_io_wait_writable(fileno(f)))
00344 rb_sys_fail(fptr->path);
00345 }
00346 fptr->mode &= ~FMODE_WBUF;
00347 }
00348
00349 int
00350 rb_io_wait_readable(f)
00351 int f;
00352 {
00353 fd_set rfds;
00354
00355 switch (errno) {
00356 case EINTR:
00357 #if defined(ERESTART)
00358 case ERESTART:
00359 #endif
00360 rb_thread_wait_fd(f);
00361 return Qtrue;
00362
00363 case EAGAIN:
00364 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
00365 case EWOULDBLOCK:
00366 #endif
00367 FD_ZERO(&rfds);
00368 FD_SET(f, &rfds);
00369 rb_thread_select(f + 1, &rfds, NULL, NULL, NULL);
00370 return Qtrue;
00371
00372 default:
00373 return Qfalse;
00374 }
00375 }
00376
00377 int
00378 rb_io_wait_writable(f)
00379 int f;
00380 {
00381 fd_set wfds;
00382
00383 switch (errno) {
00384 case EINTR:
00385 #if defined(ERESTART)
00386 case ERESTART:
00387 #endif
00388 rb_thread_fd_writable(f);
00389 return Qtrue;
00390
00391 case EAGAIN:
00392 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
00393 case EWOULDBLOCK:
00394 #endif
00395 FD_ZERO(&wfds);
00396 FD_SET(f, &wfds);
00397 rb_thread_select(f + 1, NULL, &wfds, NULL, NULL);
00398 return Qtrue;
00399
00400 default:
00401 return Qfalse;
00402 }
00403 }
00404
00405 #ifndef S_ISREG
00406 # define S_ISREG(m) ((m & S_IFMT) == S_IFREG)
00407 #endif
00408
00409 static int
00410 wsplit_p(OpenFile *fptr)
00411 {
00412 FILE *f = GetWriteFile(fptr);
00413 int r;
00414 if (!(fptr->mode & FMODE_WSPLIT_INITIALIZED)) {
00415 struct stat buf;
00416 if (fstat(fileno(f), &buf) == 0 &&
00417 !S_ISREG(buf.st_mode)
00418 #if defined(HAVE_FCNTL) && defined(F_GETFL) && defined(O_NONBLOCK)
00419 && (r = fcntl(fileno(f), F_GETFL)) != -1 &&
00420 !(r & O_NONBLOCK)
00421 #endif
00422 ) {
00423 fptr->mode |= FMODE_WSPLIT;
00424 }
00425 fptr->mode |= FMODE_WSPLIT_INITIALIZED;
00426 }
00427 return fptr->mode & FMODE_WSPLIT;
00428 }
00429
00430
00431 static long
00432 io_fwrite(str, fptr)
00433 VALUE str;
00434 OpenFile *fptr;
00435 {
00436 long len, n, r, l, offset = 0;
00437 FILE *f = GetWriteFile(fptr);
00438
00439 len = RSTRING(str)->len;
00440 if ((n = len) <= 0) return n;
00441 if (fptr->mode & FMODE_SYNC) {
00442 io_fflush(f, fptr);
00443 if (!rb_thread_fd_writable(fileno(f))) {
00444 rb_io_check_closed(fptr);
00445 }
00446 retry:
00447 l = n;
00448 if (PIPE_BUF < l &&
00449 !rb_thread_critical &&
00450 !rb_thread_alone() &&
00451 wsplit_p(fptr)) {
00452 l = PIPE_BUF;
00453 }
00454 TRAP_BEG;
00455 r = write(fileno(f), RSTRING(str)->ptr+offset, l);
00456 TRAP_END;
00457 if (r == n) return len;
00458 if (0 <= r) {
00459 offset += r;
00460 n -= r;
00461 errno = EAGAIN;
00462 }
00463 if (rb_io_wait_writable(fileno(f))) {
00464 rb_io_check_closed(fptr);
00465 if (offset < RSTRING(str)->len)
00466 goto retry;
00467 }
00468 return -1L;
00469 }
00470 #if defined(__human68k__) || defined(__vms)
00471 do {
00472 if (fputc(RSTRING(str)->ptr[offset++], f) == EOF) {
00473 if (ferror(f)) return -1L;
00474 break;
00475 }
00476 } while (--n > 0);
00477 #else
00478 while (errno = 0, offset += (r = fwrite(RSTRING(str)->ptr+offset, 1, n, f)), (n -= r) > 0) {
00479 if (ferror(f)
00480 #if defined __BORLANDC__
00481 || errno
00482 #endif
00483 ) {
00484 #ifdef __hpux
00485 if (!errno) errno = EAGAIN;
00486 #elif defined(_WIN32) && !defined(__BORLANDC__)
00487
00488 if (!errno) {
00489 if (GetLastError() == ERROR_NO_DATA)
00490 errno = EPIPE;
00491 else
00492 errno = EBADF;
00493 }
00494 #endif
00495 if (rb_io_wait_writable(fileno(f))) {
00496 rb_io_check_closed(fptr);
00497 clearerr(f);
00498 if (offset < RSTRING(str)->len)
00499 continue;
00500 }
00501 return -1L;
00502 }
00503 }
00504 #endif
00505 return len - n;
00506 }
00507
00508 long
00509 rb_io_fwrite(ptr, len, f)
00510 const char *ptr;
00511 long len;
00512 FILE *f;
00513 {
00514 OpenFile of;
00515
00516 of.f = f;
00517 of.f2 = NULL;
00518 of.mode = FMODE_WRITABLE;
00519 of.path = NULL;
00520 return io_fwrite(rb_str_new(ptr, len), &of);
00521 }
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541 static VALUE
00542 io_write(io, str)
00543 VALUE io, str;
00544 {
00545 OpenFile *fptr;
00546 long n;
00547
00548 rb_secure(4);
00549 if (TYPE(str) != T_STRING)
00550 str = rb_obj_as_string(str);
00551
00552 if (TYPE(io) != T_FILE) {
00553
00554 return rb_funcall(io, id_write, 1, str);
00555 }
00556 if (RSTRING(str)->len == 0) return INT2FIX(0);
00557
00558 GetOpenFile(io, fptr);
00559 rb_io_check_writable(fptr);
00560
00561 n = io_fwrite(str, fptr);
00562 if (n == -1L) rb_sys_fail(fptr->path);
00563 if (!(fptr->mode & FMODE_SYNC)) {
00564 fptr->mode |= FMODE_WBUF;
00565 }
00566
00567 return LONG2FIX(n);
00568 }
00569
00570 VALUE
00571 rb_io_write(io, str)
00572 VALUE io, str;
00573 {
00574 return rb_funcall(io, id_write, 1, str);
00575 }
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592 VALUE
00593 rb_io_addstr(io, str)
00594 VALUE io, str;
00595 {
00596 rb_io_write(io, str);
00597 return io;
00598 }
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616 static VALUE
00617 rb_io_flush(io)
00618 VALUE io;
00619 {
00620 OpenFile *fptr;
00621 FILE *f;
00622
00623 GetOpenFile(io, fptr);
00624 rb_io_check_writable(fptr);
00625 f = GetWriteFile(fptr);
00626
00627 io_fflush(f, fptr);
00628
00629 return io;
00630 }
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645 static VALUE
00646 rb_io_tell(io)
00647 VALUE io;
00648 {
00649 OpenFile *fptr;
00650 off_t pos;
00651
00652 GetOpenFile(io, fptr);
00653 pos = io_tell(fptr);
00654 if (pos < 0) rb_sys_fail(fptr->path);
00655 return OFFT2NUM(pos);
00656 }
00657
00658 static VALUE
00659 rb_io_seek(io, offset, whence)
00660 VALUE io, offset;
00661 int whence;
00662 {
00663 OpenFile *fptr;
00664 off_t pos;
00665
00666 pos = NUM2OFFT(offset);
00667 GetOpenFile(io, fptr);
00668 pos = io_seek(fptr, pos, whence);
00669 if (pos < 0) rb_sys_fail(fptr->path);
00670 clearerr(fptr->f);
00671
00672 return INT2FIX(0);
00673 }
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696 static VALUE
00697 rb_io_seek_m(argc, argv, io)
00698 int argc;
00699 VALUE *argv;
00700 VALUE io;
00701 {
00702 VALUE offset, ptrname;
00703 int whence = SEEK_SET;
00704
00705 if (rb_scan_args(argc, argv, "11", &offset, &ptrname) == 2) {
00706 whence = NUM2INT(ptrname);
00707 }
00708
00709 return rb_io_seek(io, offset, whence);
00710 }
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723 static VALUE
00724 rb_io_set_pos(io, offset)
00725 VALUE io, offset;
00726 {
00727 OpenFile *fptr;
00728 off_t pos;
00729
00730 pos = NUM2OFFT(offset);
00731 GetOpenFile(io, fptr);
00732 pos = io_seek(fptr, pos, SEEK_SET);
00733 if (pos != 0) rb_sys_fail(fptr->path);
00734 clearerr(fptr->f);
00735
00736 return OFFT2NUM(pos);
00737 }
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753 static VALUE
00754 rb_io_rewind(io)
00755 VALUE io;
00756 {
00757 OpenFile *fptr;
00758
00759 GetOpenFile(io, fptr);
00760 if (io_seek(fptr, 0L, 0) != 0) rb_sys_fail(fptr->path);
00761 clearerr(fptr->f);
00762 if (io == current_file) {
00763 gets_lineno -= fptr->lineno;
00764 }
00765 fptr->lineno = 0;
00766
00767 return INT2FIX(0);
00768 }
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802 VALUE
00803 rb_io_eof(io)
00804 VALUE io;
00805 {
00806 OpenFile *fptr;
00807 int ch;
00808
00809 GetOpenFile(io, fptr);
00810 rb_io_check_readable(fptr);
00811
00812 if (feof(fptr->f)) return Qtrue;
00813 if (READ_DATA_PENDING(fptr->f)) return Qfalse;
00814 READ_CHECK(fptr->f);
00815 clearerr(fptr->f);
00816 TRAP_BEG;
00817 ch = getc(fptr->f);
00818 TRAP_END;
00819
00820 if (ch != EOF) {
00821 ungetc(ch, fptr->f);
00822 return Qfalse;
00823 }
00824 rb_io_check_closed(fptr);
00825 clearerr(fptr->f);
00826 return Qtrue;
00827 }
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842 static VALUE
00843 rb_io_sync(io)
00844 VALUE io;
00845 {
00846 OpenFile *fptr;
00847
00848 GetOpenFile(io, fptr);
00849 return (fptr->mode & FMODE_SYNC) ? Qtrue : Qfalse;
00850 }
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867 static VALUE
00868 rb_io_set_sync(io, mode)
00869 VALUE io, mode;
00870 {
00871 OpenFile *fptr;
00872
00873 GetOpenFile(io, fptr);
00874 if (RTEST(mode)) {
00875 fptr->mode |= FMODE_SYNC;
00876 }
00877 else {
00878 fptr->mode &= ~FMODE_SYNC;
00879 }
00880 return mode;
00881 }
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895 static VALUE
00896 rb_io_fsync(io)
00897 VALUE io;
00898 {
00899 #ifdef HAVE_FSYNC
00900 OpenFile *fptr;
00901 FILE *f;
00902
00903 GetOpenFile(io, fptr);
00904 f = GetWriteFile(fptr);
00905
00906 io_fflush(f, fptr);
00907 if (fsync(fileno(f)) < 0)
00908 rb_sys_fail(fptr->path);
00909 return INT2FIX(0);
00910 #else
00911 rb_notimplement();
00912 return Qnil;
00913 #endif
00914 }
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928 static VALUE
00929 rb_io_fileno(io)
00930 VALUE io;
00931 {
00932 OpenFile *fptr;
00933 int fd;
00934
00935 GetOpenFile(io, fptr);
00936 fd = fileno(fptr->f);
00937 return INT2FIX(fd);
00938 }
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960 static VALUE
00961 rb_io_pid(io)
00962 VALUE io;
00963 {
00964 OpenFile *fptr;
00965
00966 GetOpenFile(io, fptr);
00967 if (!fptr->pid)
00968 return Qnil;
00969 return INT2FIX(fptr->pid);
00970 }
00971
00972
00973
00974
00975
00976
00977
00978
00979 static VALUE
00980 rb_io_inspect(obj)
00981 VALUE obj;
00982 {
00983 OpenFile *fptr;
00984 char *buf, *cname, *st = "";
00985 long len;
00986
00987 fptr = RFILE(rb_io_taint_check(obj))->fptr;
00988 if (!fptr || !fptr->path) return rb_any_to_s(obj);
00989 cname = rb_obj_classname(obj);
00990 len = strlen(cname) + strlen(fptr->path) + 5;
00991 if (!(fptr->f || fptr->f2)) {
00992 st = " (closed)";
00993 len += 9;
00994 }
00995 buf = ALLOCA_N(char, len);
00996 snprintf(buf, len, "#<%s:%s%s>", cname, fptr->path, st);
00997 return rb_str_new2(buf);
00998 }
00999
01000
01001
01002
01003
01004
01005
01006
01007 static VALUE
01008 rb_io_to_io(io)
01009 VALUE io;
01010 {
01011 return io;
01012 }
01013
01014
01015 static long
01016 read_buffered_data(ptr, len, f)
01017 char *ptr;
01018 long len;
01019 FILE *f;
01020 {
01021 long n;
01022
01023 #ifdef READ_DATA_PENDING_COUNT
01024 n = READ_DATA_PENDING_COUNT(f);
01025 if (n <= 0) return 0;
01026 if (n > len) n = len;
01027 return fread(ptr, 1, n, f);
01028 #else
01029 int c;
01030
01031 for (n = 0; n < len && READ_DATA_PENDING(f) && (c = getc(f)) != EOF; ++n) {
01032 *ptr++ = c;
01033 }
01034 return n;
01035 #endif
01036 }
01037
01038 long
01039 io_fread(ptr, len, fptr)
01040 char *ptr;
01041 long len;
01042 OpenFile *fptr;
01043 {
01044 long n = len;
01045 int c;
01046 int saved_errno;
01047
01048 while (n > 0) {
01049 c = read_buffered_data(ptr, n, fptr->f);
01050 if (c < 0) goto eof;
01051 if (c > 0) {
01052 ptr += c;
01053 if ((n -= c) <= 0) break;
01054 }
01055 rb_thread_wait_fd(fileno(fptr->f));
01056 rb_io_check_closed(fptr);
01057 clearerr(fptr->f);
01058 TRAP_BEG;
01059 c = getc(fptr->f);
01060 TRAP_END;
01061 if (c == EOF) {
01062 eof:
01063 if (ferror(fptr->f)) {
01064 switch (errno) {
01065 case EINTR:
01066 #if defined(ERESTART)
01067 case ERESTART:
01068 #endif
01069 clearerr(fptr->f);
01070 continue;
01071 case EAGAIN:
01072 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
01073 case EWOULDBLOCK:
01074 #endif
01075 if (len > n) {
01076 clearerr(fptr->f);
01077 }
01078 saved_errno = errno;
01079 rb_warning("nonblocking IO#read is obsolete; use IO#readpartial or IO#sysread");
01080 errno = saved_errno;
01081 }
01082 if (len == n) return 0;
01083 }
01084 break;
01085 }
01086 *ptr++ = c;
01087 n--;
01088 }
01089 return len - n;
01090 }
01091
01092 long
01093 rb_io_fread(ptr, len, f)
01094 char *ptr;
01095 long len;
01096 FILE *f;
01097 {
01098 OpenFile of;
01099
01100 of.f = f;
01101 of.f2 = NULL;
01102 return io_fread(ptr, len, &of);
01103 }
01104
01105 #define SMALLBUF 100
01106
01107 static long
01108 remain_size(fptr)
01109 OpenFile *fptr;
01110 {
01111 struct stat st;
01112 off_t siz = BUFSIZ;
01113 off_t pos;
01114
01115 if (feof(fptr->f)) return 0;
01116 if (fstat(fileno(fptr->f), &st) == 0 && S_ISREG(st.st_mode)
01117 #ifdef __BEOS__
01118 && (st.st_dev > 3)
01119 #endif
01120 )
01121 {
01122 pos = io_tell(fptr);
01123 if (st.st_size >= pos && pos >= 0) {
01124 siz = st.st_size - pos + 1;
01125 if (siz > LONG_MAX) {
01126 rb_raise(rb_eIOError, "file too big for single read");
01127 }
01128 }
01129 }
01130 return (long)siz;
01131 }
01132
01133 static VALUE
01134 read_all(fptr, siz, str)
01135 OpenFile *fptr;
01136 long siz;
01137 VALUE str;
01138 {
01139 long bytes = 0;
01140 long n;
01141
01142 if (siz == 0) siz = BUFSIZ;
01143 if (NIL_P(str)) {
01144 str = rb_str_new(0, siz);
01145 }
01146 else {
01147 rb_str_resize(str, siz);
01148 }
01149 for (;;) {
01150 rb_str_locktmp(str);
01151 READ_CHECK(fptr->f);
01152 n = io_fread(RSTRING(str)->ptr+bytes, siz-bytes, fptr);
01153 rb_str_unlocktmp(str);
01154 if (n == 0 && bytes == 0) {
01155 if (!fptr->f) break;
01156 if (feof(fptr->f)) break;
01157 if (!ferror(fptr->f)) break;
01158 rb_sys_fail(fptr->path);
01159 }
01160 bytes += n;
01161 if (bytes < siz) break;
01162 siz += BUFSIZ;
01163 rb_str_resize(str, siz);
01164 }
01165 if (bytes != siz) rb_str_resize(str, bytes);
01166 OBJ_TAINT(str);
01167
01168 return str;
01169 }
01170
01171 static VALUE
01172 io_getpartial(int argc, VALUE *argv, VALUE io)
01173 {
01174 OpenFile *fptr;
01175 VALUE length, str;
01176 long n, len;
01177
01178 rb_scan_args(argc, argv, "11", &length, &str);
01179
01180 if ((len = NUM2LONG(length)) < 0) {
01181 rb_raise(rb_eArgError, "negative length %ld given", len);
01182 }
01183
01184 if (NIL_P(str)) {
01185 str = rb_str_new(0, len);
01186 }
01187 else {
01188 StringValue(str);
01189 rb_str_modify(str);
01190 rb_str_resize(str, len);
01191 }
01192 OBJ_TAINT(str);
01193
01194 GetOpenFile(io, fptr);
01195 rb_io_check_readable(fptr);
01196
01197 if (len == 0)
01198 return str;
01199
01200 READ_CHECK(fptr->f);
01201 if (RSTRING(str)->len != len) {
01202 modified:
01203 rb_raise(rb_eRuntimeError, "buffer string modified");
01204 }
01205 n = read_buffered_data(RSTRING(str)->ptr, len, fptr->f);
01206 if (n <= 0) {
01207 again:
01208 if (RSTRING(str)->len != len) goto modified;
01209 TRAP_BEG;
01210 n = read(fileno(fptr->f), RSTRING(str)->ptr, len);
01211 TRAP_END;
01212 if (n < 0) {
01213 if (rb_io_wait_readable(fileno(fptr->f)))
01214 goto again;
01215 rb_sys_fail(fptr->path);
01216 }
01217 }
01218 rb_str_resize(str, n);
01219
01220 if (n == 0)
01221 return Qnil;
01222 else
01223 return str;
01224 }
01225
01226
01227
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279 static VALUE
01280 io_readpartial(int argc, VALUE *argv, VALUE io)
01281 {
01282 VALUE ret;
01283
01284 ret = io_getpartial(argc, argv, io);
01285 if (NIL_P(ret))
01286 rb_eof_error();
01287 else
01288 return ret;
01289 }
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311 static VALUE
01312 io_read(argc, argv, io)
01313 int argc;
01314 VALUE *argv;
01315 VALUE io;
01316 {
01317 OpenFile *fptr;
01318 long n, len;
01319 VALUE length, str;
01320
01321 rb_scan_args(argc, argv, "02", &length, &str);
01322
01323 if (NIL_P(length)) {
01324 if (!NIL_P(str)) StringValue(str);
01325 GetOpenFile(io, fptr);
01326 rb_io_check_readable(fptr);
01327 return read_all(fptr, remain_size(fptr), str);
01328 }
01329 len = NUM2LONG(length);
01330 if (len < 0) {
01331 rb_raise(rb_eArgError, "negative length %ld given", len);
01332 }
01333
01334 if (NIL_P(str)) {
01335 str = rb_tainted_str_new(0, len);
01336 }
01337 else {
01338 StringValue(str);
01339 rb_str_modify(str);
01340 rb_str_resize(str,len);
01341 }
01342
01343 GetOpenFile(io, fptr);
01344 rb_io_check_readable(fptr);
01345 if (feof(fptr->f)) return Qnil;
01346 if (len == 0) return str;
01347
01348 rb_str_locktmp(str);
01349 READ_CHECK(fptr->f);
01350 if (RSTRING(str)->len != len) {
01351 rb_raise(rb_eRuntimeError, "buffer string modified");
01352 }
01353 n = io_fread(RSTRING(str)->ptr, len, fptr);
01354 rb_str_unlocktmp(str);
01355 if (n == 0) {
01356 if (!fptr->f) return Qnil;
01357 if (feof(fptr->f)) {
01358 rb_str_resize(str, 0);
01359 return Qnil;
01360 }
01361 if (len > 0) rb_sys_fail(fptr->path);
01362 }
01363 rb_str_resize(str, n);
01364 RSTRING(str)->len = n;
01365 RSTRING(str)->ptr[n] = '\0';
01366 OBJ_TAINT(str);
01367
01368 return str;
01369 }
01370
01371 static int
01372 appendline(fptr, delim, strp)
01373 OpenFile *fptr;
01374 int delim;
01375 VALUE *strp;
01376 {
01377 FILE *f = fptr->f;
01378 VALUE str = *strp;
01379 int c = EOF;
01380 #ifndef READ_DATA_PENDING_PTR
01381 char buf[8192];
01382 char *bp = buf, *bpe = buf + sizeof buf - 3;
01383 int update = Qfalse;
01384 #endif
01385
01386 do {
01387 #ifdef READ_DATA_PENDING_PTR
01388 long pending = READ_DATA_PENDING_COUNT(f);
01389 if (pending > 0) {
01390 const char *p = READ_DATA_PENDING_PTR(f);
01391 const char *e = memchr(p, delim, pending);
01392 long last = 0, len = (c != EOF);
01393 if (e) pending = e - p + 1;
01394 len += pending;
01395 if (!NIL_P(str)) {
01396 last = RSTRING(str)->len;
01397 rb_str_resize(str, last + len);
01398 }
01399 else {
01400 *strp = str = rb_str_buf_new(len);
01401 RSTRING(str)->len = len;
01402 RSTRING(str)->ptr[len] = '\0';
01403 }
01404 if (c != EOF) {
01405 RSTRING(str)->ptr[last++] = c;
01406 }
01407 fread(RSTRING(str)->ptr + last, 1, pending, f);
01408 if (e) return delim;
01409 }
01410 else if (c != EOF) {
01411 if (!NIL_P(str)) {
01412 char ch = c;
01413 rb_str_buf_cat(str, &ch, 1);
01414 }
01415 else {
01416 *strp = str = rb_str_buf_new(1);
01417 RSTRING(str)->ptr[RSTRING(str)->len++] = c;
01418 }
01419 }
01420 rb_thread_wait_fd(fileno(f));
01421 rb_io_check_closed(fptr);
01422 #else
01423 READ_CHECK(f);
01424 #endif
01425 clearerr(f);
01426 TRAP_BEG;
01427 c = getc(f);
01428 TRAP_END;
01429 if (c == EOF) {
01430 if (ferror(f)) {
01431 clearerr(f);
01432 if (!rb_io_wait_readable(fileno(f)))
01433 rb_sys_fail(fptr->path);
01434 continue;
01435 }
01436 #ifdef READ_DATA_PENDING_PTR
01437 return c;
01438 #endif
01439 }
01440 #ifndef READ_DATA_PENDING_PTR
01441 if (c == EOF || (*bp++ = c) == delim || bp == bpe) {
01442 int cnt = bp - buf;
01443
01444 if (cnt > 0) {
01445 if (!NIL_P(str))
01446 rb_str_cat(str, buf, cnt);
01447 else
01448 *strp = str = rb_str_new(buf, cnt);
01449 }
01450 if (c == EOF) {
01451 if (update)
01452 return (int)RSTRING(str)->ptr[RSTRING(str)->len-1];
01453 return c;
01454 }
01455 bp = buf;
01456 }
01457 update = Qtrue;
01458 #endif
01459 } while (c != delim);
01460
01461 #ifdef READ_DATA_PENDING_PTR
01462 {
01463 char ch = c;
01464 if (!NIL_P(str)) {
01465 rb_str_cat(str, &ch, 1);
01466 }
01467 else {
01468 *strp = str = rb_str_new(&ch, 1);
01469 }
01470 }
01471 #endif
01472
01473 return c;
01474 }
01475
01476 static inline int
01477 swallow(fptr, term)
01478 OpenFile *fptr;
01479 int term;
01480 {
01481 FILE *f = fptr->f;
01482 int c;
01483
01484 do {
01485 #ifdef READ_DATA_PENDING_PTR
01486 long cnt;
01487 while ((cnt = READ_DATA_PENDING_COUNT(f)) > 0) {
01488 char buf[1024];
01489 const char *p = READ_DATA_PENDING_PTR(f);
01490 int i;
01491 if (cnt > sizeof buf) cnt = sizeof buf;
01492 if (*p != term) return Qtrue;
01493 i = cnt;
01494 while (--i && *++p == term);
01495 if (!fread(buf, 1, cnt - i, f))
01496 rb_sys_fail(fptr->path);
01497 }
01498 rb_thread_wait_fd(fileno(f));
01499 rb_io_check_closed(fptr);
01500 #else
01501 READ_CHECK(f);
01502 #endif
01503 clearerr(f);
01504 TRAP_BEG;
01505 c = getc(f);
01506 TRAP_END;
01507 if (c != term) {
01508 ungetc(c, f);
01509 return Qtrue;
01510 }
01511 } while (c != EOF);
01512 return Qfalse;
01513 }
01514
01515 static VALUE
01516 rb_io_getline_fast(fptr, delim)
01517 OpenFile *fptr;
01518 unsigned char delim;
01519 {
01520 VALUE str = Qnil;
01521 int c;
01522
01523 while ((c = appendline(fptr, delim, &str)) != EOF && c != delim);
01524
01525 if (!NIL_P(str)) {
01526 fptr->lineno++;
01527 lineno = INT2FIX(fptr->lineno);
01528 OBJ_TAINT(str);
01529 }
01530
01531 return str;
01532 }
01533
01534 static int
01535 rscheck(rsptr, rslen, rs)
01536 char *rsptr;
01537 long rslen;
01538 VALUE rs;
01539 {
01540 if (RSTRING(rs)->ptr != rsptr && RSTRING(rs)->len != rslen)
01541 rb_raise(rb_eRuntimeError, "rs modified");
01542 return 1;
01543 }
01544
01545 static VALUE rb_io_getline(VALUE rs, VALUE io);
01546
01547 static VALUE
01548 rb_io_getline(rs, io)
01549 VALUE rs, io;
01550 {
01551 VALUE str = Qnil;
01552 OpenFile *fptr;
01553
01554 GetOpenFile(io, fptr);
01555 rb_io_check_readable(fptr);
01556 if (NIL_P(rs)) {
01557 str = read_all(fptr, 0, Qnil);
01558 if (RSTRING(str)->len == 0) return Qnil;
01559 }
01560 else if (rs == rb_default_rs) {
01561 return rb_io_getline_fast(fptr, '\n');
01562 }
01563 else {
01564 int c, newline;
01565 char *rsptr;
01566 long rslen;
01567 int rspara = 0;
01568
01569 rslen = RSTRING(rs)->len;
01570 if (rslen == 0) {
01571 rsptr = "\n\n";
01572 rslen = 2;
01573 rspara = 1;
01574 swallow(fptr, '\n');
01575 }
01576 else if (rslen == 1) {
01577 return rb_io_getline_fast(fptr, (unsigned char)RSTRING(rs)->ptr[0]);
01578 }
01579 else {
01580 rsptr = RSTRING(rs)->ptr;
01581 }
01582 newline = rsptr[rslen - 1];
01583
01584 while ((c = appendline(fptr, newline, &str)) != EOF &&
01585 (c != newline || RSTRING(str)->len < rslen ||
01586 (rspara || rscheck(rsptr,rslen,rs), 0) ||
01587 memcmp(RSTRING(str)->ptr+RSTRING(str)->len-rslen,rsptr,rslen)));
01588
01589 if (rspara) {
01590 if (c != EOF) {
01591 swallow(fptr, '\n');
01592 }
01593 }
01594 }
01595
01596 if (!NIL_P(str)) {
01597 fptr->lineno++;
01598 lineno = INT2FIX(fptr->lineno);
01599 OBJ_TAINT(str);
01600 }
01601
01602 return str;
01603 }
01604
01605 VALUE
01606 rb_io_gets(io)
01607 VALUE io;
01608 {
01609 OpenFile *fptr;
01610
01611 GetOpenFile(io, fptr);
01612 rb_io_check_readable(fptr);
01613 return rb_io_getline_fast(fptr, '\n');
01614 }
01615
01616
01617
01618
01619
01620
01621
01622
01623
01624
01625
01626
01627
01628
01629
01630
01631
01632
01633 static VALUE
01634 rb_io_gets_m(argc, argv, io)
01635 int argc;
01636 VALUE *argv;
01637 VALUE io;
01638 {
01639 VALUE rs, str;
01640
01641 if (argc == 0) {
01642 rs = rb_rs;
01643 }
01644 else {
01645 rb_scan_args(argc, argv, "1", &rs);
01646 if (!NIL_P(rs)) StringValue(rs);
01647 }
01648 str = rb_io_getline(rs, io);
01649 rb_lastline_set(str);
01650
01651 return str;
01652 }
01653
01654
01655
01656
01657
01658
01659
01660
01661
01662
01663
01664
01665
01666
01667
01668
01669
01670
01671
01672
01673 static VALUE
01674 rb_io_lineno(io)
01675 VALUE io;
01676 {
01677 OpenFile *fptr;
01678
01679 GetOpenFile(io, fptr);
01680 rb_io_check_readable(fptr);
01681 return INT2NUM(fptr->lineno);
01682 }
01683
01684
01685
01686
01687
01688
01689
01690
01691
01692
01693
01694
01695
01696
01697
01698
01699
01700
01701 static VALUE
01702 rb_io_set_lineno(io, lineno)
01703 VALUE io, lineno;
01704 {
01705 OpenFile *fptr;
01706
01707 GetOpenFile(io, fptr);
01708 rb_io_check_readable(fptr);
01709 fptr->lineno = NUM2INT(lineno);
01710 return lineno;
01711 }
01712
01713 static void
01714 lineno_setter(val, id, var)
01715 VALUE val;
01716 ID id;
01717 VALUE *var;
01718 {
01719 gets_lineno = NUM2INT(val);
01720 *var = INT2FIX(gets_lineno);
01721 }
01722
01723 static VALUE
01724 argf_set_lineno(argf, val)
01725 VALUE argf, val;
01726 {
01727 gets_lineno = NUM2INT(val);
01728 lineno = INT2FIX(gets_lineno);
01729 return Qnil;
01730 }
01731
01732 static VALUE
01733 argf_lineno()
01734 {
01735 return lineno;
01736 }
01737
01738
01739
01740
01741
01742
01743
01744
01745
01746 static VALUE
01747 rb_io_readline(argc, argv, io)
01748 int argc;
01749 VALUE *argv;
01750 VALUE io;
01751 {
01752 VALUE line = rb_io_gets_m(argc, argv, io);
01753
01754 if (NIL_P(line)) {
01755 rb_eof_error();
01756 }
01757 return line;
01758 }
01759
01760
01761
01762
01763
01764
01765
01766
01767
01768
01769
01770
01771
01772
01773
01774
01775 static VALUE
01776 rb_io_readlines(argc, argv, io)
01777 int argc;
01778 VALUE *argv;
01779 VALUE io;
01780 {
01781 VALUE line, ary;
01782 VALUE rs;
01783
01784 if (argc == 0) {
01785 rs = rb_rs;
01786 }
01787 else {
01788 rb_scan_args(argc, argv, "1", &rs);
01789 if