1 # -*- encoding: binary -*-
2 require 'io_splice_ext'
7 # The maximum default capacity of the pipe in bytes.
8 # Under stock Linux, this is 65536 bytes as of 2.6.11, and 4096 before
9 # We detect this at runtime as it is easy to recompile the kernel
10 # and set a new value.
11 # Starting with Linux 2.6.35, pipe capacity will be tunable
12 # and this will only represent the default capacity of a
19 n += wr.write_nonblock(buf)
28 def self.need_open?(obj) # :nodoc:
29 return false if obj.respond_to?(:to_io)
30 obj.respond_to?(:to_path) || obj.kind_of?(String)
33 # copies the contents of the IO object given by +src+ to +dst+
34 # If +len+ is specified, then only +len+ bytes are copied and
35 # +EOFError+ is raised if fewer than +len+ bytes could be copied.
36 # Otherwise the copy will be until EOF is reached on the +src+.
37 # +src+ and +dst+ must be IO objects or respond to +to_io+
39 # This is nearly a drop-in replacement for IO.copy_stream (in Ruby 1.9)
40 # but does not take into account userspace I/O buffers nor IO-like
41 # objects with no underlying file descriptor (e.g. StringIO).
42 def self.copy_stream(src, dst, len = nil, src_offset = nil)
44 need_open?(src) and close << (src = File.open(src))
45 need_open?(dst) and close << (dst = File.open(dst, "w"))
47 src, dst = src.to_io, dst.to_io
49 if src.stat.pipe? || dst.stat.pipe?
50 return full(src, dst, len, src_offset) if len
52 while n = partial(src, dst, PIPE_CAPA, src_offset)
54 src_offset += n if src_offset
60 while len != 0 && n = partial(src, w, len, src_offset)
61 src_offset += n if src_offset
62 len -= full(r, dst, n, nil)
66 while n = partial(src, w, PIPE_CAPA, src_offset)
67 src_offset += n if src_offset
68 rv += full(r, dst, n, nil)
75 close.each { |io| io.close }
78 # splice the full amount specified from +src+ to +dst+
79 # Either +dst+ or +src+ must be a pipe. +dst+ and +src+
80 # may BOTH be pipes in Linux 2.6.31 or later.
81 # This will block and wait for IO completion of +len+
82 # Raises +EOFError+ if end of file is reached.
83 # bytes. Returns the number of bytes actually spliced (always +len+)
84 # unless +src+ does not have +len+ bytes to read.
86 # Do not use this method to splice a socket +src+ into a pipe +dst+
87 # unless there is another process or native thread doing a blocking
88 # read on the other end of the +dst+ pipe.
90 # This method is safe for splicing a pipe +src+ into any type of +dst+ IO.
91 def self.full(src, dst, len, src_offset)
92 IO.splice(src, src_offset, dst, nil, len, F_MOVE | WAITALL)
95 # splice up to +len+ bytes from +src+ to +dst+.
96 # Either +dst+ or +src+ must be a pipe. +dst+ and +src+
97 # may BOTH be pipes in Linux 2.6.31 or later.
98 # Returns the number of bytes actually spliced.
99 # Like IO#readpartial, this never returns Errno::EAGAIN
100 def self.partial(src, dst, len, src_offset)
101 case rv = IO.trysplice(src, src_offset, dst, nil, len, F_MOVE)
104 IO.select(nil, [dst])
112 if (! defined?(RUBY_ENGINE) || RUBY_ENGINE == "ruby") &&
113 RUBY_VERSION.to_f <= 1.8
114 require "io/splice/mri_18"