зеркало из https://github.com/github/ruby.git
99 строки
2.2 KiB
Ruby
99 строки
2.2 KiB
Ruby
|
require 'socket'
|
||
|
require 'drb/drb'
|
||
|
|
||
|
module DRb
|
||
|
|
||
|
class DRbUNIXSocket < DRbTCPSocket
|
||
|
def self.parse_uri(uri)
|
||
|
if /^drbunix:(.*?)(\?(.*))?$/ =~ uri
|
||
|
filename = $1
|
||
|
option = $3
|
||
|
[filename, option]
|
||
|
else
|
||
|
raise(DRbBadScheme, uri) unless uri =~ /^drbunix:/
|
||
|
raise(DRbBadURI, 'can\'t parse uri:' + uri)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def self.open(uri, config)
|
||
|
filename, option = parse_uri(uri)
|
||
|
filename.untaint
|
||
|
soc = UNIXSocket.open(filename)
|
||
|
self.new(uri, soc, config)
|
||
|
end
|
||
|
|
||
|
def self.open_server(uri, config)
|
||
|
filename, option = parse_uri(uri)
|
||
|
if filename.size == 0
|
||
|
soc = temp_server
|
||
|
uri = 'drbunix:' + soc.path
|
||
|
else
|
||
|
soc = UNIXServer.open(filename)
|
||
|
end
|
||
|
mode = config[:UNIXFileMode]
|
||
|
File.chmod(mode, filename) if mode
|
||
|
|
||
|
self.new(uri, soc, config, true)
|
||
|
end
|
||
|
|
||
|
def self.uri_option(uri, config)
|
||
|
filename, option = parse_uri(uri)
|
||
|
return "drbunix:#{filename}", option
|
||
|
end
|
||
|
|
||
|
def initialize(uri, soc, config={}, server_mode = false)
|
||
|
super(uri, soc, config)
|
||
|
set_sockopt(@socket)
|
||
|
@server_mode = server_mode
|
||
|
@acl = nil
|
||
|
end
|
||
|
|
||
|
# import from tempfile.rb
|
||
|
Max_try = 10
|
||
|
private
|
||
|
def self.temp_server
|
||
|
tmpdir = ENV['TMPDIR'] || ENV['TMP'] || ENV['TEMP'] || '/tmp'
|
||
|
tmpdir = '/tmp' if $SAFE > 0 and tmpdir.tainted?
|
||
|
n = 0
|
||
|
while true
|
||
|
begin
|
||
|
tmpname = sprintf('%s/druby%d.%d', tmpdir, $$, n)
|
||
|
lock = tmpname + '.lock'
|
||
|
unless File.exist?(tmpname) or File.exist?(lock)
|
||
|
Dir.mkdir(lock)
|
||
|
break
|
||
|
end
|
||
|
rescue
|
||
|
raise "cannot generate tempfile `%s'" % tmpname if n >= Max_try
|
||
|
#sleep(1)
|
||
|
end
|
||
|
n += 1
|
||
|
end
|
||
|
soc = UNIXServer.new(tmpname)
|
||
|
Dir.rmdir(lock)
|
||
|
soc
|
||
|
end
|
||
|
|
||
|
public
|
||
|
def close
|
||
|
return unless @socket
|
||
|
path = @socket.path
|
||
|
@socket.close
|
||
|
File.unlink(path) if @server_mode
|
||
|
@socket = nil
|
||
|
end
|
||
|
|
||
|
def accept
|
||
|
s = @socket.accept
|
||
|
self.class.new(nil, s, @config)
|
||
|
end
|
||
|
|
||
|
def set_sockopt(soc)
|
||
|
soc.fcntl(Fcntl::F_SETFL, Fcntl::O_NONBLOCK) if defined? Fcntl::O_NONBLOCK
|
||
|
soc.fcntl(Fcntl::F_SETFL, Fcntl::FD_CLOEXEC) if defined? Fcntl::FD_CLOEXEC
|
||
|
end
|
||
|
end
|
||
|
|
||
|
DRbProtocol.add_protocol(DRbUNIXSocket)
|
||
|
end
|