nfs-rb 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,3 @@
1
+ module NFS
2
+ VERSION = '1.0.0'
3
+ end
@@ -0,0 +1,300 @@
1
+ # Ruby XDR. XDR codec for Ruby. Based on RFC 4506.
2
+
3
+ module NFS
4
+ module XDR
5
+ class Void
6
+ def encode(value)
7
+ ''
8
+ end
9
+
10
+ def decode(string)
11
+ nil
12
+ end
13
+ end
14
+
15
+ class SignedInteger
16
+ def encode(value)
17
+ [value].pack('N')
18
+ end
19
+
20
+ def decode(string)
21
+ string.slice!(0..3).unpack('N').pack('I').unpack('i')[0]
22
+ end
23
+ end
24
+
25
+ class UnsignedInteger
26
+ def encode(value)
27
+ [value].pack('N')
28
+ end
29
+
30
+ def decode(string)
31
+ string.slice!(0..3).unpack('N')[0]
32
+ end
33
+ end
34
+
35
+ class Enumeration < SignedInteger
36
+ def initialize(&block)
37
+ @values = {}
38
+ @names = {}
39
+
40
+ if block_given?
41
+ instance_eval(&block)
42
+ end
43
+ end
44
+
45
+ def name(v_name, value)
46
+ @values[v_name] = value
47
+ @names[value] = v_name
48
+ end
49
+
50
+ def encode(name)
51
+ super(@values[name])
52
+ end
53
+
54
+ def decode(string)
55
+ @names[super(string)]
56
+ end
57
+ end
58
+
59
+ class Boolean < Enumeration
60
+ def initialize
61
+ super
62
+
63
+ name :TRUE, 1
64
+ name :FALSE, 0
65
+ end
66
+ end
67
+
68
+ class FloatNum
69
+ def encode(value)
70
+ [value].pack('g')
71
+ end
72
+
73
+ def decode(string)
74
+ string.slice!(0..3).unpack('g')[0]
75
+ end
76
+ end
77
+
78
+ class DoubleNum
79
+ def encode(value)
80
+ [value].pack('G')
81
+ end
82
+
83
+ def decode(string)
84
+ string.slice!(0..7).unpack('G')[0]
85
+ end
86
+ end
87
+
88
+ def self.pad(n, align)
89
+ r = n % align
90
+ r = align if r == 0
91
+ n + align - r
92
+ end
93
+
94
+ class FixedString
95
+ def initialize(n)
96
+ @n = n
97
+ end
98
+
99
+ def encode(value)
100
+ [value.to_s].pack('a' + XDR.pad(@n, 4).to_s)
101
+ end
102
+
103
+ def decode(string)
104
+ superstring = string.slice!(0, XDR.pad(@n, 4))
105
+ superstring.nil? ? '' : superstring[0, @n]
106
+ end
107
+ end
108
+
109
+ class DynamicString
110
+ def initialize(n = nil)
111
+ @n = n
112
+ @length = UnsignedInteger.new
113
+ end
114
+
115
+ def encode(value)
116
+ value = value.to_s
117
+ n = value.size
118
+ n = @n if !@n.nil? && @n < n
119
+ @length.encode(n) + [value].pack('a' + XDR::pad(n, 4).to_s)
120
+ end
121
+
122
+ def decode(string)
123
+ length = @length.decode(string)
124
+ superstring = string.slice!(0, XDR.pad(length, 4))
125
+ superstring.nil? ? '' : superstring[0, length]
126
+ end
127
+ end
128
+
129
+ class FixedOpaque < FixedString
130
+ end
131
+
132
+ class Opaque < DynamicString
133
+ end
134
+
135
+ class FixedArray
136
+ def initialize(type, n)
137
+ @type, @n = type, n
138
+ end
139
+
140
+ def encode(value)
141
+ n.times do |i|
142
+ @type.encode(value[i])
143
+ end
144
+ end
145
+
146
+ def decode(string)
147
+ Array.new(n) do
148
+ @type.decode(string)
149
+ end
150
+ end
151
+ end
152
+
153
+ class DynamicArray
154
+ def initialize(type, n)
155
+ @type, @n = type, n
156
+ @length = UnsignedInteger.new
157
+ end
158
+
159
+ def encode(value)
160
+ n = value.size
161
+
162
+ if !@n.nil? && @n < n
163
+ n = @n
164
+ end
165
+
166
+ result = @length.encode(n)
167
+
168
+ n.times do |i|
169
+ result << @type.encode(value[i])
170
+ end
171
+
172
+ result
173
+ end
174
+
175
+ def decode(string)
176
+ length = @length.decode(string)
177
+
178
+ Array.new(length) do
179
+ @type.decode(string)
180
+ end
181
+ end
182
+ end
183
+
184
+ class Optional < DynamicArray
185
+ def initialize(type)
186
+ super(type, 1)
187
+ end
188
+
189
+ def encode(value)
190
+ if value.nil?
191
+ super([])
192
+ else
193
+ super([value])
194
+ end
195
+ end
196
+
197
+ def decode(string)
198
+ result = super(string)
199
+
200
+ if result.empty?
201
+ nil
202
+ else
203
+ result[0]
204
+ end
205
+ end
206
+ end
207
+
208
+ class Structure
209
+ def initialize(&block)
210
+ @components = []
211
+ @names = []
212
+ instance_eval(&block) if block_given?
213
+ end
214
+
215
+ def component(name, type)
216
+ @components << [name, type]
217
+ @names << name
218
+ end
219
+
220
+ def encode(value)
221
+ ''.tap do |result|
222
+ @components.each do |component|
223
+ unless value.include?(component[0])
224
+ raise 'missing structure component ' + component[0].to_s
225
+ end
226
+
227
+ result << component[1].encode(value[component[0]])
228
+ end
229
+ end
230
+ end
231
+
232
+ def decode(string)
233
+ @components.each_with_object({}) do |component, result|
234
+ result[component[0]] = component[1].decode(string)
235
+ end
236
+ end
237
+ end
238
+
239
+ # Each arm of the union is represented as a struct
240
+ class Union
241
+ def initialize(disc_type, &block)
242
+ @disc_type = disc_type
243
+ @arms = {}
244
+ @default_arm = nil
245
+ instance_eval(&block) if block_given?
246
+ end
247
+
248
+ # Add an arm
249
+ def arm(disc_value, struct = nil, &block)
250
+ if block_given?
251
+ struct = Structure.new(&block)
252
+ end
253
+
254
+ @arms[disc_value] = struct
255
+ end
256
+
257
+ # Set the default arm
258
+ def default(struct = nil, &block)
259
+ if block_given?
260
+ struct = Structure.new(&block)
261
+ end
262
+
263
+ @default_arm = struct
264
+ end
265
+
266
+ def encode(struct)
267
+ disc = struct[:_discriminant]
268
+ arm = @default_arm
269
+ arm = @arms[disc] if @arms.include?(disc)
270
+ result = @disc_type.encode(disc)
271
+
272
+ unless arm.nil?
273
+ result << arm.encode(struct)
274
+ end
275
+
276
+ result
277
+ end
278
+
279
+ def decode(string)
280
+ disc = @disc_type.decode(string)
281
+ arm = @default_arm
282
+
283
+ if @arms.include?(disc)
284
+ arm = @arms[disc]
285
+ end
286
+
287
+ result = nil
288
+
289
+ if arm.nil?
290
+ result = {}
291
+ else
292
+ result = arm.decode(string)
293
+ end
294
+
295
+ result[:_discriminant] = disc
296
+ result
297
+ end
298
+ end
299
+ end
300
+ end
@@ -0,0 +1,17 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), 'lib')
2
+ require 'nfs/version'
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = 'nfs-rb'
6
+ s.version = ::NFS::VERSION
7
+ s.authors = ['Cameron Dutro', 'Brian Ollenberger']
8
+ s.email = ['camertron@gmail.com']
9
+ s.homepage = 'http://github.com/camertron/nfs'
10
+ s.description = s.summary = 'An NFS v2 server implemented in pure Ruby.'
11
+ s.platform = Gem::Platform::RUBY
12
+ s.require_path = 'lib'
13
+
14
+ s.executables << 'nfs-rb'
15
+
16
+ s.files = Dir['{lib,spec}/**/*', 'Gemfile', 'LICENSE', 'CHANGELOG.md', 'README.md', 'Rakefile', 'nfs-rb.gemspec']
17
+ end
@@ -0,0 +1,29 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'NFS' do
4
+ it 'supports directory listing' do
5
+ files = Dir.chdir($dest_dir) do
6
+ Dir.glob("*.*")
7
+ end
8
+
9
+ expect(files.sort).to eq(['file1.txt', 'file2.txt'].sort)
10
+ end
11
+
12
+ it 'supports reading files' do
13
+ %w(file1.txt file2.txt).each do |file|
14
+ orig_contents = File.read(File.join($orig_dir, file))
15
+ dest_contents = File.read(File.join($dest_dir, file))
16
+ expect(dest_contents).to eq(orig_contents)
17
+ end
18
+ end
19
+
20
+ it 'supports file stats' do
21
+ %w(file1.txt file2.txt).each do |file|
22
+ orig_stat = File.lstat(File.join($orig_dir, 'file1.txt'))
23
+ dest_stat = File.lstat(File.join($dest_dir, 'file1.txt'))
24
+ expect(orig_stat.size).to eq(dest_stat.size)
25
+ expect(orig_stat.mtime.to_i).to eq(dest_stat.mtime.to_i)
26
+ expect(orig_stat.ctime.to_i).to eq(dest_stat.ctime.to_i)
27
+ end
28
+ end
29
+ end
@@ -0,0 +1 @@
1
+ Hello world!
@@ -0,0 +1,3 @@
1
+ Oy! This is a other file.
2
+
3
+ With multiple lines.
@@ -0,0 +1,10 @@
1
+ require 'nfs'
2
+
3
+ nfs_server = NFS::Server.new(
4
+ dir: File.expand_path(File.join('.', 'orig_dir'), __dir__),
5
+ host: '127.0.0.1',
6
+ port: 1234,
7
+ protocol: :tcp
8
+ )
9
+
10
+ nfs_server.join
@@ -0,0 +1,44 @@
1
+ # encoding: UTF-8
2
+
3
+ $:.push(File.dirname(__FILE__))
4
+
5
+ require 'rspec'
6
+ require 'fileutils'
7
+ require 'nfs'
8
+
9
+ RSpec.configure do |config|
10
+ config.before(:suite) do
11
+ $orig_dir = File.expand_path(File.join('.', 'orig_dir'), __dir__)
12
+ $dest_dir = File.expand_path(File.join('.', 'dest_dir'), __dir__)
13
+
14
+ FileUtils.mkdir_p($dest_dir)
15
+
16
+ $server_pid = Process.spawn(
17
+ "bundle exec ruby #{File.join('spec', 'run_server.rb')}"
18
+ )
19
+
20
+ system(
21
+ "mount -t nfs -o "\
22
+ 'rsize=8192,wsize=8192,timeo=1,nfsvers=2,proto=tcp,'\
23
+ "port=1234,mountport=1234,"\
24
+ "hard,intr,nolock 127.0.0.1:/ "\
25
+ "#{$dest_dir}"
26
+ )
27
+
28
+ if $?.exitstatus != 0
29
+ fail "Unable to mount NFS volume at #{$dest_dir}"
30
+ exit 1
31
+ end
32
+ end
33
+
34
+ config.after(:suite) do
35
+ system("umount #{$dest_dir}")
36
+
37
+ if $?.exitstatus != 0
38
+ fail "Unable to unmount NFS volume at #{$dest_dir}"
39
+ exit 2
40
+ end
41
+
42
+ Process.kill('HUP', $server_pid)
43
+ end
44
+ end
metadata ADDED
@@ -0,0 +1,74 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: nfs-rb
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Cameron Dutro
8
+ - Brian Ollenberger
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2020-08-16 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: An NFS v2 server implemented in pure Ruby.
15
+ email:
16
+ - camertron@gmail.com
17
+ executables:
18
+ - nfs-rb
19
+ extensions: []
20
+ extra_rdoc_files: []
21
+ files:
22
+ - CHANGELOG.md
23
+ - Gemfile
24
+ - LICENSE
25
+ - README.md
26
+ - Rakefile
27
+ - bin/nfs-rb
28
+ - lib/nfs.rb
29
+ - lib/nfs/default_logger.rb
30
+ - lib/nfs/file_proxy.rb
31
+ - lib/nfs/filehandle.rb
32
+ - lib/nfs/handler.rb
33
+ - lib/nfs/mount.rb
34
+ - lib/nfs/nfs.rb
35
+ - lib/nfs/server.rb
36
+ - lib/nfs/sunrpc.rb
37
+ - lib/nfs/sunrpc/client.rb
38
+ - lib/nfs/sunrpc/procedure.rb
39
+ - lib/nfs/sunrpc/program.rb
40
+ - lib/nfs/sunrpc/server.rb
41
+ - lib/nfs/sunrpc/tcp_server.rb
42
+ - lib/nfs/sunrpc/udp_server.rb
43
+ - lib/nfs/sunrpc/version.rb
44
+ - lib/nfs/version.rb
45
+ - lib/nfs/xdr.rb
46
+ - nfs-rb.gemspec
47
+ - spec/nfs_spec.rb
48
+ - spec/orig_dir/file1.txt
49
+ - spec/orig_dir/file2.txt
50
+ - spec/run_server.rb
51
+ - spec/spec_helper.rb
52
+ homepage: http://github.com/camertron/nfs
53
+ licenses: []
54
+ metadata: {}
55
+ post_install_message:
56
+ rdoc_options: []
57
+ require_paths:
58
+ - lib
59
+ required_ruby_version: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: '0'
64
+ required_rubygems_version: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ requirements: []
70
+ rubygems_version: 3.1.4
71
+ signing_key:
72
+ specification_version: 4
73
+ summary: An NFS v2 server implemented in pure Ruby.
74
+ test_files: []