Change soft-fail to use the config, rather than env
[rbx.git] / kernel / core / io.rb
blobc9fb62c9efd134ac36d2b6fed4bb45ca204e981e
1 # depends on: class.rb
3 class IO
5   ivar_as_index :__ivars__ => 0, :descriptor => 1, :buffer => 2, :mode => 3
7   BufferSize = 8096
9   class Buffer < String
10     ivar_as_index :bytes => 0, :characters => 1, :encoding => 2, :data => 3, :hash => 4, :shared => 5
12     ##
13     # Create a buffer of +size+ bytes. The buffer contains an internal Channel
14     # object it uses to fill itself.
15     def initialize(size)
16       @data = ByteArray.new(size)
17       @bytes = 0
18       @characters = 0
19       @encoding = :buffer
21       @total = size
22       @channel = Channel.new
23     end
25     ##
26     # Block until the buffer receives more data
27     def process
28       @channel.receive
29     end
31     attr_reader :channel
33     ##
34     # Indicates how many bytes are left
35     def unused
36       @total - @bytes
37     end
39     ##
40     # Remove +count+ bytes from the front of the buffer and return them.
41     # All other bytes are moved up.
42     def shift_front(count)
43       count = @bytes if count > @bytes
45       str = String.buffer count
46       str.copy_from self, 0, count, 0
48       rest = @bytes - count
49       @data.move_bytes count, rest, 0
50       @bytes = rest
52       return str
53     end
55     ##
56     # Empty the contents of the Buffer into a String object and return it.
57     def as_str
58       str = String.buffer @bytes
59       str.copy_from self, 0, @bytes, 0
60       @bytes = 0
61       return str
62     end
64     def empty?
65       @bytes == 0
66     end
68     ##
69     # Indicates if the Buffer has no more room.
70     def full?
71       @total == @bytes
72     end
74     ##
75     # Empty the buffer.
76     def reset!
77       @bytes = 0
78     end
80     ##
81     # Fill the buffer from IO object +io+. The buffer requests +unused+
82     # bytes, but may not receive that many. Any new data causes this to
83     # return.
84     def fill_from(io)
85       Scheduler.send_on_readable @channel, io, self, unused()
86       obj = @channel.receive
87       if obj.kind_of? Class
88         raise IOError, "error occured while filling buffer (#{obj})"
89       end
91       io.eof! unless obj
93       return obj
94     end
96     def inspect # :nodoc:
97       "#<IO::Buffer:0x%x total=%p bytes=%p characters=%p data=%p>" % [
98         object_id, @total, @bytes, @characters, @data
99       ]
100     end
102     ##
103     # Match the buffer against Regexp +reg+, and remove bytes starting
104     # at the beginning of the buffer, up to the end of where the Regexp
105     # matched.
106     def clip_to(reg)
107       if m = reg.match(self)
108         idx = m.end(0)
109         return shift_front(idx)
110       else
111         nil
112       end
113     end
114   end
116   module Constants
117     F_GETFL  = Rubinius::RUBY_CONFIG['rbx.platform.fcntl.F_GETFL']
118     F_SETFL  = Rubinius::RUBY_CONFIG['rbx.platform.fcntl.F_SETFL']
119     ACCMODE  = Rubinius::RUBY_CONFIG['rbx.platform.fcntl.O_ACCMODE']
121     SEEK_SET = Rubinius::RUBY_CONFIG['rbx.platform.io.SEEK_SET']
122     SEEK_CUR = Rubinius::RUBY_CONFIG['rbx.platform.io.SEEK_CUR']
123     SEEK_END = Rubinius::RUBY_CONFIG['rbx.platform.io.SEEK_END']
125     RDONLY   = Rubinius::RUBY_CONFIG['rbx.platform.file.O_RDONLY']
126     WRONLY   = Rubinius::RUBY_CONFIG['rbx.platform.file.O_WRONLY']
127     RDWR     = Rubinius::RUBY_CONFIG['rbx.platform.file.O_RDWR']
129     CREAT    = Rubinius::RUBY_CONFIG['rbx.platform.file.O_CREAT']
130     EXCL     = Rubinius::RUBY_CONFIG['rbx.platform.file.O_EXCL']
131     NOCTTY   = Rubinius::RUBY_CONFIG['rbx.platform.file.O_NOCTTY']
132     TRUNC    = Rubinius::RUBY_CONFIG['rbx.platform.file.O_TRUNC']
133     APPEND   = Rubinius::RUBY_CONFIG['rbx.platform.file.O_APPEND']
134     NONBLOCK = Rubinius::RUBY_CONFIG['rbx.platform.file.O_NONBLOCK']
135     SYNC     = Rubinius::RUBY_CONFIG['rbx.platform.file.O_SYNC']
137     # TODO: these flags should probably be imported from Platform
138     LOCK_SH  = 0x01
139     LOCK_EX  = 0x02
140     LOCK_NB  = 0x04
141     LOCK_UN  = 0x08
142     BINARY   = 0x04
143   end
145   include Constants
147   def self.for_fd(fd = -1, mode = nil)
148     self.new(fd, mode)
149   end
151   def self.foreach(name, sep_string = $/, &block)
152     sep_string ||= ''
153     io = File.open(StringValue(name), 'r')
154     sep = StringValue(sep_string)
155     begin
156       while(line = io.gets(sep))
157         yield line
158       end
159     ensure
160       io.close
161     end
162   end
164   ##
165   # Creates a new IO object to access the existing stream referenced by the
166   # descriptor given. The stream is not copied in any way so anything done on
167   # one IO will affect any other IOs accessing the same descriptor.
168   #
169   # The mode string given must be compatible with the original one so going
170   # 'r' from 'w' cannot be done but it is possible to go from 'w+' to 'r', for
171   # example (since the stream is not being "widened".)
172   #
173   # The initialization will verify that the descriptor given is a valid one.
174   # Errno::EBADF will be raised if that is not the case. If the mode is
175   # incompatible, it will raise Errno::EINVAL instead.
176   def self.open(*args)
177     io = self.new(*args)
179     return io unless block_given?
181     begin
182       yield io
183     ensure
184       io.close rescue nil unless io.closed?
185     end
186   end
188   def self.parse_mode(mode)
189     ret = 0
191     case mode[0]
192     when ?r
193       ret |= RDONLY
194     when ?w
195       ret |= WRONLY | CREAT | TRUNC
196     when ?a
197       ret |= WRONLY | CREAT | APPEND
198     else
199       raise ArgumentError, "invalid mode -- #{mode}"
200     end
202     return ret if mode.length == 1
204     case mode[1]
205     when ?+
206       ret &= ~(RDONLY | WRONLY)
207       ret |= RDWR
208     when ?b
209       ret |= BINARY
210     else
211       raise ArgumentError, "invalid mode -- #{mode}"
212     end
214     return ret if mode.length == 2
216     case mode[2]
217     when ?+
218       ret &= ~(RDONLY | WRONLY)
219       ret |= RDWR
220     when ?b
221       ret |= BINARY
222     else
223       raise ArgumentError, "invalid mode -- #{mode}"
224     end
226     ret
227   end
229   ##
230   # Creates a pair of pipe endpoints (connected to each other)
231   # and returns them as a two-element array of IO objects:
232   # [ read_file, write_file ]. Not available on all platforms.
233   #
234   # In the example below, the two processes close the ends of 
235   # the pipe that they are not using. This is not just a cosmetic
236   # nicety. The read end of a pipe will not generate an end of
237   # file condition if there are any writers with the pipe still
238   # open. In the case of the parent process, the rd.read will
239   # never return if it does not first issue a wr.close.
240   #
241   #  rd, wr = IO.pipe
242   #
243   #  if fork
244   #    wr.close
245   #    puts "Parent got: <#{rd.read}>"
246   #    rd.close
247   #    Process.wait
248   #  else
249   #    rd.close
250   #    puts "Sending message to parent"
251   #    wr.write "Hi Dad"
252   #    wr.close
253   #  end
254   # produces:
255   #
256   #  Sending message to parent
257   #  Parent got: <Hi Dad>
258   def self.pipe
259     lhs = IO.allocate
260     rhs = IO.allocate
261     out = create_pipe(lhs, rhs)
262     lhs.setup
263     rhs.setup
264     return [lhs, rhs]
265   end
267   ## 
268   # Runs the specified command string as a subprocess;
269   # the subprocess‘s standard input and output will be
270   # connected to the returned IO object. If cmd_string
271   # starts with a ``-’’, then a new instance of Ruby is
272   # started as the subprocess. The default mode for the
273   # new file object is ``r’’, but mode may be set to any
274   # of the modes listed in the description for class IO.
275   #
276   # If a block is given, Ruby will run the command as a
277   # child connected to Ruby with a pipe. Ruby‘s end of
278   # the pipe will be passed as a parameter to the block. 
279   # At the end of block, Ruby close the pipe and sets $?.
280   # In this case IO::popen returns the value of the block.
281   # 
282   # If a block is given with a cmd_string of ``-’’, the
283   # block will be run in two separate processes: once in
284   # the parent, and once in a child. The parent process
285   # will be passed the pipe object as a parameter to the
286   # block, the child version of the block will be passed
287   # nil, and the child‘s standard in and standard out will
288   # be connected to the parent through the pipe.
289   # Not available on all platforms.
290   #
291   #  f = IO.popen("uname")
292   #  p f.readlines
293   #  puts "Parent is #{Process.pid}"
294   #  IO.popen ("date") { |f| puts f.gets }
295   #  IO.popen("-") {|f| $stderr.puts "#{Process.pid} is here, f is #{f}"}
296   #  p $?
297   # produces:
298   # 
299   #  ["Linux\n"]
300   #  Parent is 26166
301   #  Wed Apr  9 08:53:52 CDT 2003
302   #  26169 is here, f is
303   #  26166 is here, f is #<IO:0x401b3d44>
304   #  #<Process::Status: pid=26166,exited(0)>
305   def self.popen(str, mode = "r")
306     if str == "+-+" and !block_given?
307       raise ArgumentError, "this mode requires a block currently"
308     end
310     mode = parse_mode mode
312     readable = false
313     writable = false
315     if mode & IO::RDWR != 0 then
316       readable = true
317       writable = true
318     elsif mode & IO::WRONLY != 0 then
319       writable = true
320     else # IO::RDONLY
321       readable = true
322     end
324     pa_read, ch_write = IO.pipe if readable
325     ch_read, pa_write = IO.pipe if writable
327     pid = Process.fork do
328       if readable then
329         pa_read.close
330         STDOUT.reopen ch_write
331       end
333       if writable then
334         pa_write.close
335         STDIN.reopen ch_read
336       end
338       if str == "+-+"
339         yield nil
340       else
341         Process.replace "/bin/sh", ["sh", "-c", str]
342       end
343     end
345     ch_write.close if readable
346     ch_read.close  if writable
348     # See bottom for definition
349     pipe = IO::BidirectionalPipe.new pid, pa_read, pa_write
351     if block_given? then
352       begin
353         yield pipe
354       ensure
355         pipe.close
356       end
357     else
358       return pipe
359     end
360   end
362   ##
363   # Opens the file, optionally seeks to the given offset,
364   # then returns length bytes (defaulting to the rest of
365   # the file). read ensures the file is closed before returning.
366   #
367   #  IO.read("testfile")           #=> "This is line one\nThis is line two\nThis is line three\nAnd so on...\n"
368   #  IO.read("testfile", 20)       #=> "This is line one\nThi"
369   #  IO.read("testfile", 20, 10)   #=> "ne one\nThis is line "
370   def self.read(name, length = Undefined, offset = 0)
371     name = StringValue(name)
372     length ||= Undefined
373     offset ||= 0
375     offset = Type.coerce_to(offset, Fixnum, :to_int)
377     if offset < 0
378       raise Errno::EINVAL, "offset must not be negative"
379     end
381     unless length.equal?(Undefined)
382       length = Type.coerce_to(length, Fixnum, :to_int)
384       if length < 0
385         raise ArgumentError, "length must not be negative"
386       end
387     end
389     File.open(name) do |f|
390       f.seek(offset) unless offset.zero?
392       if length.equal?(Undefined)
393         f.read
394       else
395         f.read(length)
396       end
397     end
398   end
400   ## 
401   # Reads the entire file specified by name as individual
402   # lines, and returns those lines in an array. Lines are
403   # separated by sep_string.
404   #
405   #  a = IO.readlines("testfile")
406   #  a[0]   #=> "This is line one\n"
407   def self.readlines(name, sep_string = $/)
408     io = File.open(StringValue(name), 'r')
409     return if io.nil?
411     begin
412       io.readlines(sep_string)
413     ensure
414       io.close
415     end
416   end
418   ##
419   # Select() examines the I/O descriptor sets who are passed in
420   # +read_array+, +write_array+, and +error_array+ to see if some of their descriptors are
421   # ready for reading, are ready for writing, or have an exceptions pending.
422   #
423   # If +timeout+ is not nil, it specifies a maximum interval to wait
424   # for the selection to complete. If timeout is nil, the select
425   # blocks indefinitely.
426   # 
427   # +write_array+, +error_array+, and +timeout+ may be left as nil if they are
428   # unimportant
429   def self.select(read_array, write_array = nil, error_array = nil,
430                   timeout = nil)
431     chan = Channel.new
433     if read_array then
434       read_array.each do |readable|
435         Scheduler.send_on_readable chan, readable, nil, nil
436       end
437     end
439     raise NotImplementedError, "write_array is not supported" if write_array
440     raise NotImplementedError, "error_array is not supported" if error_array
442     # HACK can't do this yet
443     #if write_array then
444     #  write_array.each do |writable|
445     #    Scheduler.send_on_writable chan, writable, nil, nil
446     #  end
447     #end
448     #
449     #if error_array then
450     #  error_array.each do |errorable|
451     #    Scheduler.send_on_error chan, errorable, nil, nil
452     #  end
453     #end
455     Scheduler.send_in_microseconds chan, (timeout * 1_000_000).to_i, nil if timeout
457     value = chan.receive
459     return nil if value == 1 # timeout
461     io = read_array.find { |readable| readable.fileno == value }
463     return nil if io.nil?
465     [[io], [], []]
466   end
468   ##
469   # Opens the given path, returning the underlying file descriptor as a Fixnum.
470   #  IO.sysopen("testfile")   #=> 3
471   def self.sysopen(path, mode = "r", perm = 0666)
472     if mode.kind_of?(String)
473       mode = parse_mode(mode)
474     end
476     return open_with_mode(path, mode, perm)
477   end
479   def initialize(fd, mode = nil)
480     fd = Type.coerce_to fd, Integer, :to_int
482     # Descriptor must be an open and valid one
483     raise Errno::EBADF, "Invalid descriptor #{fd}" if fd < 0
485     cur_mode = Platform::POSIX.fcntl(fd, F_GETFL, 0)
486     raise Errno::EBADF, "Invalid descriptor #{fd}" if cur_mode < 0
488     unless mode.nil?
489       # Must support the desired mode.
490       # O_ACCMODE is /undocumented/ for fcntl() on some platforms
491       # but it should work. If there is a problem, check it though.
492       new_mode = IO.parse_mode(mode) & ACCMODE
493       cur_mode = cur_mode & ACCMODE
495       if cur_mode != RDWR and cur_mode != new_mode
496         raise Errno::EINVAL, "Invalid mode '#{mode}' for existing descriptor #{fd}"
497       end
498     end
500     setup fd, mode
501   end
503   ##
504   # Obtains a new duplicate descriptor for the current one.
505   def initialize_copy(original) # :nodoc:
506     @descriptor = Platform::POSIX.dup(@descriptor)
507   end
509   private :initialize_copy
511   def setup(desc = nil, mode = nil)
512     @descriptor = desc if desc
513     @mode = mode if mode
514     @buffer = IO::Buffer.new(BufferSize)
515     @eof = false
516     @lineno = 0
517   end
519   def <<(obj)
520     write(obj.to_s)
521     return self
522   end
524   def __ivars__ ; @__ivars__  ; end
526   ##
527   # Puts ios into binary mode. This is useful only in
528   # MS-DOS/Windows environments. Once a stream is in
529   # binary mode, it cannot be reset to nonbinary mode.
530   def binmode
531     # HACK what to do?
532   end
534   def breadall(buffer=nil)
535     return "" if @eof and @buffer.empty?
537     output = ''
539     buf = @buffer
541     while true
542       bytes = buf.fill_from(self)
544       if !bytes or buf.full?
545         output << buf
546         buf.reset!
547       end
549       break unless bytes
550     end
552     if buffer then
553       buffer = StringValue buffer
554       buffer.replace output
555     else
556       buffer = output
557     end
559     buffer
560   end
562   ##
563   # Closes the read end of a duplex I/O stream (i.e., one
564   # that contains both a read and a write stream, such as
565   # a pipe). Will raise an IOError if the stream is not duplexed.
566   #
567   #  f = IO.popen("/bin/sh","r+")
568   #  f.close_read
569   #  f.readlines
570   # produces:
571   #
572   #  prog.rb:3:in `readlines': not opened for reading (IOError)
573   #   from prog.rb:3
574   def close_read
575     # TODO raise IOError if writable
576     close
577   end
579   ##
580   # Closes the write end of a duplex I/O stream (i.e., one
581   # that contains both a read and a write stream, such as
582   # a pipe). Will raise an IOError if the stream is not duplexed.
583   #
584   #  f = IO.popen("/bin/sh","r+")
585   #  f.close_write
586   #  f.print "nowhere"
587   # produces:
588   #
589   #  prog.rb:3:in `write': not opened for writing (IOError)
590   #   from prog.rb:3:in `print'
591   #   from prog.rb:3
592   def close_write
593     # TODO raise IOError if readable
594     close
595   end
597   ##
598   # Returns true if ios is completely closed (for duplex
599   # streams, both reader and writer), false otherwise.
600   #
601   #  f = File.new("testfile")
602   #  f.close         #=> nil
603   #  f.closed?       #=> true
604   #  f = IO.popen("/bin/sh","r+")
605   #  f.close_write   #=> nil
606   #  f.closed?       #=> false
607   #  f.close_read    #=> nil
608   #  f.closed?       #=> true
609   def closed?
610     @descriptor == -1
611   end
613   def descriptor
614     @descriptor
615   end
617   def dup
618     raise IOError, "closed stream" if closed?
619     super
620   end
622   ##
623   # Executes the block for every line in ios, where
624   # lines are separated by sep_string. ios must be
625   # opened for reading or an IOError will be raised.
626   #
627   #  f = File.new("testfile")
628   #  f.each {|line| puts "#{f.lineno}: #{line}" }
629   # produces:
630   #
631   #  1: This is line one
632   #  2: This is line two
633   #  3: This is line three
634   #  4: And so on...
635   def each(sep=$/)
636     while line = gets_helper(sep)
637       yield line
638     end
639   end
641   alias_method :each_line, :each
643   def each_byte
644     yield getc until eof?
646     self
647   end
649   ##
650   # Set the pipe so it is at the end of the file
651   def eof!
652     @eof = true
653   end
655   ##
656   # Returns true if ios is at end of file that means
657   # there are no more data to read. The stream must be
658   # opened for reading or an IOError will be raised.
659   #
660   #  f = File.new("testfile")
661   #  dummy = f.readlines
662   #  f.eof   #=> true
663   # If ios is a stream such as pipe or socket, IO#eof? 
664   # blocks until the other end sends some data or closes it.
665   #
666   #  r, w = IO.pipe
667   #  Thread.new { sleep 1; w.close }
668   #  r.eof?  #=> true after 1 second blocking
669   #
670   #  r, w = IO.pipe
671   #  Thread.new { sleep 1; w.puts "a" }
672   #  r.eof?  #=> false after 1 second blocking
673   #
674   #  r, w = IO.pipe
675   #  r.eof?  # blocks forever
676   # Note that IO#eof? reads data to a input buffer. So IO#sysread doesn‘t work with IO#eof?.
677   def eof?
678     read 0 # HACK force check
679     @eof and @buffer.empty?
680   end
682   alias_method :eof, :eof?
684   ##
685   # Provides a mechanism for issuing low-level commands to
686   # control or query file-oriented I/O streams. Arguments
687   # and results are platform dependent. If arg is a number,
688   # its value is passed directly. If it is a string, it is
689   # interpreted as a binary sequence of bytes (Array#pack
690   # might be a useful way to build this string). On Unix
691   # platforms, see fcntl(2) for details. Not implemented on all platforms.
692   def fcntl(command, arg=0)
693     raise IOError, "closed stream" if closed?
694     if arg.kind_of? Fixnum then
695       Platform::POSIX.fcntl(descriptor, command, arg)
696     else
697       raise NotImplementedError, "cannot handle #{arg.class}"
698     end
699   end
701   ##
702   # Returns an integer representing the numeric file descriptor for ios.
703   #
704   #  $stdin.fileno    #=> 0
705   #  $stdout.fileno   #=> 1
706   def fileno
707     raise IOError, "closed stream" if closed?
708     @descriptor
709   end
711   alias_method :to_i, :fileno
713   ##
714   # Flushes any buffered data within ios to the underlying
715   # operating system (note that this is Ruby internal 
716   # buffering only; the OS may buffer the data as well).
717   #
718   #  $stdout.print "no newline"
719   #  $stdout.flush
720   # produces:
721   #
722   #  no newline
723   def flush
724     raise IOError, "closed stream" if closed?
725     true
726   end
728   ##
729   # Immediately writes all buffered data in ios to disk. Returns
730   # nil if the underlying operating system does not support fsync(2).
731   # Note that fsync differs from using IO#sync=. The latter ensures
732   # that data is flushed from Ruby‘s buffers, but doesn‘t not guarantee
733   # that the underlying operating system actually writes it to disk.
734   def fsync
735     raise IOError, 'closed stream' if closed?
737     err = Platform::POSIX.fsync @descriptor
739     Errno.handle 'fsync(2)' if err < 0
741     err
742   end
744   ##
745   # Gets the next 8-bit byte (0..255) from ios.
746   # Returns nil if called at end of file.
747   #
748   #  f = File.new("testfile")
749   #  f.getc   #=> 84
750   #  f.getc   #=> 104
751   def getc
752     char = read 1
753     return nil if char.nil?
754     char[0]
755   end
757   ##
758   # Reads the next ``line’’ from the I/O stream;
759   # lines are separated by sep_string. A separator
760   # of nil reads the entire contents, and a zero-length 
761   # separator reads the input a paragraph at a time (two
762   # successive newlines in the input separate paragraphs).
763   # The stream must be opened for reading or an IOError
764   # will be raised. The line read in will be returned and
765   # also assigned to $_. Returns nil if called at end of file.
766   #
767   #  File.new("testfile").gets   #=> "This is line one\n"
768   #  $_                          #=> "This is line one\n"
769   def gets(sep=$/)
770     @lineno += 1
772     line = gets_helper sep
773     line.taint unless line.nil?
775     $_ = line
776     $. = @lineno
778     line
779   end
781   ##
782   #--
783   # Several methods use similar rules for reading strings from IO, but differ
784   # slightly. This helper is an extraction of the code.
786   def gets_helper(sep=$/)
787     raise IOError, "closed stream" if closed?
788     return nil if @eof and @buffer.empty?
790     return breadall() unless sep
792     buf = @buffer
794     if sep.empty?
795       return gets_stripped($/ + $/)
796     end
798     reg = /#{sep}/m
800     if str = buf.clip_to(reg)
801       return str
802     end
804     # Do an initial fill.
805     return nil if !buf.fill_from(self) and buf.empty?
807     output = nil
808     while true
809       if str = buf.clip_to(reg)
810         if output
811           return output + str
812         else
813           return str
814         end
815       end
817       if !buf.fill_from(self)
818         if buf.empty?
819           rest = nil
820         else
821           rest = buf.as_str
822         end
824         if output
825           if rest
826             return output << buf.as_str
827           else
828             return output
829           end
830         else
831           return rest
832         end
833       end
835       if buf.full?
836         if output
837           output << buf
838           buf.reset!
839         else
840           output = buf.as_str
841         end
842       end
843     end
844   end
846   def gets_stripped(sep)
847     buf = @buffer
849     if m = /^\n+/m.match(buf)
850       buf.shift_front(m.end(0)) if m.begin(0) == 0
851     end
853     str = gets_helper(sep)
855     if m = /^\n+/m.match(buf)
856       buf.shift_front(m.end(0)) if m.begin(0) == 0
857     end
859     return str
860   end
861   
862   ##
863   # Return a string describing this IO object.
864   def inspect
865     "#<#{self.class}:0x#{object_id.to_s(16)}>"
866   end
868   ##
869   # Returns the current line number in ios. The
870   # stream must be opened for reading. lineno
871   # counts the number of times gets is called,
872   # rather than the number of newlines encountered.
873   # The two values will differ if gets is called with
874   # a separator other than newline. See also the $. variable.
875   #
876   #  f = File.new("testfile")
877   #  f.lineno   #=> 0
878   #  f.gets     #=> "This is line one\n"
879   #  f.lineno   #=> 1
880   #  f.gets     #=> "This is line two\n"
881   #  f.lineno   #=> 2
882   def lineno
883     raise IOError, 'closed stream' if closed?
885     @lineno
886   end
888   ##
889   # Manually sets the current line number to the
890   # given value. $. is updated only on the next read.
891   #
892   #  f = File.new("testfile")
893   #  f.gets                     #=> "This is line one\n"
894   #  $.                         #=> 1
895   #  f.lineno = 1000
896   #  f.lineno                   #=> 1000
897   #  $. # lineno of last read   #=> 1
898   #  f.gets                     #=> "This is line two\n"
899   #  $. # lineno of last read   #=> 1001
900   def lineno=(line_number)
901     raise IOError, 'closed stream' if closed?
903     raise TypeError if line_number.nil?
905     @lineno = Integer line_number
906   end
908   ##
909   # FIXME
910   # Returns the process ID of a child process
911   # associated with ios. This will be set by IO::popen.
912   #
913   #  pipe = IO.popen("-")
914   #  if pipe
915   #    $stderr.puts "In parent, child pid is #{pipe.pid}"
916   #  else
917   #    $stderr.puts "In child, pid is #{$$}"
918   #  end
919   # produces:
920   #
921   #  In child, pid is 26209
922   #  In parent, child pid is 26209
923   def pid
924     nil
925   end
927   ##
928   # 
929   def pos
930     seek 0, SEEK_CUR
931   end
933   alias_method :tell, :pos
935   ##
936   # Seeks to the given position (in bytes) in ios.
937   #
938   #  f = File.new("testfile")
939   #  f.pos = 17
940   #  f.gets   #=> "This is line two\n"
941   def pos=(offset)
942     offset = Integer offset
944     seek offset, SEEK_SET
945   end
947   ##
948   # Writes each given argument.to_s to the stream or $_ (the result of last
949   # IO#gets) if called without arguments. Appends $\.to_s to output. Returns
950   # nil.
951   def print(*args)
952     if args.empty?
953       write $_.to_s
954     else
955       args.each {|o| write o.to_s }
956     end
958     write $\.to_s
959     nil
960   end
962   ##
963   # Formats and writes to ios, converting parameters under
964   # control of the format string. See Kernel#sprintf for details.
965   def printf(fmt, *args)
966     write Sprintf.new(fmt, *args).parse
967   end
969   ##
970   # If obj is Numeric, write the character whose code is obj,
971   # otherwise write the first character of the string
972   # representation of obj to ios.
973   #
974   #  $stdout.putc "A"
975   #  $stdout.putc 65
976   # produces:
977   #
978   #  AA
979   def putc(obj)
980     byte = if obj.__kind_of__ String then
981              obj[0]
982            else
983              Type.coerce_to(obj, Integer, :to_int) & 0xff
984            end
986     write byte.chr
987   end
989   ##
990   # Writes the given objects to ios as with IO#print.
991   # Writes a record separator (typically a newline)
992   # after any that do not already end with a newline
993   # sequence. If called with an array argument, writes 
994   # each element on a new line. If called without arguments,
995   # outputs a single record separator.
996   #
997   #  $stdout.puts("this", "is", "a", "test")
998   # produces:
999   #
1000   #  this
1001   #  is
1002   #  a
1003   #  test
1004   def puts(*args)
1005     if args.empty?
1006       write DEFAULT_RECORD_SEPARATOR
1007     else
1008       args.each do |arg|
1009         if arg.nil?
1010           str = "nil"
1011         elsif RecursionGuard.inspecting?(arg)
1012           str = "[...]"
1013         elsif arg.kind_of?(Array)
1014           RecursionGuard.inspect(arg) do
1015             arg.each do |a|
1016               puts a
1017             end
1018           end
1019         else
1020           str = arg.to_s
1021         end
1023         if str
1024           write str
1025           write DEFAULT_RECORD_SEPARATOR unless str.suffix?(DEFAULT_RECORD_SEPARATOR)
1026         end
1027       end
1028     end
1030     nil
1031   end
1033   ##
1034   # Reads at most length bytes from the I/O stream,
1035   # or to the end of file if length is omitted or is
1036   # nil. length must be a non-negative integer or nil.
1037   # If the optional buffer argument is present, it must
1038   # reference a String, which will receive the data.
1039   #
1040   # At end of file, it returns nil or "" depend on length.
1041   # ios.read() and ios.read(nil) returns "". ios.read(positive-integer) returns nil.
1042   #
1043   #  f = File.new("testfile")
1044   #  f.read(16)   #=> "This is line one"
1045   def read(size=nil, buffer=nil)
1046     raise IOError, "closed stream" if closed?
1047     return breadall(buffer) unless size
1049     return nil if @eof and @buffer.empty?
1051     buf = @buffer
1052     done = false
1054     output = ''
1056     needed = size
1058     if needed > 0 and buf.size >= needed
1059       output << buf.shift_front(needed)
1060     else
1061       while true
1062         bytes = buf.fill_from(self)
1064         if bytes
1065           done = needed - bytes <= 0
1066         else
1067           done = true
1068         end
1070         if done or buf.full?
1071           output << buf.shift_front(needed)
1072           needed = size - output.length
1073         end
1075         break if done or needed == 0
1076       end
1077     end
1079     if buffer then
1080       buffer = StringValue buffer
1081       buffer.replace output
1082     else
1083       buffer = output
1084     end
1086     buffer
1087   end
1089   ##
1090   # Reads at most maxlen bytes from ios using read(2) system
1091   # call after O_NONBLOCK is set for the underlying file descriptor.
1092   #
1093   # If the optional outbuf argument is present, it must reference
1094   # a String, which will receive the data.
1095   #
1096   # read_nonblock just calls read(2). It causes all errors read(2)
1097   # causes: EAGAIN, EINTR, etc. The caller should care such errors.
1098   #
1099   # read_nonblock causes EOFError on EOF.
1100   #
1101   # If the read buffer is not empty, read_nonblock reads from the
1102   # buffer like readpartial. In this case, read(2) is not called.
1103   def read_nonblock(size, buffer = nil)
1104     raise IOError, "closed stream" if closed?
1105     prim_read(size, buffer)
1106   end
1108   ##
1109   # Reads a character as with IO#getc, but raises an EOFError on end of file.
1110   def readchar
1111     char = getc
1113     raise EOFError, 'end of file reached' if char.nil?
1115     char
1116   end
1118   ##
1119   # Reads a line as with IO#gets, but raises an EOFError on end of file.
1120   def readline(sep=$/)
1121     out = gets(sep)
1122     raise EOFError, "end of file" unless out
1123     return out
1124   end
1126   ##
1127   # Reads all of the lines in ios, and returns them in an array.
1128   # Lines are separated by the optional sep_string. If sep_string
1129   # is nil, the rest of the stream is returned as a single record.
1130   # The stream must be opened for reading or an IOError will be raised.
1131   #
1132   #  f = File.new("testfile")
1133   #  f.readlines[0]   #=> "This is line one\n"
1134   def readlines(sep=$/)
1135     ary = Array.new
1136     while line = gets(sep)
1137       ary << line
1138     end
1139     return ary
1140   end
1142   ##
1143   # Reads at most maxlen bytes from the I/O stream. It blocks
1144   # only if ios has no data immediately available. It doesn‘t
1145   # block if some data available. If the optional outbuf argument
1146   # is present, it must reference a String, which will receive the
1147   # data. It raises EOFError on end of file.
1148   #
1149   # readpartial is designed for streams such as pipe, socket, tty,
1150   # etc. It blocks only when no data immediately available. This
1151   # means that it blocks only when following all conditions hold.
1152   #
1153   # the buffer in the IO object is empty.
1154   # the content of the stream is empty.
1155   # the stream is not reached to EOF.
1156   # When readpartial blocks, it waits data or EOF on the stream.
1157   # If some data is reached, readpartial returns with the data.
1158   # If EOF is reached, readpartial raises EOFError.
1159   #
1160   # When readpartial doesn‘t blocks, it returns or raises immediately.
1161   # If the buffer is not empty, it returns the data in the buffer.
1162   # Otherwise if the stream has some content, it returns the data in
1163   # the stream. Otherwise if the stream is reached to EOF, it raises EOFError.
1164   #
1165   #  r, w = IO.pipe           #               buffer          pipe content
1166   #  w << "abc"               #               ""              "abc".
1167   #  r.readpartial(4096)      #=> "abc"       ""              ""
1168   #  r.readpartial(4096)      # blocks because buffer and pipe is empty.
1169   #
1170   #  r, w = IO.pipe           #               buffer          pipe content
1171   #  w << "abc"               #               ""              "abc"
1172   #  w.close                  #               ""              "abc" EOF
1173   #  r.readpartial(4096)      #=> "abc"       ""              EOF
1174   #  r.readpartial(4096)      # raises EOFError
1175   #
1176   #  r, w = IO.pipe           #               buffer          pipe content
1177   #  w << "abc\ndef\n"        #               ""              "abc\ndef\n"
1178   #  r.gets                   #=> "abc\n"     "def\n"         ""
1179   #  w << "ghi\n"             #               "def\n"         "ghi\n"
1180   #  r.readpartial(4096)      #=> "def\n"     ""              "ghi\n"
1181   #  r.readpartial(4096)      #=> "ghi\n"     ""              ""
1182   # Note that readpartial behaves similar to sysread. The differences are:
1183   #
1184   # If the buffer is not empty, read from the buffer instead
1185   # of "sysread for buffered IO (IOError)".
1186   # It doesn‘t cause Errno::EAGAIN and Errno::EINTR. When readpartial
1187   # meets EAGAIN and EINTR by read system call, readpartial retry the system call.
1188   # The later means that readpartial is nonblocking-flag insensitive. It
1189   # blocks on the situation IO#sysread causes Errno::EAGAIN as if the fd is blocking mode.
1190   def readpartial(size, buffer = nil)
1191     raise ArgumentError, 'negative string size' unless size >= 0
1192     raise IOError, "closed stream" if closed?
1194     buffer = '' if buffer.nil?
1196     in_buf = @buffer.shift_front size
1197     size = size - in_buf.length
1199     in_buf << sysread(size) if size > 0
1201     buffer.replace in_buf
1203     buffer
1204   end
1206   alias_method :orig_reopen, :reopen
1208   ##
1209   # Reassociates ios with the I/O stream given in other_IO or to
1210   # a new stream opened on path. This may dynamically change the
1211   # actual class of this stream.
1212   #
1213   #  f1 = File.new("testfile")
1214   #  f2 = File.new("testfile")
1215   #  f2.readlines[0]   #=> "This is line one\n"
1216   #  f2.reopen(f1)     #=> #<File:testfile>
1217   #  f2.readlines[0]   #=> "This is line one\n"
1218   def reopen(other, mode = 'r')
1219     other = if other.respond_to? :to_io then
1220               other.to_io
1221             else
1222               File.new other, mode
1223             end
1225     raise IOError, 'closed stream' if other.closed?
1227     prim_reopen other
1229     self
1230   end
1232   ##
1233   # Positions ios to the beginning of input, resetting lineno to zero.
1234   #
1235   #  f = File.new("testfile")
1236   #  f.readline   #=> "This is line one\n"
1237   #  f.rewind     #=> 0
1238   #  f.lineno     #=> 0
1239   #  f.readline   #=> "This is line one\n"
1240   def rewind
1241     seek 0
1242     @lineno = 0
1243     @eof = false
1244     return 0
1245   end
1247   ##
1248   # Seeks to a given offset +amount+ in the stream according to the value of whence:
1249   #
1250   # IO::SEEK_CUR  | Seeks to _amount_ plus current position
1251   # --------------+----------------------------------------------------
1252   # IO::SEEK_END  | Seeks to _amount_ plus end of stream (you probably
1253   #               | want a negative value for _amount_)
1254   # --------------+----------------------------------------------------
1255   # IO::SEEK_SET  | Seeks to the absolute location given by _amount_
1256   # Example:
1257   #
1258   #  f = File.new("testfile")
1259   #  f.seek(-13, IO::SEEK_END)   #=> 0
1260   #  f.readline                  #=> "And so on...\n"
1261   def seek(amount, whence=SEEK_SET)
1262     raise IOError, "closed stream" if closed?
1263     # Unseek the still buffered amount
1264     unless @buffer.empty?
1265       prim_seek(-@buffer.size, SEEK_CUR)
1266       @buffer.reset!
1267       @eof = false
1268     end
1270     prim_seek amount, whence
1271   end
1273   ##
1274   # Returns status information for ios as an object of type File::Stat.
1275   #
1276   #  f = File.new("testfile")
1277   #  s = f.stat
1278   #  "%o" % s.mode   #=> "100644"
1279   #  s.blksize       #=> 4096
1280   #  s.atime         #=> Wed Apr 09 08:53:54 CDT 2003
1281   def stat
1282     raise IOError, "closed stream" if closed?
1284     File::Stat.from_fd fileno
1285   end
1287   ##
1288   # Returns the current ``sync mode’’ of ios. When sync mode is true,
1289   # all output is immediately flushed to the underlying operating
1290   # system and is not buffered by Ruby internally. See also IO#fsync.
1291   #
1292   #  f = File.new("testfile")
1293   #  f.sync   #=> false
1294   def sync
1295     raise IOError, "closed stream" if closed?
1296     true
1297   end
1299   ##
1300   #--
1301   # The current implementation does no write buffering, so we're always in
1302   # sync mode.
1304   def sync=(v)
1305     raise IOError, "closed stream" if closed?
1306   end
1308   ##
1309   # Reads integer bytes from ios using a low-level read and returns
1310   # them as a string. Do not mix with other methods that read from
1311   # ios or you may get unpredictable results. Raises SystemCallError 
1312   # on error and EOFError at end of file.
1313   #
1314   #  f = File.new("testfile")
1315   #  f.sysread(16)   #=> "This is line one"
1316   def sysread(size, buffer = nil)
1317     raise ArgumentError, 'negative string size' unless size >= 0
1318     raise IOError, "closed stream" if closed?
1320     buffer = "\0" * size unless buffer
1322     chan = Channel.new
1323     Scheduler.send_on_readable chan, self, buffer, size
1324     raise EOFError if chan.receive.nil?
1326     buffer
1327   end
1329   ##
1330   # Seeks to a given offset in the stream according to the value
1331   # of whence (see IO#seek for values of whence). Returns the new offset into the file.
1332   #
1333   #  f = File.new("testfile")
1334   #  f.sysseek(-13, IO::SEEK_END)   #=> 53
1335   #  f.sysread(10)                  #=> "And so on."
1336   def sysseek(amount, whence=SEEK_SET)
1337     raise IOError, "closed stream" if closed?
1338     Platform::POSIX.lseek(@descriptor, amount, whence)
1339   end
1341   def to_io
1342     self
1343   end
1345   alias_method :prim_tty?, :tty?
1347   ##
1348   # Returns true if ios is associated with a terminal device (tty), false otherwise.
1349   #
1350   #  File.new("testfile").isatty   #=> false
1351   #  File.new("/dev/tty").isatty   #=> true
1352   def tty?
1353     raise IOError, "closed stream" if closed?
1354     prim_tty?
1355   end
1357   alias_method :isatty, :tty?
1359   def wait_til_readable
1360     chan = Channel.new
1361     Scheduler.send_on_readable chan, self, nil, nil
1362     chan.receive
1363   end
1365   alias_method :prim_write, :write
1367   ##
1368   # Pushes back one character (passed as a parameter) onto ios,
1369   # such that a subsequent buffered read will return it. Only one
1370   # character may be pushed back before a subsequent read operation
1371   # (that is, you will be able to read only the last of several
1372   # characters that have been pushed back). Has no effect with
1373   # unbuffered reads (such as IO#sysread).
1374   #
1375   #  f = File.new("testfile")   #=> #<File:testfile>
1376   #  c = f.getc                 #=> 84
1377   #  f.ungetc(c)                #=> nil
1378   #  f.getc                     #=> 84
1379   def write(data)
1380     raise IOError, "closed stream" if closed?
1381     # If we have buffered data, rewind.
1382     unless @buffer.empty?
1383       seek 0, SEEK_CUR
1384     end
1386     data = String data
1388     return 0 if data.length == 0
1389     raise IOError if ((Platform::POSIX.fcntl(@descriptor, F_GETFL, 0) & ACCMODE) == RDONLY)
1390     prim_write(data)
1391   end
1393   alias_method :syswrite, :write
1394   alias_method :write_nonblock, :write
1396   def self.after_loaded()
1397     remove_method :orig_reopen
1398     # Nothing to do right now
1399   end
1404 # Implements the pipe returned by IO::pipe.
1406 class IO::BidirectionalPipe < IO
1408   READ_METHODS = [
1409     :each,
1410     :each_line,
1411     :getc,
1412     :gets,
1413     :read,
1414     :read_nonblock,
1415     :readchar,
1416     :readline,
1417     :readlines,
1418     :readpartial,
1419     :sysread,
1420   ]
1422   WRITE_METHODS = [
1423     :<<,
1424     :print,
1425     :printf,
1426     :putc,
1427     :puts,
1428     :syswrite,
1429     :write,
1430     :write_nonblock,
1431   ]
1433   def initialize(pid, read, write)
1434     @pid = pid
1435     @read = read
1436     @write = write
1437   end
1439   def check_read
1440     raise IOError, 'not opened for reading' if @read.nil?
1441   end
1443   def check_write
1444     raise IOError, 'not opened for writing' if @write.nil?
1445   end
1447   ##
1448   # Closes ios and flushes any pending writes to the
1449   # operating system. The stream is unavailable for
1450   # any further data operations; an IOError is raised
1451   # if such an attempt is made. I/O streams are
1452   # automatically closed when they are claimed by
1453   # the garbage collector.
1454   #
1455   # If ios is opened by IO.popen, close sets $?.
1456   def close
1457     @read.close  if @read  and not @read.closed?
1458     @write.close if @write and not @write.closed?
1460     if @pid != 0 then
1461       Process.wait @pid
1463       @pid = 0
1464     end
1466     nil
1467   end
1469   def closed?
1470     if @read and @write then
1471       @read.closed? and @write.closed?
1472     elsif @read then
1473       @read.closed?
1474     else
1475       @write.closed?
1476     end
1477   end
1479   def close_read
1480     raise IOError, 'closed stream' if @read.closed?
1482     @read.close if @read
1483   end
1485   def close_write
1486     raise IOError, 'closed stream' if @write.closed?
1488     @write.close if @write
1489   end
1491   def method_missing(message, *args, &block)
1492     if READ_METHODS.include? message then
1493       check_read
1495       @read.send(message, *args, &block)
1496     elsif WRITE_METHODS.include? message then
1497       check_write
1499       @write.send(message, *args, &block)
1500     else
1501       super
1502     end
1503   end
1505   def pid
1506     raise IOError, 'closed stream' if closed?
1508     @pid
1509   end
1511   def self.after_loaded
1512     (READ_METHODS + WRITE_METHODS).each do |method|
1513       undef_method method
1514     end
1515   end