1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
|
require 'socket'
require 'drb/drb'
require 'tmpdir'
raise(LoadError, "UNIXServer is required") unless defined?(UNIXServer)
module DRb
# Implements DRb over a UNIX socket
#
# DRb UNIX socket URIs look like <code>drbunix:<path>?<option></code>. The
# option is optional.
class DRbUNIXSocket < DRbTCPSocket
# :stopdoc:
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, = parse_uri(uri)
filename.untaint
soc = UNIXSocket.open(filename)
self.new(uri, soc, config)
end
def self.open_server(uri, config)
filename, = parse_uri(uri)
if filename.size == 0
soc = temp_server
filename = soc.path
uri = 'drbunix:' + soc.path
else
soc = UNIXServer.open(filename)
end
owner = config[:UNIXFileOwner]
group = config[:UNIXFileGroup]
if owner || group
require 'etc'
owner = Etc.getpwnam( owner ).uid if owner
group = Etc.getgrnam( group ).gid if group
File.chown owner, group, 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 = Dir::tmpdir
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 if @server_mode
@socket.close
File.unlink(path) if @server_mode
@socket = nil
close_shutdown_pipe
end
def accept
s = accept_or_shutdown
return nil unless s
self.class.new(nil, s, @config)
end
def set_sockopt(soc)
soc.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC) if defined? Fcntl::FD_CLOEXEC
end
end
DRbProtocol.add_protocol(DRbUNIXSocket)
# :startdoc:
end
|