sambal 0.1.6 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile +2 -0
- data/README.md +2 -0
- data/Spookfile +11 -0
- data/circle.yml +4 -0
- data/lib/sambal.rb +4 -278
- data/lib/sambal/client.rb +258 -0
- data/lib/sambal/response.rb +25 -0
- data/lib/sambal/smb.conf.erb +5 -3
- data/lib/sambal/test_server.rb +21 -11
- data/lib/sambal/version.rb +1 -1
- data/sambal.gemspec +1 -1
- data/spec/sambal/client_spec.rb +123 -106
- data/spec/spec_helper.rb +3 -2
- metadata +8 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 38f975857d880b0980139c775c4209198a0fc61d
|
4
|
+
data.tar.gz: 736a0bff136bf70413f17df9e54a691b38e26a3a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c64dd602dc5e03c8c5d4b2f72664e0fd2edf37fca88b795ee0f1ebb9d977d483c0e071728d187f45ce10bbbf4cb94f20b4fc7fe62a2eea031d11909201b07fad
|
7
|
+
data.tar.gz: 16d10c22578db5eb2ac0b30835d892b41588cf4a79b953d9ad3231e0c3735a8808001edde69f8d1631470d9ff41a997fe5aacc9017efd66f34c2fb9c8cb20be6
|
data/Gemfile
CHANGED
data/README.md
CHANGED
data/Spookfile
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
-- How much output do we want?
|
2
|
+
log_level "INFO"
|
3
|
+
|
4
|
+
rspec = command "bundle exec rspec -f d"
|
5
|
+
|
6
|
+
watch "lib", "spec", ->
|
7
|
+
on_changed "^(spec)/(spec_helper%.rb)", -> rspec "spec"
|
8
|
+
on_changed "^spec/(.*)_spec%.rb", (a) -> rspec "spec/#{a}_spec.rb"
|
9
|
+
on_changed "^lib/sambal%.rb", (a) -> rspec "spec/sambal/client_spec.rb"
|
10
|
+
|
11
|
+
notifier "#{os.getenv('HOME')}/.spook/notifiers"
|
data/circle.yml
ADDED
data/lib/sambal.rb
CHANGED
@@ -1,284 +1,10 @@
|
|
1
|
-
# coding: UTF-8
|
2
|
-
|
3
|
-
require "sambal/version"
|
4
|
-
require 'open3'
|
5
|
-
require 'logger'
|
6
|
-
require 'json'
|
7
|
-
require 'pty'
|
8
|
-
require 'expect'
|
9
1
|
require 'time'
|
10
2
|
require 'tempfile'
|
11
3
|
|
12
|
-
|
4
|
+
require 'sambal/version'
|
5
|
+
require 'sambal/client'
|
6
|
+
require 'sambal/response'
|
13
7
|
|
8
|
+
module Sambal
|
14
9
|
class InternalError < RuntimeError; end
|
15
|
-
|
16
|
-
class Response
|
17
|
-
|
18
|
-
attr_reader :message
|
19
|
-
|
20
|
-
def initialize(message, success)
|
21
|
-
msg = message.split("\n")
|
22
|
-
msg.each do |line|
|
23
|
-
if line =~ /^NT\_.*\s/
|
24
|
-
@message = line
|
25
|
-
end
|
26
|
-
end
|
27
|
-
@message ||= message
|
28
|
-
@success = success
|
29
|
-
end
|
30
|
-
|
31
|
-
def success?
|
32
|
-
@success
|
33
|
-
end
|
34
|
-
|
35
|
-
def failure?
|
36
|
-
!success?
|
37
|
-
end
|
38
|
-
|
39
|
-
end
|
40
|
-
|
41
|
-
class Client
|
42
|
-
|
43
|
-
attr_reader :connected
|
44
|
-
|
45
|
-
def initialize(options={})
|
46
|
-
begin
|
47
|
-
options = {domain: 'WORKGROUP', host: '127.0.0.1', share: '', user: 'guest', password: '--no-pass', port: 445, timeout: 10}.merge(options)
|
48
|
-
@timeout = options[:timeout].to_i
|
49
|
-
@o, @i, @pid = PTY.spawn("smbclient \"//#{options[:host]}/#{options[:share]}\" '#{options[:password]}' -W \"#{options[:domain]}\" -U \"#{options[:user]}\" -p #{options[:port]}")
|
50
|
-
#@o.set_encoding('UTF-8:UTF-8') ## don't know didn't work, we only have this problem when the files are named using non-english characters
|
51
|
-
#@i.set_encoding('UTF-8:UTF-8')
|
52
|
-
res = @o.expect(/(.*\n)?smb:.*\\>/, @timeout)[0] rescue nil
|
53
|
-
@connected = case res
|
54
|
-
when nil
|
55
|
-
$stderr.puts "Failed to connect"
|
56
|
-
false
|
57
|
-
when /^put/
|
58
|
-
res['putting'].nil? ? false : true
|
59
|
-
else
|
60
|
-
if res['NT_STATUS']
|
61
|
-
false
|
62
|
-
elsif res['timed out'] || res['Server stopped']
|
63
|
-
false
|
64
|
-
else
|
65
|
-
true
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
unless @connected
|
70
|
-
close if @pid
|
71
|
-
exit(1)
|
72
|
-
end
|
73
|
-
rescue Exception => e
|
74
|
-
raise RuntimeError.exception("Unknown Process Failed!! (#{$!.to_s}): #{e.message.inspect}\n"+e.backtrace.join("\n"))
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
def logger
|
79
|
-
@logger ||= Logger.new(STDOUT)
|
80
|
-
end
|
81
|
-
|
82
|
-
def logger=(l)
|
83
|
-
@logger = l
|
84
|
-
end
|
85
|
-
|
86
|
-
def file_context(path)
|
87
|
-
if (path_parts = path.split('/')).length>1
|
88
|
-
file = path_parts.pop
|
89
|
-
subdirs = path_parts.length
|
90
|
-
dir = path_parts.join('/')
|
91
|
-
cd dir
|
92
|
-
else
|
93
|
-
file = path
|
94
|
-
end
|
95
|
-
begin
|
96
|
-
yield(file)
|
97
|
-
ensure
|
98
|
-
unless subdirs.nil?
|
99
|
-
subdirs.times { cd '..' }
|
100
|
-
end
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
def ls(qualifier = '*')
|
105
|
-
parse_files(ask_wrapped('ls', qualifier))
|
106
|
-
end
|
107
|
-
|
108
|
-
def cd(dir)
|
109
|
-
response = ask("cd \"#{dir}\"")
|
110
|
-
if response.split("\r\n").join('') =~ /NT_STATUS_OBJECT_NAME_NOT_FOUND/
|
111
|
-
Response.new(response, false)
|
112
|
-
else
|
113
|
-
Response.new(response, true)
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
def get(file, output)
|
118
|
-
begin
|
119
|
-
file_context(file) do |file|
|
120
|
-
response = ask_wrapped 'get', [file, output]
|
121
|
-
if response =~ /^getting\sfile.*$/
|
122
|
-
Response.new(response, true)
|
123
|
-
else
|
124
|
-
Response.new(response, false)
|
125
|
-
end
|
126
|
-
end
|
127
|
-
rescue InternalError => e
|
128
|
-
Response.new(e.message, false)
|
129
|
-
end
|
130
|
-
end
|
131
|
-
|
132
|
-
def put(file, destination)
|
133
|
-
response = ask_wrapped 'put', [file, destination]
|
134
|
-
if response =~ /^putting\sfile.*$/
|
135
|
-
Response.new(response, true)
|
136
|
-
else
|
137
|
-
Response.new(response, false)
|
138
|
-
end
|
139
|
-
rescue InternalError => e
|
140
|
-
Response.new(e.message, false)
|
141
|
-
end
|
142
|
-
|
143
|
-
def put_content(content, destination)
|
144
|
-
t = Tempfile.new("upload-smb-content-#{destination}")
|
145
|
-
File.open(t.path, 'w') do |f|
|
146
|
-
f << content
|
147
|
-
end
|
148
|
-
response = ask_wrapped 'put', [t.path, destination]
|
149
|
-
if response =~ /^putting\sfile.*$/
|
150
|
-
Response.new(response, true)
|
151
|
-
else
|
152
|
-
Response.new(response, false)
|
153
|
-
end
|
154
|
-
rescue InternalError => e
|
155
|
-
Response.new(e.message, false)
|
156
|
-
ensure
|
157
|
-
t.close
|
158
|
-
end
|
159
|
-
|
160
|
-
def rmdir(dir)
|
161
|
-
response = cd dir
|
162
|
-
return response if response.failure?
|
163
|
-
begin
|
164
|
-
ls.each do |name, meta|
|
165
|
-
if meta[:type]==:file
|
166
|
-
response = del name
|
167
|
-
elsif meta[:type]==:directory && !(name =~ /^\.+$/)
|
168
|
-
response = rmdir(name)
|
169
|
-
end
|
170
|
-
raise InternalError.new response.message if response && response.failure?
|
171
|
-
end
|
172
|
-
cd '..'
|
173
|
-
response = ask_wrapped 'rmdir', dir
|
174
|
-
next_line = response.split("\n")[1]
|
175
|
-
if next_line =~ /^smb:.*\\>/
|
176
|
-
Response.new(response, true)
|
177
|
-
else
|
178
|
-
Response.new(response, false)
|
179
|
-
end
|
180
|
-
rescue InternalError => e
|
181
|
-
Response.new(e.message, false)
|
182
|
-
end
|
183
|
-
end
|
184
|
-
|
185
|
-
def del(file)
|
186
|
-
begin
|
187
|
-
file_context(file) do |file|
|
188
|
-
response = ask_wrapped 'del', file
|
189
|
-
next_line = response.split("\n")[1]
|
190
|
-
if next_line =~ /^smb:.*\\>/
|
191
|
-
Response.new(response, true)
|
192
|
-
#elsif next_line =~ /^NT_STATUS_NO_SUCH_FILE.*$/
|
193
|
-
# Response.new(response, false)
|
194
|
-
#elsif next_line =~ /^NT_STATUS_ACCESS_DENIED.*$/
|
195
|
-
# Response.new(response, false)
|
196
|
-
else
|
197
|
-
Response.new(response, false)
|
198
|
-
end
|
199
|
-
end
|
200
|
-
rescue InternalError => e
|
201
|
-
Response.new(e.message, false)
|
202
|
-
end
|
203
|
-
#end
|
204
|
-
#if (path_parts = file.split('/')).length>1
|
205
|
-
# file = path_parts.pop
|
206
|
-
# subdirs = path_parts.length
|
207
|
-
# dir = path_parts.join('/')
|
208
|
-
# cd dir
|
209
|
-
#end
|
210
|
-
# response = ask "del #{file}"
|
211
|
-
# next_line = response.split("\n")[1]
|
212
|
-
# if next_line =~ /^smb:.*\\>/
|
213
|
-
# Response.new(response, true)
|
214
|
-
# #elsif next_line =~ /^NT_STATUS_NO_SUCH_FILE.*$/
|
215
|
-
# # Response.new(response, false)
|
216
|
-
# #elsif next_line =~ /^NT_STATUS_ACCESS_DENIED.*$/
|
217
|
-
# # Response.new(response, false)
|
218
|
-
# else
|
219
|
-
# Response.new(response, false)
|
220
|
-
# end
|
221
|
-
#rescue InternalError => e
|
222
|
-
# Response.new(e.message, false)
|
223
|
-
#ensure
|
224
|
-
# unless subdirs.nil?
|
225
|
-
# subdirs.times { cd '..' }
|
226
|
-
# end
|
227
|
-
end
|
228
|
-
|
229
|
-
def close
|
230
|
-
@i.close
|
231
|
-
@o.close
|
232
|
-
Process.wait(@pid)
|
233
|
-
@connected = false
|
234
|
-
end
|
235
|
-
|
236
|
-
def ask(cmd)
|
237
|
-
@i.printf("#{cmd}\n")
|
238
|
-
response = @o.expect(/^smb:.*\\>/,@timeout)[0] rescue nil
|
239
|
-
if response.nil?
|
240
|
-
$stderr.puts "Failed to do #{cmd}"
|
241
|
-
raise Exception.new, "Failed to do #{cmd}"
|
242
|
-
else
|
243
|
-
response
|
244
|
-
end
|
245
|
-
end
|
246
|
-
|
247
|
-
def ask_wrapped(cmd,filenames)
|
248
|
-
ask wrap_filenames(cmd,filenames)
|
249
|
-
end
|
250
|
-
|
251
|
-
def wrap_filenames(cmd,filenames)
|
252
|
-
filenames = [filenames] unless filenames.kind_of?(Array)
|
253
|
-
filenames.map!{ |filename| "\"#{filename}\"" }
|
254
|
-
[cmd,filenames].flatten.join(' ')
|
255
|
-
end
|
256
|
-
|
257
|
-
def parse_files(str)
|
258
|
-
files = {}
|
259
|
-
str.each_line do |line|
|
260
|
-
if line =~ /\s+([\w\.\d\-\_\?\!\s]+)\s+([DAH]?)\s+(\d+)\s+(.+)$/
|
261
|
-
lsplit = line.split(/\s{2,}/)
|
262
|
-
#$stderr.puts "lsplit: #{lsplit}"
|
263
|
-
lsplit.shift ## remove first empty string
|
264
|
-
name = lsplit.shift#$1
|
265
|
-
if lsplit.first =~ /^[A-Za-z]+$/
|
266
|
-
type = lsplit.shift
|
267
|
-
else
|
268
|
-
type = ""
|
269
|
-
end
|
270
|
-
size = lsplit.shift#$3
|
271
|
-
date = lsplit.join(' ')#$4
|
272
|
-
name.gsub!(/\s+$/,'')
|
273
|
-
files[name] = if type =~/^D.*$/
|
274
|
-
{type: :directory, size: size, modified: (Time.parse(date) rescue "!!#{date}")}
|
275
|
-
else
|
276
|
-
{type: :file, size: size , modified: (Time.parse(date) rescue "!!#{date}")}
|
277
|
-
end
|
278
|
-
end
|
279
|
-
end
|
280
|
-
files
|
281
|
-
end
|
282
|
-
|
283
|
-
end
|
284
10
|
end
|
@@ -0,0 +1,258 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'logger'
|
4
|
+
require 'pty'
|
5
|
+
require 'expect'
|
6
|
+
|
7
|
+
module Sambal
|
8
|
+
class Client
|
9
|
+
|
10
|
+
attr_reader :connected
|
11
|
+
|
12
|
+
def initialize(options={})
|
13
|
+
begin
|
14
|
+
options = {domain: 'WORKGROUP', host: '127.0.0.1', share: '', user: 'guest', password: '--no-pass', port: 445, timeout: 10, columns: 80}.merge(options)
|
15
|
+
@timeout = options[:timeout].to_i
|
16
|
+
@o, @i, @pid = PTY.spawn("COLUMNS=#{options[:columns]} smbclient \"//#{options[:host]}/#{options[:share]}\" '#{options[:password]}' -W \"#{options[:domain]}\" -U \"#{options[:user]}\" -p #{options[:port]}")
|
17
|
+
res = @o.expect(/(.*\n)?smb:.*\\>/, @timeout)[0] rescue nil
|
18
|
+
@connected = case res
|
19
|
+
when nil
|
20
|
+
$stderr.puts "Failed to connect"
|
21
|
+
false
|
22
|
+
when /^put/
|
23
|
+
res['putting'].nil? ? false : true
|
24
|
+
else
|
25
|
+
if res['NT_STATUS']
|
26
|
+
false
|
27
|
+
elsif res['timed out'] || res['Server stopped']
|
28
|
+
false
|
29
|
+
else
|
30
|
+
true
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
unless @connected
|
35
|
+
close if @pid
|
36
|
+
exit(1)
|
37
|
+
end
|
38
|
+
rescue Exception => e
|
39
|
+
raise RuntimeError.exception("Unknown Process Failed!! (#{$!.to_s}): #{e.message.inspect}\n"+e.backtrace.join("\n"))
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def logger
|
44
|
+
@logger ||= Logger.new(STDOUT)
|
45
|
+
end
|
46
|
+
|
47
|
+
def logger=(l)
|
48
|
+
@logger = l
|
49
|
+
end
|
50
|
+
|
51
|
+
def file_context(path)
|
52
|
+
if (path_parts = path.split('/')).length>1
|
53
|
+
file = path_parts.pop
|
54
|
+
subdirs = path_parts.length
|
55
|
+
dir = path_parts.join('/')
|
56
|
+
cd dir
|
57
|
+
else
|
58
|
+
file = path
|
59
|
+
end
|
60
|
+
begin
|
61
|
+
yield(file)
|
62
|
+
ensure
|
63
|
+
unless subdirs.nil?
|
64
|
+
subdirs.times { cd '..' }
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def ls(qualifier = '*')
|
70
|
+
parse_files(ask_wrapped('ls', qualifier))
|
71
|
+
end
|
72
|
+
|
73
|
+
def cd(dir)
|
74
|
+
response = ask("cd \"#{dir}\"")
|
75
|
+
if response.split("\r\n").join('') =~ /NT_STATUS_OBJECT_NAME_NOT_FOUND/
|
76
|
+
Response.new(response, false)
|
77
|
+
else
|
78
|
+
Response.new(response, true)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def get(file, output)
|
83
|
+
begin
|
84
|
+
file_context(file) do |file|
|
85
|
+
response = ask_wrapped 'get', [file, output]
|
86
|
+
if response =~ /^getting\sfile.*$/
|
87
|
+
Response.new(response, true)
|
88
|
+
else
|
89
|
+
Response.new(response, false)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
rescue InternalError => e
|
93
|
+
Response.new(e.message, false)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def put(file, destination)
|
98
|
+
response = ask_wrapped 'put', [file, destination]
|
99
|
+
if response =~ /^putting\sfile.*$/
|
100
|
+
Response.new(response, true)
|
101
|
+
else
|
102
|
+
Response.new(response, false)
|
103
|
+
end
|
104
|
+
rescue InternalError => e
|
105
|
+
Response.new(e.message, false)
|
106
|
+
end
|
107
|
+
|
108
|
+
def put_content(content, destination)
|
109
|
+
t = Tempfile.new("upload-smb-content-#{destination}")
|
110
|
+
File.open(t.path, 'w') do |f|
|
111
|
+
f << content
|
112
|
+
end
|
113
|
+
response = ask_wrapped 'put', [t.path, destination]
|
114
|
+
if response =~ /^putting\sfile.*$/
|
115
|
+
Response.new(response, true)
|
116
|
+
else
|
117
|
+
Response.new(response, false)
|
118
|
+
end
|
119
|
+
rescue InternalError => e
|
120
|
+
Response.new(e.message, false)
|
121
|
+
ensure
|
122
|
+
t.close
|
123
|
+
end
|
124
|
+
|
125
|
+
def mkdir(directory)
|
126
|
+
return Response.new('directory name is empty', false) if directory.strip.empty?
|
127
|
+
response = ask_wrapped('mkdir', directory)
|
128
|
+
if response =~ /NT_STATUS_OBJECT_NAME_(INVALID|COLLISION)/
|
129
|
+
Response.new(response, false)
|
130
|
+
else
|
131
|
+
Response.new(response, true)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def rmdir(dir)
|
136
|
+
response = cd dir
|
137
|
+
return response if response.failure?
|
138
|
+
begin
|
139
|
+
ls.each do |name, meta|
|
140
|
+
if meta[:type]==:file
|
141
|
+
response = del name
|
142
|
+
elsif meta[:type]==:directory && !(name =~ /^\.+$/)
|
143
|
+
response = rmdir(name)
|
144
|
+
end
|
145
|
+
raise InternalError.new response.message if response && response.failure?
|
146
|
+
end
|
147
|
+
cd '..'
|
148
|
+
response = ask_wrapped 'rmdir', dir
|
149
|
+
next_line = response.split("\n")[1]
|
150
|
+
if next_line =~ /^smb:.*\\>/
|
151
|
+
Response.new(response, true)
|
152
|
+
else
|
153
|
+
Response.new(response, false)
|
154
|
+
end
|
155
|
+
rescue InternalError => e
|
156
|
+
Response.new(e.message, false)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
def del(file)
|
161
|
+
begin
|
162
|
+
file_context(file) do |file|
|
163
|
+
response = ask_wrapped 'del', file
|
164
|
+
next_line = response.split("\n")[1]
|
165
|
+
if next_line =~ /^smb:.*\\>/
|
166
|
+
Response.new(response, true)
|
167
|
+
#elsif next_line =~ /^NT_STATUS_NO_SUCH_FILE.*$/
|
168
|
+
# Response.new(response, false)
|
169
|
+
#elsif next_line =~ /^NT_STATUS_ACCESS_DENIED.*$/
|
170
|
+
# Response.new(response, false)
|
171
|
+
else
|
172
|
+
Response.new(response, false)
|
173
|
+
end
|
174
|
+
end
|
175
|
+
rescue InternalError => e
|
176
|
+
Response.new(e.message, false)
|
177
|
+
end
|
178
|
+
#end
|
179
|
+
#if (path_parts = file.split('/')).length>1
|
180
|
+
# file = path_parts.pop
|
181
|
+
# subdirs = path_parts.length
|
182
|
+
# dir = path_parts.join('/')
|
183
|
+
# cd dir
|
184
|
+
#end
|
185
|
+
# response = ask "del #{file}"
|
186
|
+
# next_line = response.split("\n")[1]
|
187
|
+
# if next_line =~ /^smb:.*\\>/
|
188
|
+
# Response.new(response, true)
|
189
|
+
# #elsif next_line =~ /^NT_STATUS_NO_SUCH_FILE.*$/
|
190
|
+
# # Response.new(response, false)
|
191
|
+
# #elsif next_line =~ /^NT_STATUS_ACCESS_DENIED.*$/
|
192
|
+
# # Response.new(response, false)
|
193
|
+
# else
|
194
|
+
# Response.new(response, false)
|
195
|
+
# end
|
196
|
+
#rescue InternalError => e
|
197
|
+
# Response.new(e.message, false)
|
198
|
+
#ensure
|
199
|
+
# unless subdirs.nil?
|
200
|
+
# subdirs.times { cd '..' }
|
201
|
+
# end
|
202
|
+
end
|
203
|
+
|
204
|
+
def close
|
205
|
+
@i.close
|
206
|
+
@o.close
|
207
|
+
Process.wait(@pid)
|
208
|
+
@connected = false
|
209
|
+
end
|
210
|
+
|
211
|
+
def ask(cmd)
|
212
|
+
@i.printf("#{cmd}\n")
|
213
|
+
response = @o.expect(/^smb:.*\\>/,@timeout)[0] rescue nil
|
214
|
+
if response.nil?
|
215
|
+
$stderr.puts "Failed to do #{cmd}"
|
216
|
+
raise Exception.new, "Failed to do #{cmd}"
|
217
|
+
else
|
218
|
+
response
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
def ask_wrapped(cmd,filenames)
|
223
|
+
ask wrap_filenames(cmd,filenames)
|
224
|
+
end
|
225
|
+
|
226
|
+
def wrap_filenames(cmd,filenames)
|
227
|
+
filenames = [filenames] unless filenames.kind_of?(Array)
|
228
|
+
filenames.map!{ |filename| "\"#{filename}\"" }
|
229
|
+
[cmd,filenames].flatten.join(' ')
|
230
|
+
end
|
231
|
+
|
232
|
+
def parse_files(str)
|
233
|
+
files = {}
|
234
|
+
str.each_line do |line|
|
235
|
+
if line =~ /\s+([\w\.\d\-\_\?\!\s]+)\s+([DAH]?)\s+(\d+)\s+(.+)$/
|
236
|
+
lsplit = line.split(/\s{2,}/)
|
237
|
+
#$stderr.puts "lsplit: #{lsplit}"
|
238
|
+
lsplit.shift ## remove first empty string
|
239
|
+
name = lsplit.shift#$1
|
240
|
+
if lsplit.first =~ /^[A-Za-z]+$/
|
241
|
+
type = lsplit.shift
|
242
|
+
else
|
243
|
+
type = ""
|
244
|
+
end
|
245
|
+
size = lsplit.shift#$3
|
246
|
+
date = lsplit.join(' ')#$4
|
247
|
+
name.gsub!(/\s+$/,'')
|
248
|
+
files[name] = if type =~/^D.*$/
|
249
|
+
{type: :directory, size: size, modified: (Time.parse(date) rescue "!!#{date}")}
|
250
|
+
else
|
251
|
+
{type: :file, size: size , modified: (Time.parse(date) rescue "!!#{date}")}
|
252
|
+
end
|
253
|
+
end
|
254
|
+
end
|
255
|
+
files
|
256
|
+
end
|
257
|
+
end
|
258
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Sambal
|
2
|
+
class Response
|
3
|
+
|
4
|
+
attr_reader :message
|
5
|
+
|
6
|
+
def initialize(message, success)
|
7
|
+
msg = message.split("\n")
|
8
|
+
msg.each do |line|
|
9
|
+
if line =~ /^NT\_.*\s/
|
10
|
+
@message = line
|
11
|
+
end
|
12
|
+
end
|
13
|
+
@message ||= message
|
14
|
+
@success = success
|
15
|
+
end
|
16
|
+
|
17
|
+
def success?
|
18
|
+
@success
|
19
|
+
end
|
20
|
+
|
21
|
+
def failure?
|
22
|
+
!success?
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/sambal/smb.conf.erb
CHANGED
@@ -34,6 +34,8 @@
|
|
34
34
|
|
35
35
|
## Browsing/Identification ###
|
36
36
|
|
37
|
+
ncalrpc dir = <%= ncalrpc_dir %>
|
38
|
+
|
37
39
|
# Change this to the workgroup/NT-domain name your Samba server will part of
|
38
40
|
workgroup = WORKGROUP
|
39
41
|
|
@@ -75,7 +77,7 @@
|
|
75
77
|
|
76
78
|
# This tells Samba to use a separate log file for each machine
|
77
79
|
# that connects
|
78
|
-
|
80
|
+
log file = <%= log_path %>/log.%m
|
79
81
|
|
80
82
|
# Cap the size of the individual log files (in KiB).
|
81
83
|
max log size = 1000
|
@@ -99,8 +101,8 @@
|
|
99
101
|
# in this server for every user accessing the server. See
|
100
102
|
# /usr/share/doc/samba-doc/htmldocs/Samba3-HOWTO/ServerType.html
|
101
103
|
# in the samba-doc package for details.
|
102
|
-
|
103
|
-
security = share
|
104
|
+
security = user
|
105
|
+
# security = share
|
104
106
|
# we set it to whoever is running the specs
|
105
107
|
guest account = <%= local_user %>
|
106
108
|
|
data/lib/sambal/test_server.rb
CHANGED
@@ -26,20 +26,30 @@ module Sambal
|
|
26
26
|
attr_reader :port
|
27
27
|
attr_reader :share_path
|
28
28
|
attr_reader :root_path
|
29
|
+
attr_reader :tmp_path
|
30
|
+
attr_reader :private_dir
|
31
|
+
attr_reader :cache_dir
|
32
|
+
attr_reader :state_dir
|
29
33
|
attr_reader :config_path
|
30
34
|
attr_reader :share_name
|
31
35
|
attr_reader :run_as
|
32
36
|
attr_reader :host
|
33
37
|
|
34
|
-
def initialize(
|
38
|
+
def initialize(share_name='sambal_test', run_as=ENV['USER'])
|
35
39
|
@erb_path = "#{File.expand_path(File.dirname(__FILE__))}/smb.conf.erb"
|
36
40
|
@host = "127.0.0.1" ## will always just be localhost
|
37
|
-
@root_path =
|
38
|
-
@
|
41
|
+
@root_path = File.expand_path(File.dirname(File.dirname(File.dirname(__FILE__))))
|
42
|
+
@tmp_path = "#{root_path}/spec_tmp"
|
43
|
+
@share_path = "#{tmp_path}/share"
|
39
44
|
@share_name = share_name
|
40
|
-
@config_path = "#{
|
41
|
-
@lock_path = "#{
|
42
|
-
@pid_dir = "#{
|
45
|
+
@config_path = "#{tmp_path}/smb.conf"
|
46
|
+
@lock_path = "#{tmp_path}"
|
47
|
+
@pid_dir = "#{tmp_path}"
|
48
|
+
@cache_dir = "#{tmp_path}"
|
49
|
+
@state_dir = "#{tmp_path}"
|
50
|
+
@log_path = "#{tmp_path}"
|
51
|
+
@private_dir = "#{tmp_path}"
|
52
|
+
@ncalrpc_dir = "#{tmp_path}"
|
43
53
|
@port = Random.new(Time.now.to_i).rand(2345..5678).to_i
|
44
54
|
@run_as = run_as
|
45
55
|
FileUtils.mkdir_p @share_path
|
@@ -53,18 +63,18 @@ module Sambal
|
|
53
63
|
|
54
64
|
def write_config
|
55
65
|
File.open(@config_path, 'w') do |f|
|
56
|
-
f << Document.new(IO.binread(@erb_path)).interpolate(samba_share: @share_path, local_user: @run_as, share_name: @share_name)
|
66
|
+
f << Document.new(IO.binread(@erb_path)).interpolate(samba_share: @share_path, local_user: @run_as, share_name: @share_name, log_path: @log_path, ncalrpc_dir: @ncalrpc_dir)
|
57
67
|
end
|
58
68
|
end
|
59
69
|
|
60
70
|
def start
|
61
71
|
if RUBY_PLATFORM=="java"
|
62
72
|
@smb_server_pid = Thread.new do
|
63
|
-
`smbd -S -F -s #{@config_path} -p #{@port} --lockdir=#{@lock_path} --piddir=#{@pid_dir}`
|
73
|
+
`smbd -S -F -s #{@config_path} -p #{@port} --lockdir=#{@lock_path} --piddir=#{@pid_dir} --private-dir=#{@private_dir} --cachedir=#{@cache_dir} --statedir=#{@state_dir} > #{@log_path}/smb.log`
|
64
74
|
end
|
65
75
|
else
|
66
76
|
@smb_server_pid = fork do
|
67
|
-
`smbd -S -F -s #{@config_path} -p #{@port} --lockdir=#{@lock_path} --piddir=#{@pid_dir}`
|
77
|
+
`smbd -S -F -s #{@config_path} -p #{@port} --lockdir=#{@lock_path} --piddir=#{@pid_dir} --private-dir=#{@private_dir} --cachedir=#{@cache_dir} --statedir=#{@state_dir} > #{@log_path}/smb.log`
|
68
78
|
end
|
69
79
|
end
|
70
80
|
sleep 2 ## takes a short time to start up
|
@@ -78,8 +88,8 @@ module Sambal
|
|
78
88
|
|
79
89
|
def stop!
|
80
90
|
stop
|
81
|
-
FileUtils.rm_rf @
|
91
|
+
FileUtils.rm_rf @tmp_path unless ENV.key?('KEEP_SMB_TMP')
|
82
92
|
end
|
83
93
|
|
84
94
|
end
|
85
|
-
end
|
95
|
+
end
|
data/lib/sambal/version.rb
CHANGED
data/sambal.gemspec
CHANGED
data/spec/sambal/client_spec.rb
CHANGED
@@ -5,31 +5,47 @@ require 'tempfile'
|
|
5
5
|
|
6
6
|
describe Sambal::Client do
|
7
7
|
|
8
|
+
TEST_DIRECTORY_WITH_SPACE_IN_NAME = 'my dir with spaces in name'
|
9
|
+
TEST_FILE_IN_DIRECTORY_WITH_SPACE_IN_NAME = 'a_file_in_a_dir_with_spaces_in_name'
|
10
|
+
TEST_SPACES_IN_NAME_PATH = "#{TEST_DIRECTORY_WITH_SPACE_IN_NAME}/#{TEST_FILE_IN_DIRECTORY_WITH_SPACE_IN_NAME}"
|
11
|
+
TEST_DIRECTORY = 'testdir'
|
12
|
+
TEST_SUB_DIRECTORY = 'testdir_sub'
|
13
|
+
SUB_DIRECTORY_PATH = "#{TEST_DIRECTORY}/#{TEST_SUB_DIRECTORY}"
|
14
|
+
TESTFILE = 'testfile.txt'
|
15
|
+
TESTFILE2 = 'testfile.tx'
|
16
|
+
TESTFILE3 = 'testfil.txt'
|
17
|
+
TESTFILE_SUB = 'testfile_sub.txt'
|
18
|
+
TESTFILE_SUB_PATH = "#{SUB_DIRECTORY_PATH}/#{TESTFILE_SUB}"
|
19
|
+
|
8
20
|
before(:all) do
|
9
21
|
@sambal_client = described_class.new(host: test_server.host, share: test_server.share_name, port: test_server.port)
|
10
22
|
end
|
11
23
|
|
12
24
|
before(:each) do
|
13
|
-
File.open("#{test_server.share_path}/#{
|
25
|
+
File.open("#{test_server.share_path}/#{TESTFILE}", 'w') do |f|
|
14
26
|
f << "Hello"
|
15
27
|
end
|
16
|
-
FileUtils.mkdir_p "#{test_server.share_path}/#{
|
17
|
-
File.open("#{test_server.share_path}/#{
|
28
|
+
FileUtils.mkdir_p "#{test_server.share_path}/#{TEST_DIRECTORY_WITH_SPACE_IN_NAME}"
|
29
|
+
File.open("#{test_server.share_path}/#{TEST_DIRECTORY_WITH_SPACE_IN_NAME}/#{TEST_FILE_IN_DIRECTORY_WITH_SPACE_IN_NAME}", 'w') do |f|
|
18
30
|
f << "Hello there"
|
19
31
|
end
|
20
|
-
FileUtils.mkdir_p "#{test_server.share_path}/#{
|
21
|
-
FileUtils.mkdir_p "#{test_server.share_path}/#{
|
22
|
-
File.open("#{test_server.share_path}/#{
|
32
|
+
FileUtils.mkdir_p "#{test_server.share_path}/#{TEST_DIRECTORY}"
|
33
|
+
FileUtils.mkdir_p "#{test_server.share_path}/#{TEST_DIRECTORY}/#{TEST_SUB_DIRECTORY}"
|
34
|
+
File.open("#{test_server.share_path}/#{TEST_DIRECTORY}/#{TEST_SUB_DIRECTORY}/#{TESTFILE_SUB}", 'w') do |f|
|
23
35
|
f << "Hello"
|
24
36
|
end
|
25
|
-
FileUtils.chmod 0775, "#{test_server.share_path}/#{
|
26
|
-
FileUtils.chmod 0775, "#{test_server.share_path}/#{
|
27
|
-
FileUtils.chmod 0775, "#{test_server.share_path}/#{
|
28
|
-
FileUtils.chmod 0775, "#{test_server.share_path}/#{
|
29
|
-
FileUtils.chmod 0777, "#{test_server.share_path}/#{
|
37
|
+
FileUtils.chmod 0775, "#{test_server.share_path}/#{TEST_DIRECTORY_WITH_SPACE_IN_NAME}/#{TEST_FILE_IN_DIRECTORY_WITH_SPACE_IN_NAME}"
|
38
|
+
FileUtils.chmod 0775, "#{test_server.share_path}/#{TEST_DIRECTORY}/#{TEST_SUB_DIRECTORY}/#{TESTFILE_SUB}"
|
39
|
+
FileUtils.chmod 0775, "#{test_server.share_path}/#{TEST_DIRECTORY}/#{TEST_SUB_DIRECTORY}"
|
40
|
+
FileUtils.chmod 0775, "#{test_server.share_path}/#{TEST_DIRECTORY}"
|
41
|
+
FileUtils.chmod 0777, "#{test_server.share_path}/#{TESTFILE}"
|
30
42
|
@sambal_client.cd('/')
|
31
43
|
end
|
32
44
|
|
45
|
+
after(:each) do
|
46
|
+
FileUtils.rm_rf "#{test_server.share_path}/*"
|
47
|
+
end
|
48
|
+
|
33
49
|
after(:all) do
|
34
50
|
@sambal_client.close
|
35
51
|
end
|
@@ -42,174 +58,175 @@ describe Sambal::Client do
|
|
42
58
|
t
|
43
59
|
end
|
44
60
|
|
45
|
-
let(:test_directory_with_space_in_name) { 'my dir with spaces in name' }
|
46
|
-
|
47
|
-
let(:test_file_in_directory_with_space_in_name) { 'a_file_in_a_dir_with_spaces_in_name' }
|
48
|
-
|
49
|
-
let(:test_spaces_in_name_path) { "#{test_directory_with_space_in_name}/#{test_file_in_directory_with_space_in_name}" }
|
50
|
-
|
51
|
-
let(:test_directory) do
|
52
|
-
'testdir'
|
53
|
-
end
|
54
|
-
|
55
|
-
let(:test_sub_directory) do
|
56
|
-
'testdir_sub'
|
57
|
-
end
|
58
|
-
|
59
|
-
let(:sub_directory_path) do
|
60
|
-
"#{test_directory}/#{test_sub_directory}"
|
61
|
-
end
|
62
|
-
|
63
|
-
let(:testfile) do
|
64
|
-
'testfile.txt'
|
65
|
-
end
|
66
|
-
|
67
|
-
let(:testfile2) do
|
68
|
-
'testfile.tx'
|
69
|
-
end
|
70
|
-
|
71
|
-
let(:testfile3) do
|
72
|
-
'testfil.txt'
|
73
|
-
end
|
74
|
-
|
75
|
-
let(:testfile_sub) do
|
76
|
-
'testfile_sub.txt'
|
77
|
-
end
|
78
|
-
|
79
|
-
let(:testfile_sub_path) do
|
80
|
-
"#{sub_directory_path}/#{testfile_sub}"
|
81
|
-
end
|
82
|
-
|
83
61
|
describe 'ls' do
|
84
62
|
before(:all) do
|
85
|
-
FileUtils.cp "#{test_server.share_path}/#{
|
86
|
-
FileUtils.cp "#{test_server.share_path}/#{
|
63
|
+
FileUtils.cp "#{test_server.share_path}/#{TESTFILE}", "#{test_server.share_path}/#{TESTFILE2}"
|
64
|
+
FileUtils.cp "#{test_server.share_path}/#{TESTFILE}", "#{test_server.share_path}/#{TESTFILE3}"
|
87
65
|
end
|
88
66
|
|
89
67
|
it "should list files with spaces in their names" do
|
90
68
|
result = @sambal_client.ls
|
91
|
-
result.
|
69
|
+
expect(result).to have_key(TEST_DIRECTORY_WITH_SPACE_IN_NAME)
|
92
70
|
end
|
93
71
|
|
94
72
|
it "should list files on an smb server" do
|
95
73
|
result = @sambal_client.ls
|
96
|
-
result.
|
97
|
-
result.
|
98
|
-
result.
|
74
|
+
expect(result).to have_key(TESTFILE)
|
75
|
+
expect(result).to have_key(TESTFILE2)
|
76
|
+
expect(result).to have_key(TESTFILE3)
|
99
77
|
end
|
100
78
|
|
101
79
|
it "should list files using a wildcard on an smb server" do
|
102
80
|
result = @sambal_client.ls '*.txt'
|
103
|
-
result.
|
104
|
-
result.
|
105
|
-
result.
|
81
|
+
expect(result).to have_key(TESTFILE)
|
82
|
+
expect(result).to_not have_key(TESTFILE2)
|
83
|
+
expect(result).to have_key(TESTFILE3)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe 'mkdir' do
|
88
|
+
before(:all) do
|
89
|
+
@sambal_client.cd('/')
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'should create a new directory' do
|
93
|
+
result = @sambal_client.mkdir('test')
|
94
|
+
expect(result).to be_successful
|
95
|
+
|
96
|
+
expect(@sambal_client.ls).to have_key('test')
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'should create a directory with spaces' do
|
100
|
+
result = @sambal_client.mkdir('test spaces directory')
|
101
|
+
expect(result).to be_successful
|
102
|
+
expect(@sambal_client.ls).to have_key('test spaces directory')
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'should not create an invalid directory' do
|
106
|
+
result = @sambal_client.mkdir('**')
|
107
|
+
expect(result).to_not be_successful
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'should not overwrite an existing directory' do
|
111
|
+
# Ensure our test directory exists
|
112
|
+
@sambal_client.rmdir('test')
|
113
|
+
@sambal_client.mkdir('test')
|
114
|
+
expect(@sambal_client.ls).to have_key('test')
|
115
|
+
|
116
|
+
result = @sambal_client.mkdir('test')
|
117
|
+
expect(result).to_not be_successful
|
118
|
+
end
|
119
|
+
|
120
|
+
it 'should handle empty directory names' do
|
121
|
+
expect(@sambal_client.mkdir('')).to_not be_successful
|
122
|
+
expect(@sambal_client.mkdir(' ')).to_not be_successful
|
106
123
|
end
|
107
124
|
end
|
108
125
|
|
109
126
|
it "should get files from an smb server" do
|
110
|
-
@sambal_client.get(
|
111
|
-
File.exists?("/tmp/sambal_spec_testfile.txt").
|
112
|
-
File.size("/tmp/sambal_spec_testfile.txt").
|
127
|
+
expect(@sambal_client.get(TESTFILE, "/tmp/sambal_spec_testfile.txt")).to be_successful
|
128
|
+
expect(File.exists?("/tmp/sambal_spec_testfile.txt")).to eq true
|
129
|
+
expect(File.size("/tmp/sambal_spec_testfile.txt")).to eq @sambal_client.ls[TESTFILE][:size].to_i
|
113
130
|
end
|
114
131
|
|
115
132
|
it "should get files in a dir with spaces in it's name from an smb server" do
|
116
|
-
@sambal_client.get(
|
117
|
-
File.exists?("/tmp/sambal_this_file_was_in_dir_with_spaces.txt").
|
118
|
-
@sambal_client.cd(
|
119
|
-
File.size("/tmp/sambal_this_file_was_in_dir_with_spaces.txt").
|
133
|
+
expect(@sambal_client.get(TEST_SPACES_IN_NAME_PATH, "/tmp/sambal_this_file_was_in_dir_with_spaces.txt")).to be_successful
|
134
|
+
expect(File.exists?("/tmp/sambal_this_file_was_in_dir_with_spaces.txt")).to eq true
|
135
|
+
@sambal_client.cd(TEST_DIRECTORY_WITH_SPACE_IN_NAME)
|
136
|
+
expect(File.size("/tmp/sambal_this_file_was_in_dir_with_spaces.txt")).to eq @sambal_client.ls[TEST_FILE_IN_DIRECTORY_WITH_SPACE_IN_NAME][:size].to_i
|
120
137
|
end
|
121
138
|
|
122
139
|
it "should get files in a subdirectory while in a higher level directory from an smb server" do
|
123
|
-
@sambal_client.get(
|
124
|
-
File.exists?("/tmp/sambal_spec_testfile_sub.txt").
|
125
|
-
@sambal_client.cd(
|
126
|
-
File.size("/tmp/sambal_spec_testfile_sub.txt").
|
140
|
+
expect(@sambal_client.get(TESTFILE_SUB_PATH, "/tmp/sambal_spec_testfile_sub.txt")).to be_successful
|
141
|
+
expect(File.exists?("/tmp/sambal_spec_testfile_sub.txt")).to eq true
|
142
|
+
@sambal_client.cd(SUB_DIRECTORY_PATH)
|
143
|
+
expect(File.size("/tmp/sambal_spec_testfile_sub.txt")).to eq @sambal_client.ls[TESTFILE_SUB][:size].to_i
|
127
144
|
end
|
128
145
|
|
129
146
|
it "should not be successful when getting a file from an smb server fails" do
|
130
147
|
result = @sambal_client.get("non_existant_file.txt", "/tmp/sambal_spec_non_existant_file.txt")
|
131
|
-
result.
|
132
|
-
result.message.
|
133
|
-
result.message.split("\n").
|
134
|
-
File.exists?("/tmp/sambal_spec_non_existant_file.txt").
|
148
|
+
expect(result).to_not be_successful
|
149
|
+
expect(result.message).to match(/^NT_.*$/)
|
150
|
+
expect(result.message.split("\n").size).to eq 1
|
151
|
+
expect(File.exists?("/tmp/sambal_spec_non_existant_file.txt")).to eq false
|
135
152
|
end
|
136
153
|
|
137
154
|
it "should upload files to an smb server" do
|
138
|
-
@sambal_client.ls.
|
139
|
-
@sambal_client.put(file_to_upload.path, 'uploaded_file.txt').
|
140
|
-
@sambal_client.ls.
|
155
|
+
expect(@sambal_client.ls).to_not have_key("uploaded_file.txt")
|
156
|
+
expect(@sambal_client.put(file_to_upload.path, 'uploaded_file.txt')).to be_successful
|
157
|
+
expect(@sambal_client.ls).to have_key("uploaded_file.txt")
|
141
158
|
end
|
142
159
|
|
143
160
|
it "should upload content to an smb server" do
|
144
|
-
@sambal_client.ls.
|
145
|
-
@sambal_client.put_content("Content upload", 'content_uploaded_file.txt').
|
146
|
-
@sambal_client.ls.
|
161
|
+
expect(@sambal_client.ls).to_not have_key("content_uploaded_file.txt")
|
162
|
+
expect(@sambal_client.put_content("Content upload", 'content_uploaded_file.txt')).to be_successful
|
163
|
+
expect(@sambal_client.ls).to have_key("content_uploaded_file.txt")
|
147
164
|
end
|
148
165
|
|
149
166
|
it "should delete files on an smb server" do
|
150
|
-
@sambal_client.del(
|
151
|
-
@sambal_client.ls.
|
167
|
+
expect(@sambal_client.del(TESTFILE)).to be_successful
|
168
|
+
expect(@sambal_client.ls).to_not have_key(TESTFILE)
|
152
169
|
end
|
153
170
|
|
154
171
|
it "should not be successful when deleting a file from an smb server fails" do
|
155
172
|
result = @sambal_client.del("non_existant_file.txt")
|
156
|
-
result.
|
157
|
-
result.message.
|
158
|
-
result.message.split("\n").
|
173
|
+
expect(result).to_not be_successful
|
174
|
+
expect(result.message).to match(/^NT_.*$/)
|
175
|
+
expect(result.message.split("\n").size).to eq 1
|
159
176
|
end
|
160
177
|
|
161
178
|
it "should switch directory on an smb server" do
|
162
|
-
@sambal_client.put_content("testing directories", 'dirtest.txt').
|
163
|
-
@sambal_client.ls.
|
164
|
-
@sambal_client.cd(
|
165
|
-
@sambal_client.ls.
|
166
|
-
@sambal_client.put_content("in #{
|
167
|
-
@sambal_client.ls.
|
168
|
-
@sambal_client.cd('..').
|
169
|
-
@sambal_client.ls.
|
170
|
-
@sambal_client.ls.
|
179
|
+
expect(@sambal_client.put_content("testing directories", 'dirtest.txt')).to be_successful ## a bit stupid, but now we can check that this isn't listed when we switch dirs
|
180
|
+
expect(@sambal_client.ls).to have_key('dirtest.txt')
|
181
|
+
expect(@sambal_client.cd(TEST_DIRECTORY)).to be_successful
|
182
|
+
expect(@sambal_client.ls).to_not have_key('dirtest.txt')
|
183
|
+
expect(@sambal_client.put_content("in #{TEST_DIRECTORY}", 'intestdir.txt')).to be_successful
|
184
|
+
expect(@sambal_client.ls).to have_key('intestdir.txt')
|
185
|
+
expect(@sambal_client.cd('..')).to be_successful
|
186
|
+
expect(@sambal_client.ls).to_not have_key('intestdir.txt')
|
187
|
+
expect(@sambal_client.ls).to have_key('dirtest.txt')
|
171
188
|
end
|
172
189
|
|
173
190
|
it "should delete files in subdirectory while in a higher level directory" do
|
174
191
|
@sambal_client.cd('/')
|
175
|
-
@sambal_client.cd(
|
176
|
-
@sambal_client.put_content("some content", "file_to_delete").
|
192
|
+
@sambal_client.cd(TEST_DIRECTORY)
|
193
|
+
expect(@sambal_client.put_content("some content", "file_to_delete")).to be_successful
|
177
194
|
@sambal_client.cd('/')
|
178
|
-
@sambal_client.del("#{
|
195
|
+
expect(@sambal_client.del("#{TEST_DIRECTORY}/file_to_delete")).to be_successful
|
179
196
|
@sambal_client.cd('/')
|
180
|
-
@sambal_client.ls.
|
197
|
+
expect(@sambal_client.ls).to have_key("#{TESTFILE}")
|
181
198
|
end
|
182
199
|
|
183
200
|
it "should recursively delete a directory" do
|
184
201
|
@sambal_client.cd('/')
|
185
|
-
@sambal_client.cd(
|
186
|
-
@sambal_client.put_content("some content", "file_to_delete").
|
202
|
+
@sambal_client.cd(TEST_DIRECTORY)
|
203
|
+
expect(@sambal_client.put_content("some content", "file_to_delete")).to be_successful
|
187
204
|
@sambal_client.cd('/')
|
188
|
-
@sambal_client.rmdir("#{
|
205
|
+
expect(@sambal_client.rmdir("#{TEST_DIRECTORY}")).to be_successful
|
189
206
|
@sambal_client.cd('/')
|
190
|
-
@sambal_client.ls.
|
207
|
+
expect(@sambal_client.ls).to_not have_key("#{TEST_DIRECTORY}")
|
191
208
|
end
|
192
209
|
|
193
210
|
it "should not be successful when recursively deleting a nonexistant directory" do
|
194
211
|
@sambal_client.cd('/')
|
195
|
-
@sambal_client.rmdir("this_doesnt_exist").
|
212
|
+
expect(@sambal_client.rmdir("this_doesnt_exist")).to_not be_successful
|
196
213
|
end
|
197
214
|
|
198
215
|
it "should not be successful when command fails" do
|
199
216
|
result = @sambal_client.put("jhfahsf iasifasifh", "jsfijsf ijidjag")
|
200
|
-
result.
|
217
|
+
expect(result).to_not be_successful
|
201
218
|
end
|
202
219
|
|
203
220
|
it 'should create commands with one wrapped filename' do
|
204
|
-
@sambal_client.wrap_filenames('cmd','file1').
|
221
|
+
expect(@sambal_client.wrap_filenames('cmd','file1')).to eq('cmd "file1"')
|
205
222
|
end
|
206
223
|
|
207
224
|
it 'should create commands with more than one wrapped filename' do
|
208
|
-
@sambal_client.wrap_filenames('cmd',['file1','file2']).
|
225
|
+
expect(@sambal_client.wrap_filenames('cmd',['file1','file2'])).to eq('cmd "file1" "file2"')
|
209
226
|
end
|
210
227
|
|
211
228
|
it 'should create commands with pathnames instead of strings' do
|
212
|
-
@sambal_client.wrap_filenames('cmd',[Pathname.new('file1'), Pathname.new('file2')]).
|
229
|
+
expect(@sambal_client.wrap_filenames('cmd',[Pathname.new('file1'), Pathname.new('file2')])).to eq('cmd "file1" "file2"')
|
213
230
|
end
|
214
231
|
|
215
232
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -9,10 +9,11 @@ $:.unshift(lib_path) if File.directory?(lib_path) && !$:.include?(lib_path)
|
|
9
9
|
|
10
10
|
require 'sambal'
|
11
11
|
require 'sambal/test_server'
|
12
|
+
require 'rspec/expectations'
|
12
13
|
|
13
14
|
RSpec::Matchers.define :be_successful do
|
14
15
|
match do |actual|
|
15
|
-
actual.success
|
16
|
+
actual.success? == true
|
16
17
|
end
|
17
18
|
end
|
18
19
|
|
@@ -31,7 +32,7 @@ RSpec.configure do |config|
|
|
31
32
|
# config.mock_with :flexmock
|
32
33
|
# config.mock_with :rr
|
33
34
|
config.mock_with :rspec
|
34
|
-
|
35
|
+
|
35
36
|
## perhaps this should be removed as well
|
36
37
|
## and done in Rakefile?
|
37
38
|
config.color = true
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sambal
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Axel Eriksson
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-01-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 3.4.0
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: 3.4.0
|
27
27
|
description: Ruby Samba Client using the cmdline smbclient
|
28
28
|
email:
|
29
29
|
- john@insane.se
|
@@ -36,7 +36,11 @@ files:
|
|
36
36
|
- LICENSE
|
37
37
|
- README.md
|
38
38
|
- Rakefile
|
39
|
+
- Spookfile
|
40
|
+
- circle.yml
|
39
41
|
- lib/sambal.rb
|
42
|
+
- lib/sambal/client.rb
|
43
|
+
- lib/sambal/response.rb
|
40
44
|
- lib/sambal/smb.conf.erb
|
41
45
|
- lib/sambal/test_server.rb
|
42
46
|
- lib/sambal/version.rb
|