sambal 0.1.6 → 0.1.7
Sign up to get free protection for your applications and to get access to all the features.
- 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
|