Main Page | Modules | Alphabetical List | Data Structures | File List | Data Fields | Globals

io.c

Go to the documentation of this file.
00001 /**********************************************************************
00002 
00003   io.c -
00004 
00005   $Author: akr $
00006   $Date: 2005/12/19 17:11:20 $
00007   created at: Fri Oct 15 18:08:59 JST 1993
00008 
00009   Copyright (C) 1993-2003 Yukihiro Matsumoto
00010   Copyright (C) 2000  Network Applied Communication Laboratory, Inc.
00011   Copyright (C) 2000  Information-technology Promotion Agency, Japan
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 /* EMX has sys/param.h, but.. */
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 /* is this ok? */
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;                /* rescue VIM plugin */
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  /* GNU libc */
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 /* requires systems own version of the ReadDataPending() */
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 /* writing functions */
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             /* workaround for MSVCRT's bug */
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  *  call-seq:
00525  *     ios.write(string)    => integer
00526  *  
00527  *  Writes the given string to <em>ios</em>. The stream must be opened
00528  *  for writing. If the argument is not a string, it will be converted
00529  *  to a string using <code>to_s</code>. Returns the number of bytes
00530  *  written.
00531  *     
00532  *     count = $stdout.write( "This is a test\n" )
00533  *     puts "That was #{count} bytes of data"
00534  *     
00535  *  <em>produces:</em>
00536  *     
00537  *     This is a test
00538  *     That was 15 bytes of data
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         /* port is not IO, call write method for it. */
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  *  call-seq:
00579  *     ios << obj     => ios
00580  *  
00581  *  String Output---Writes <i>obj</i> to <em>ios</em>.
00582  *  <i>obj</i> will be converted to a string using
00583  *  <code>to_s</code>.
00584  *     
00585  *     $stdout << "Hello " << "world!\n"
00586  *     
00587  *  <em>produces:</em>
00588  *     
00589  *     Hello world!
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  *  call-seq:
00602  *     ios.flush    => ios
00603  *  
00604  *  Flushes any buffered data within <em>ios</em> to the underlying
00605  *  operating system (note that this is Ruby internal buffering only;
00606  *  the OS may buffer the data as well).
00607  *     
00608  *     $stdout.print "no newline"
00609  *     $stdout.flush
00610  *     
00611  *  <em>produces:</em>
00612  *     
00613  *     no newline
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  *  call-seq:
00634  *     ios.pos     => integer
00635  *     ios.tell    => integer
00636  *  
00637  *  Returns the current offset (in bytes) of <em>ios</em>.
00638  *     
00639  *     f = File.new("testfile")
00640  *     f.pos    #=> 0
00641  *     f.gets   #=> "This is line one\n"
00642  *     f.pos    #=> 17
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  *  call-seq:
00677  *     ios.seek(amount, whence=SEEK_SET) -> 0
00678  *  
00679  *  Seeks to a given offset <i>anInteger</i> in the stream according to
00680  *  the value of <i>whence</i>:
00681  *
00682  *    IO::SEEK_CUR  | Seeks to _amount_ plus current position
00683  *    --------------+----------------------------------------------------
00684  *    IO::SEEK_END  | Seeks to _amount_ plus end of stream (you probably 
00685  *                  | want a negative value for _amount_)
00686  *    --------------+----------------------------------------------------
00687  *    IO::SEEK_SET  | Seeks to the absolute location given by _amount_
00688  *
00689  *  Example:
00690  *     
00691  *     f = File.new("testfile")
00692  *     f.seek(-13, IO::SEEK_END)   #=> 0
00693  *     f.readline                  #=> "And so on...\n"
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  *  call-seq:
00714  *     ios.pos = integer    => integer
00715  *  
00716  *  Seeks to the given position (in bytes) in <em>ios</em>.
00717  *     
00718  *     f = File.new("testfile")
00719  *     f.pos = 17
00720  *     f.gets   #=> "This is line two\n"
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  *  call-seq:
00741  *     ios.rewind    => 0
00742  *  
00743  *  Positions <em>ios</em> to the beginning of input, resetting
00744  *  <code>lineno</code> to zero.
00745  *     
00746  *     f = File.new("testfile")
00747  *     f.readline   #=> "This is line one\n"
00748  *     f.rewind     #=> 0
00749  *     f.lineno     #=> 0
00750  *     f.readline   #=> "This is line one\n"
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  *  call-seq:
00772  *     ios.eof     => true or false
00773  *     ios.eof?    => true or false
00774  *
00775  *  Returns true if <em>ios</em> is at end of file that means
00776  *  there are no more data to read.
00777  *  The stream must be opened for reading or an <code>IOError</code> will be
00778  *  raised.
00779  *
00780  *     f = File.new("testfile")
00781  *     dummy = f.readlines
00782  *     f.eof   #=> true
00783  *
00784  *  If <em>ios</em> is a stream such as pipe or socket, <code>IO#eof?</code>
00785  *  blocks until the other end sends some data or closes it.
00786  *
00787  *     r, w = IO.pipe
00788  *     Thread.new { sleep 1; w.close }
00789  *     r.eof?  #=> true after 1 second blocking
00790  *
00791  *     r, w = IO.pipe
00792  *     Thread.new { sleep 1; w.puts "a" }
00793  *     r.eof?  #=> false after 1 second blocking
00794  *
00795  *     r, w = IO.pipe
00796  *     r.eof?  # blocks forever
00797  *
00798  *  Note that <code>IO#eof?</code> reads data to a input buffer.
00799  *  So <code>IO#sysread</code> doesn't work with <code>IO#eof?</code>.
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  *  call-seq:
00831  *     ios.sync    => true or false
00832  *  
00833  *  Returns the current ``sync mode'' of <em>ios</em>. When sync mode is
00834  *  true, all output is immediately flushed to the underlying operating
00835  *  system and is not buffered by Ruby internally. See also
00836  *  <code>IO#fsync</code>.
00837  *     
00838  *     f = File.new("testfile")
00839  *     f.sync   #=> false
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  *  call-seq:
00854  *     ios.sync = boolean   => boolean
00855  *  
00856  *  Sets the ``sync mode'' to <code>true</code> or <code>false</code>.
00857  *  When sync mode is true, all output is immediately flushed to the
00858  *  underlying operating system and is not buffered internally. Returns
00859  *  the new state. See also <code>IO#fsync</code>.
00860  *     
00861  *     f = File.new("testfile")
00862  *     f.sync = true
00863  *     
00864  *  <em>(produces no output)</em>
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  *  call-seq:
00885  *     ios.fsync   => 0 or nil
00886  *  
00887  *  Immediately writes all buffered data in <em>ios</em> to disk.
00888  *  Returns <code>nil</code> if the underlying operating system does not
00889  *  support <em>fsync(2)</em>. Note that <code>fsync</code> differs from
00890  *  using <code>IO#sync=</code>. The latter ensures that data is flushed
00891  *  from Ruby's buffers, but doesn't not guarantee that the underlying
00892  *  operating system actually writes it to disk.
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;                /* not reached */
00913 #endif
00914 }
00915 
00916 /*
00917  *  call-seq:
00918  *     ios.fileno    => fixnum
00919  *     ios.to_i      => fixnum
00920  *  
00921  *  Returns an integer representing the numeric file descriptor for
00922  *  <em>ios</em>.
00923  *     
00924  *     $stdin.fileno    #=> 0
00925  *     $stdout.fileno   #=> 1
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  *  call-seq:
00942  *     ios.pid    => fixnum
00943  *  
00944  *  Returns the process ID of a child process associated with
00945  *  <em>ios</em>. This will be set by <code>IO::popen</code>.
00946  *     
00947  *     pipe = IO.popen("-")
00948  *     if pipe
00949  *       $stderr.puts "In parent, child pid is #{pipe.pid}"
00950  *     else
00951  *       $stderr.puts "In child, pid is #{$$}"
00952  *     end
00953  *     
00954  *  <em>produces:</em>
00955  *     
00956  *     In child, pid is 26209
00957  *     In parent, child pid is 26209
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  * call-seq:
00974  *   ios.inspect   => string
00975  *
00976  * Return a string describing this IO object.
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  *  call-seq:
01002  *     ios.to_io -> ios
01003  *  
01004  *  Returns <em>ios</em>.
01005  */
01006 
01007 static VALUE
01008 rb_io_to_io(io)
01009     VALUE io;
01010 {
01011     return io;
01012 }
01013 
01014 /* reading functions */
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  *  call-seq:
01228  *     ios.readpartial(maxlen[, outbuf])    => string, outbuf
01229  *
01230  *  Reads at most <i>maxlen</i> bytes from the I/O stream but
01231  *  it blocks only if <em>ios</em> has no data immediately available.
01232  *  If the optional <i>outbuf</i> argument is present,
01233  *  it must reference a String, which will receive the data.
01234  *  It raises <code>EOFError</code> on end of file.
01235  *
01236  *  readpartial is designed for streams such as pipe, socket, tty, etc.
01237  *  It blocks only when no data immediately available.
01238  *  This means that it blocks only when following all conditions hold.
01239  *  * the buffer in the IO object is empty.
01240  *  * the content of the stream is empty.
01241  *  * the stream is not reached to EOF.
01242  *
01243  *  When readpartial blocks, it waits data or EOF on the stream.
01244  *  If some data is reached, readpartial returns with the data.
01245  *  If EOF is reached, readpartial raises EOFError.
01246  *
01247  *  When readpartial doesn't blocks, it returns or raises immediately.
01248  *  If the buffer is not empty, it returns the data in the buffer.
01249  *  Otherwise if the stream has some content,
01250  *  it returns the data in the stream. 
01251  *  Otherwise if the stream is reached to EOF, it raises EOFError.
01252  *
01253  *     r, w = IO.pipe           #               buffer          pipe content
01254  *     w << "abc"               #               ""              "abc".
01255  *     r.readpartial(4096)      #=> "abc"       ""              ""
01256  *     r.readpartial(4096)      # blocks because buffer and pipe is empty.
01257  *
01258  *     r, w = IO.pipe           #               buffer          pipe content
01259  *     w << "abc"               #               ""              "abc"
01260  *     w.close                  #               ""              "abc" EOF
01261  *     r.readpartial(4096)      #=> "abc"       ""              EOF
01262  *     r.readpartial(4096)      # raises EOFError
01263  *
01264  *     r, w = IO.pipe           #               buffer          pipe content
01265  *     w << "abc\ndef\n"        #               ""              "abc\ndef\n"
01266  *     r.gets                   #=> "abc\n"     "def\n"         ""
01267  *     w << "ghi\n"             #               "def\n"         "ghi\n"
01268  *     r.readpartial(4096)      #=> "def\n"     ""              "ghi\n"
01269  *     r.readpartial(4096)      #=> "ghi\n"     ""              ""
01270  *
01271  *  Note that readpartial is nonblocking-flag insensitive.
01272  *  It blocks even if the nonblocking-flag is set.
01273  *
01274  *  Also note that readpartial behaves similar to sysread in blocking mode.
01275  *  The behavior is identical when the buffer is empty.
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  *  call-seq:
01293  *     ios.read([length [, buffer]])    => string, buffer, or nil
01294  *
01295  *  Reads at most <i>length</i> bytes from the I/O stream, or to the
01296  *  end of file if <i>length</i> is omitted or is <code>nil</code>.
01297  *  <i>length</i> must be a non-negative integer or nil.
01298  *  If the optional <i>buffer</i> argument is present, it must reference
01299  *  a String, which will receive the data.
01300  *
01301  *  At end of file, it returns <code>nil</code> or <code>""</code>
01302  *  depend on <i>length</i>.
01303  *  <code><i>ios</i>.read()</code> and
01304  *  <code><i>ios</i>.read(nil)</code> returns <code>""</code>.
01305  *  <code><i>ios</i>.read(<i>positive-integer</i>)</code> returns nil.
01306  *
01307  *     f = File.new("testfile")
01308  *     f.read(16)   #=> "This is line one"
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); /* must not fail */
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)) /* must not fail */
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  *  call-seq:
01618  *     ios.gets(sep_string=$/)   => string or nil
01619  *  
01620  *  Reads the next ``line'' from the I/O stream; lines are separated by
01621  *  <i>sep_string</i>. A separator of <code>nil</code> reads the entire
01622  *  contents, and a zero-length separator reads the input a paragraph at
01623  *  a time (two successive newlines in the input separate paragraphs).
01624  *  The stream must be opened for reading or an <code>IOError</code>
01625  *  will be raised. The line read in will be returned and also assigned
01626  *  to <code>$_</code>. Returns <code>nil</code> if called at end of
01627  *  file.
01628  *     
01629  *     File.new("testfile").gets   #=> "This is line one\n"
01630  *     $_                          #=> "This is line one\n"
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  *  call-seq:
01656  *     ios.lineno    => integer
01657  *  
01658  *  Returns the current line number in <em>ios</em>. The stream must be
01659  *  opened for reading. <code>lineno</code> counts the number of times
01660  *  <code>gets</code> is called, rather than the number of newlines
01661  *  encountered. The two values will differ if <code>gets</code> is
01662  *  called with a separator other than newline. See also the
01663  *  <code>$.</code> variable.
01664  *     
01665  *     f = File.new("testfile")
01666  *     f.lineno   #=> 0
01667  *     f.gets     #=> "This is line one\n"
01668  *     f.lineno   #=> 1
01669  *     f.gets     #=> "This is line two\n"
01670  *     f.lineno   #=> 2
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  *  call-seq:
01686  *     ios.lineno = integer    => integer
01687  *  
01688  *  Manually sets the current line number to the given value.
01689  *  <code>$.</code> is updated only on the next read.
01690  *     
01691  *     f = File.new("testfile")
01692  *     f.gets                     #=> "This is line one\n"
01693  *     $.                         #=> 1
01694  *     f.lineno = 1000
01695  *     f.lineno                   #=> 1000
01696  *     $. # lineno of last read   #=> 1
01697  *     f.gets                     #=> "This is line two\n"
01698  *     $. # lineno of last read   #=> 1001
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  *  call-seq:
01740  *     ios.readline(sep_string=$/)   => string
01741  *  
01742  *  Reads a line as with <code>IO#gets</code>, but raises an
01743  *  <code>EOFError</code> on end of file.
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  *  call-seq:
01762  *     ios.readlines(sep_string=$/)  =>   array
01763  *  
01764  *  Reads all of the lines in <em>ios</em>, and returns them in
01765  *  <i>anArray</i>. Lines are separated by the optional
01766  *  <i>sep_string</i>. If <i>sep_string</i> is <code>nil</code>, the
01767  *  rest of the stream is returned as a single record.
01768  *  The stream must be opened for reading or an
01769  *  <code>IOError</code> will be raised.
01770  *     
01771  *     f = File.new("testfile")
01772  *     f.readlines[0]   #=> "This is line one\n"
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