mixlib-shellout 1.1.0-x86-mingw32 → 1.2.0.rc.0-x86-mingw32

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.
data/LICENSE CHANGED
File without changes
data/README.md CHANGED
@@ -36,6 +36,12 @@ Invoke crontab to edit user cron:
36
36
  crontab = Mixlib::ShellOut.new("crontab -l -u #{@new_resource.user}", :input => crontab_lines.join("\n"))
37
37
  crontab.run_command
38
38
 
39
+ ## Windows Impersonation Example
40
+ Invoke crontab to edit user cron:
41
+
42
+ whomai = Mixlib::ShellOut.new("whoami.exe", :user => "username", :domain => "DOMAIN", :password => "password")
43
+ whoami.run_command
44
+
39
45
  ## Platform Support
40
46
  Mixlib::ShellOut does a standard fork/exec on Unix, and uses the Win32
41
47
  API on Windows. There is not currently support for JRuby.
@@ -39,6 +39,9 @@ module Mixlib
39
39
 
40
40
  # User the command will run as. Normally set via options passed to new
41
41
  attr_accessor :user
42
+ attr_accessor :domain
43
+ attr_accessor :password
44
+ attr_accessor :with_logon
42
45
 
43
46
  # Group the command will run as. Normally set via options passed to new
44
47
  attr_accessor :group
@@ -213,7 +216,7 @@ module Mixlib
213
216
  # * Errno::ENOENT when the command is not available on the system (or not
214
217
  # in the current $PATH)
215
218
  # * CommandTimeout when the command does not complete
216
- # within +timeout+ seconds (default: 60s)
219
+ # within +timeout+ seconds (default: 600s)
217
220
  def run_command
218
221
  if logger
219
222
  log_message = (log_tag.nil? ? "" : "#@log_tag ") << "sh(#@command)"
@@ -261,8 +264,13 @@ module Mixlib
261
264
  case option.to_s
262
265
  when 'cwd'
263
266
  self.cwd = setting
267
+ when 'domain'
268
+ self.domain = setting
269
+ when 'password'
270
+ self.password = setting
264
271
  when 'user'
265
272
  self.user = setting
273
+ self.with_logon = setting
266
274
  when 'group'
267
275
  self.group = setting
268
276
  when 'umask'
@@ -288,8 +296,12 @@ module Mixlib
288
296
  raise InvalidCommandOption, "option '#{option.inspect}' is not a valid option for #{self.class.name}"
289
297
  end
290
298
  end
291
- end
292
299
 
300
+ validate_options(opts)
301
+ end
293
302
 
303
+ def validate_options(opts)
304
+ super
305
+ end
294
306
  end
295
307
  end
File without changes
@@ -20,6 +20,11 @@ module Mixlib
20
20
  class ShellOut
21
21
  module Unix
22
22
 
23
+ # Option validation that is unix specific
24
+ def validate_options(opts)
25
+ # No options to validate, raise exceptions here if needed
26
+ end
27
+
23
28
  # Run the command, writing the command's standard out and standard error
24
29
  # to +stdout+ and +stderr+, and saving its exit status object to +status+
25
30
  # === Returns
@@ -30,11 +35,20 @@ module Mixlib
30
35
  # * Errno::ENOENT when the command is not available on the system (or not
31
36
  # in the current $PATH)
32
37
  # * Chef::Exceptions::CommandTimeout when the command does not complete
33
- # within +timeout+ seconds (default: 60s)
38
+ # within +timeout+ seconds (default: 600s)
34
39
  def run_command
35
40
  @child_pid = fork_subprocess
36
41
 
37
42
  configure_parent_process_file_descriptors
43
+
44
+ # Ruby 1.8.7 and 1.8.6 from mid 2009 try to allocate objects during GC
45
+ # when calling IO.select and IO#read. Some OS Vendors are not interested
46
+ # in updating their ruby packages (Apple, *cough*) and we *have to*
47
+ # make it work. So I give you this epic hack:
48
+ GC.disable
49
+
50
+ # CHEF-3390: Marshall.load on Ruby < 1.8.7p369 also has a GC bug related
51
+ # to Marshall.load, so try disabling GC first.
38
52
  propagate_pre_exec_failure
39
53
 
40
54
  @result = nil
@@ -42,11 +56,6 @@ module Mixlib
42
56
 
43
57
  write_to_child_stdin
44
58
 
45
- # Ruby 1.8.7 and 1.8.6 from mid 2009 try to allocate objects during GC
46
- # when calling IO.select and IO#read. Some OS Vendors are not interested
47
- # in updating their ruby packages (Apple, *cough*) and we *have to*
48
- # make it work. So I give you this epic hack:
49
- GC.disable
50
59
  until @status
51
60
  ready = IO.select(open_pipes, nil, nil, READ_WAIT_TIME)
52
61
  unless ready
@@ -169,6 +178,28 @@ module Mixlib
169
178
  STDIN.sync = true if input
170
179
  end
171
180
 
181
+ # When a new process is started with chef, it shares the file
182
+ # descriptors of the parent. We clean the file descriptors
183
+ # coming from the parent to prevent unintended locking if parent
184
+ # is killed.
185
+ # NOTE: After some discussions we've decided to iterate on file
186
+ # descriptors upto 256. We believe this is a reasonable upper
187
+ # limit in a chef environment. If we have issues in the future this
188
+ # number could be made to be configurable or updated based on
189
+ # the ulimit based on platform.
190
+ def clean_parent_file_descriptors
191
+ # Don't clean $stdin, $stdout, $stderr, process_status_pipe.
192
+ 3.upto(256) do |n|
193
+ # We are checking the fd for error pipe before attempting to
194
+ # create a file because error pipe will auto close when we
195
+ # try to create a file since it's set to CLOEXEC.
196
+ if n != @process_status_pipe.last.to_i
197
+ fd = File.for_fd(n) rescue nil
198
+ fd.close if fd
199
+ end
200
+ end
201
+ end
202
+
172
203
  def configure_parent_process_file_descriptors
173
204
  # Close the sides of the pipes we don't care about
174
205
  stdin_pipe.first.close
@@ -222,6 +253,8 @@ module Mixlib
222
253
  fork do
223
254
  configure_subprocess_file_descriptors
224
255
 
256
+ clean_parent_file_descriptors
257
+
225
258
  set_group
226
259
  set_user
227
260
  set_environment
@@ -1,5 +1,5 @@
1
1
  module Mixlib
2
2
  class ShellOut
3
- VERSION = "1.1.0"
3
+ VERSION = "1.2.0.rc.0"
4
4
  end
5
5
  end
@@ -35,6 +35,15 @@ module Mixlib
35
35
 
36
36
  TIME_SLICE = 0.05
37
37
 
38
+ # Option validation that is windows specific
39
+ def validate_options(opts)
40
+ if opts[:user]
41
+ unless opts[:password]
42
+ raise InvalidCommandOption, "You must supply both a username and password when supplying a user in windows"
43
+ end
44
+ end
45
+ end
46
+
38
47
  #--
39
48
  # Missing lots of features from the UNIX version, such as
40
49
  # uid, etc.
@@ -66,6 +75,10 @@ module Mixlib
66
75
  :close_handles => false
67
76
  }
68
77
  create_process_args[:cwd] = cwd if cwd
78
+ # default to local account database if domain is not specified
79
+ create_process_args[:domain] = domain.nil? ? "." : domain
80
+ create_process_args[:with_logon] = with_logon if with_logon
81
+ create_process_args[:password] = password if password
69
82
 
70
83
  #
71
84
  # Start the process
@@ -18,40 +18,65 @@
18
18
  #
19
19
 
20
20
  require 'win32/process'
21
- require 'windows/handle'
22
- require 'windows/process'
23
- require 'windows/synchronize'
24
21
 
25
- # Override module Windows::Process.CreateProcess to fix bug when
26
- # using both app_name and command_line
27
- #
28
- module Windows
29
- module Process
30
- API.new('CreateProcess', 'SPPPLLLPPP', 'B')
22
+ # Add new constants for Logon
23
+ module Process::Constants
24
+ LOGON32_LOGON_INTERACTIVE = 0x00000002
25
+ LOGON32_PROVIDER_DEFAULT = 0x00000000
26
+ UOI_NAME = 0x00000002
27
+ end
28
+
29
+ # Define the functions needed to check with Service windows station
30
+ module Process::Functions
31
+ module FFI::Library
32
+ # Wrapper method for attach_function + private
33
+ def attach_pfunc(*args)
34
+ attach_function(*args)
35
+ private args[0]
36
+ end
31
37
  end
38
+
39
+ extend FFI::Library
40
+
41
+ ffi_lib :advapi32
42
+
43
+ attach_pfunc :LogonUserW,
44
+ [:buffer_in, :buffer_in, :buffer_in, :ulong, :ulong, :pointer], :bool
45
+
46
+ attach_pfunc :CreateProcessAsUserW,
47
+ [:ulong, :buffer_in, :buffer_in, :pointer, :pointer, :bool,
48
+ :ulong, :buffer_in, :buffer_in, :pointer, :pointer], :bool
49
+
50
+ ffi_lib :user32
51
+
52
+ attach_pfunc :GetProcessWindowStation,
53
+ [], :ulong
54
+
55
+ attach_pfunc :GetUserObjectInformationA,
56
+ [:ulong, :uint, :buffer_out, :ulong, :pointer], :bool
32
57
  end
33
58
 
34
- #
35
- # Override Win32::Process.create to take a proper environment hash
36
- # so that variables can contain semicolons
37
- # (submitted patch to owner)
38
- #
59
+ # Override Process.create to check for running in the Service window station and doing
60
+ # a full logon with LogonUser, instead of a CreateProcessWithLogon
39
61
  module Process
62
+ include Process::Constants
63
+ include Process::Structs
64
+
40
65
  def create(args)
41
66
  unless args.kind_of?(Hash)
42
- raise TypeError, 'Expecting hash-style keyword arguments'
67
+ raise TypeError, 'hash keyword arguments expected'
43
68
  end
44
69
 
45
- valid_keys = %w/
70
+ valid_keys = %w[
46
71
  app_name command_line inherit creation_flags cwd environment
47
72
  startup_info thread_inherit process_inherit close_handles with_logon
48
73
  domain password
49
- /
74
+ ]
50
75
 
51
- valid_si_keys = %/
76
+ valid_si_keys = %w[
52
77
  startf_flags desktop title x y x_size y_size x_count_chars
53
78
  y_count_chars fill_attribute sw_flags stdin stdout stderr
54
- /
79
+ ]
55
80
 
56
81
  # Set default values
57
82
  hash = {
@@ -93,46 +118,43 @@ module Process
93
118
  end
94
119
  end
95
120
 
96
- # The environment string should be passed as an array of A=B paths, or
97
- # as a string of ';' separated paths.
121
+ env = nil
122
+
123
+ # The env string should be passed as a string of ';' separated paths.
98
124
  if hash['environment']
99
125
  env = hash['environment']
100
- if !env.respond_to?(:join)
101
- # Backwards compat for ; separated paths
126
+
127
+ unless env.respond_to?(:join)
102
128
  env = hash['environment'].split(File::PATH_SEPARATOR)
103
129
  end
104
- # The argument format is a series of null-terminated strings, with an additional null terminator.
105
- env = env.map { |e| e + "\0" }.join("") + "\0"
106
- if hash['with_logon']
107
- env = env.multi_to_wide(e)
108
- end
109
- env = [env].pack('p*').unpack('L').first
110
- else
111
- env = nil
112
- end
113
130
 
114
- startinfo = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
115
- startinfo = startinfo.pack('LLLLLLLLLLLLSSLLLL')
116
- procinfo = [0,0,0,0].pack('LLLL')
131
+ env = env.map{ |e| e + 0.chr }.join('') + 0.chr
132
+ env.to_wide_string! if hash['with_logon']
133
+ end
117
134
 
118
135
  # Process SECURITY_ATTRIBUTE structure
119
- process_security = 0
136
+ process_security = nil
137
+
120
138
  if hash['process_inherit']
121
- process_security = [0,0,0].pack('LLL')
122
- process_security[0,4] = [12].pack('L') # sizeof(SECURITY_ATTRIBUTE)
123
- process_security[8,4] = [1].pack('L') # TRUE
139
+ process_security = SECURITY_ATTRIBUTES.new
140
+ process_security[:nLength] = 12
141
+ process_security[:bInheritHandle] = true
124
142
  end
125
143
 
126
144
  # Thread SECURITY_ATTRIBUTE structure
127
- thread_security = 0
145
+ thread_security = nil
146
+
128
147
  if hash['thread_inherit']
129
- thread_security = [0,0,0].pack('LLL')
130
- thread_security[0,4] = [12].pack('L') # sizeof(SECURITY_ATTRIBUTE)
131
- thread_security[8,4] = [1].pack('L') # TRUE
148
+ thread_security = SECURITY_ATTRIBUTES.new
149
+ thread_security[:nLength] = 12
150
+ thread_security[:bInheritHandle] = true
132
151
  end
133
152
 
134
153
  # Automatically handle stdin, stdout and stderr as either IO objects
135
- # or file descriptors. This won't work for StringIO, however.
154
+ # or file descriptors. This won't work for StringIO, however. It also
155
+ # will not work on JRuby because of the way it handles internal file
156
+ # descriptors.
157
+ #
136
158
  ['stdin', 'stdout', 'stderr'].each{ |io|
137
159
  if si_hash[io]
138
160
  if si_hash[io].respond_to?(:fileno)
@@ -142,7 +164,15 @@ module Process
142
164
  end
143
165
 
144
166
  if handle == INVALID_HANDLE_VALUE
145
- raise Error, get_last_error
167
+ ptr = FFI::MemoryPointer.new(:int)
168
+
169
+ if windows_version >= 6 && get_errno(ptr) == 0
170
+ errno = ptr.read_int
171
+ else
172
+ errno = FFI.errno
173
+ end
174
+
175
+ raise SystemCallError.new("get_osfhandle", errno)
146
176
  end
147
177
 
148
178
  # Most implementations of Ruby on Windows create inheritable
@@ -153,7 +183,7 @@ module Process
153
183
  HANDLE_FLAG_INHERIT
154
184
  )
155
185
 
156
- raise Error, get_last_error unless bool
186
+ raise SystemCallError.new("SetHandleInformation", FFI.errno) unless bool
157
187
 
158
188
  si_hash[io] = handle
159
189
  si_hash['startf_flags'] ||= 0
@@ -162,224 +192,172 @@ module Process
162
192
  end
163
193
  }
164
194
 
165
- # The bytes not covered here are reserved (null)
195
+ procinfo = PROCESS_INFORMATION.new
196
+ startinfo = STARTUPINFO.new
197
+
166
198
  unless si_hash.empty?
167
- startinfo[0,4] = [startinfo.size].pack('L')
168
- startinfo[8,4] = [si_hash['desktop']].pack('p*') if si_hash['desktop']
169
- startinfo[12,4] = [si_hash['title']].pack('p*') if si_hash['title']
170
- startinfo[16,4] = [si_hash['x']].pack('L') if si_hash['x']
171
- startinfo[20,4] = [si_hash['y']].pack('L') if si_hash['y']
172
- startinfo[24,4] = [si_hash['x_size']].pack('L') if si_hash['x_size']
173
- startinfo[28,4] = [si_hash['y_size']].pack('L') if si_hash['y_size']
174
- startinfo[32,4] = [si_hash['x_count_chars']].pack('L') if si_hash['x_count_chars']
175
- startinfo[36,4] = [si_hash['y_count_chars']].pack('L') if si_hash['y_count_chars']
176
- startinfo[40,4] = [si_hash['fill_attribute']].pack('L') if si_hash['fill_attribute']
177
- startinfo[44,4] = [si_hash['startf_flags']].pack('L') if si_hash['startf_flags']
178
- startinfo[48,2] = [si_hash['sw_flags']].pack('S') if si_hash['sw_flags']
179
- startinfo[56,4] = [si_hash['stdin']].pack('L') if si_hash['stdin']
180
- startinfo[60,4] = [si_hash['stdout']].pack('L') if si_hash['stdout']
181
- startinfo[64,4] = [si_hash['stderr']].pack('L') if si_hash['stderr']
199
+ startinfo[:cb] = startinfo.size
200
+ startinfo[:lpDesktop] = si_hash['desktop'] if si_hash['desktop']
201
+ startinfo[:lpTitle] = si_hash['title'] if si_hash['title']
202
+ startinfo[:dwX] = si_hash['x'] if si_hash['x']
203
+ startinfo[:dwY] = si_hash['y'] if si_hash['y']
204
+ startinfo[:dwXSize] = si_hash['x_size'] if si_hash['x_size']
205
+ startinfo[:dwYSize] = si_hash['y_size'] if si_hash['y_size']
206
+ startinfo[:dwXCountChars] = si_hash['x_count_chars'] if si_hash['x_count_chars']
207
+ startinfo[:dwYCountChars] = si_hash['y_count_chars'] if si_hash['y_count_chars']
208
+ startinfo[:dwFillAttribute] = si_hash['fill_attribute'] if si_hash['fill_attribute']
209
+ startinfo[:dwFlags] = si_hash['startf_flags'] if si_hash['startf_flags']
210
+ startinfo[:wShowWindow] = si_hash['sw_flags'] if si_hash['sw_flags']
211
+ startinfo[:cbReserved2] = 0
212
+ startinfo[:hStdInput] = si_hash['stdin'] if si_hash['stdin']
213
+ startinfo[:hStdOutput] = si_hash['stdout'] if si_hash['stdout']
214
+ startinfo[:hStdError] = si_hash['stderr'] if si_hash['stderr']
215
+ end
216
+
217
+ app = nil
218
+ cmd = nil
219
+
220
+ # Convert strings to wide character strings if present
221
+ if hash['app_name']
222
+ app = hash['app_name'].to_wide_string
223
+ end
224
+
225
+ if hash['command_line']
226
+ cmd = hash['command_line'].to_wide_string
227
+ end
228
+
229
+ if hash['cwd']
230
+ cwd = hash['cwd'].to_wide_string
182
231
  end
183
232
 
233
+ inherit = hash['inherit'] || false
234
+
184
235
  if hash['with_logon']
185
- logon = multi_to_wide(hash['with_logon'])
186
- domain = multi_to_wide(hash['domain'])
187
- app = hash['app_name'].nil? ? nil : multi_to_wide(hash['app_name'])
188
- cmd = hash['command_line'].nil? ? nil : multi_to_wide(hash['command_line'])
189
- cwd = multi_to_wide(hash['cwd'])
190
- passwd = multi_to_wide(hash['password'])
236
+ logon = hash['with_logon'].to_wide_string
237
+
238
+ if hash['password']
239
+ passwd = hash['password'].to_wide_string
240
+ else
241
+ raise ArgumentError, 'password must be specified if with_logon is used'
242
+ end
243
+
244
+ if hash['domain']
245
+ domain = hash['domain'].to_wide_string
246
+ end
191
247
 
192
248
  hash['creation_flags'] |= CREATE_UNICODE_ENVIRONMENT
193
249
 
194
- process_ran = CreateProcessWithLogonW(
195
- logon, # User
196
- domain, # Domain
197
- passwd, # Password
198
- LOGON_WITH_PROFILE, # Logon flags
199
- app, # App name
200
- cmd, # Command line
201
- hash['creation_flags'], # Creation flags
202
- env, # Environment
203
- cwd, # Working directory
204
- startinfo, # Startup Info
205
- procinfo # Process Info
250
+ winsta_name = FFI::MemoryPointer.new(:char, 256)
251
+ return_size = FFI::MemoryPointer.new(:ulong)
252
+
253
+ bool = GetUserObjectInformationA(
254
+ GetProcessWindowStation(), # Window station handle
255
+ UOI_NAME, # Information to get
256
+ winsta_name, # Buffer to receive information
257
+ winsta_name.size, # Size of buffer
258
+ return_size # Size filled into buffer
206
259
  )
260
+
261
+ unless bool
262
+ raise SystemCallError.new("GetUserObjectInformationA", FFI.errno)
263
+ end
264
+
265
+ winsta_name = winsta_name.read_string(return_size.read_ulong)
266
+
267
+ # If running in the service windows station must do a log on to get
268
+ # to the interactive desktop. Running process user account must have
269
+ # the 'Replace a process level token' permission. This is necessary as
270
+ # the logon (which happens with CreateProcessWithLogon) must have an
271
+ # interactive windows station to attach to, which is created with the
272
+ # LogonUser cann with the LOGON32_LOGON_INTERACTIVE flag.
273
+ if winsta_name =~ /^Service-0x0-.*$/i
274
+ token = FFI::MemoryPointer.new(:ulong)
275
+
276
+ bool = LogonUserW(
277
+ logon, # User
278
+ domain, # Domain
279
+ passwd, # Password
280
+ LOGON32_LOGON_INTERACTIVE, # Logon Type
281
+ LOGON32_PROVIDER_DEFAULT, # Logon Provider
282
+ token # User token handle
283
+ )
284
+
285
+ unless bool
286
+ raise SystemCallError.new("LogonUserW", FFI.errno)
287
+ end
288
+
289
+ token = token.read_ulong
290
+
291
+ bool = CreateProcessAsUserW(
292
+ token, # User token handle
293
+ app, # App name
294
+ cmd, # Command line
295
+ process_security, # Process attributes
296
+ thread_security, # Thread attributes
297
+ inherit, # Inherit handles
298
+ hash['creation_flags'], # Creation Flags
299
+ env, # Environment
300
+ cwd, # Working directory
301
+ startinfo, # Startup Info
302
+ procinfo # Process Info
303
+ )
304
+
305
+ unless bool
306
+ raise SystemCallError.new("CreateProcessAsUserW (You must hold the 'Replace a process level token' permission)", FFI.errno)
307
+ end
308
+ else
309
+ bool = CreateProcessWithLogonW(
310
+ logon, # User
311
+ domain, # Domain
312
+ passwd, # Password
313
+ LOGON_WITH_PROFILE, # Logon flags
314
+ app, # App name
315
+ cmd, # Command line
316
+ hash['creation_flags'], # Creation flags
317
+ env, # Environment
318
+ cwd, # Working directory
319
+ startinfo, # Startup Info
320
+ procinfo # Process Info
321
+ )
322
+ end
323
+
324
+ unless bool
325
+ raise SystemCallError.new("CreateProcessWithLogonW", FFI.errno)
326
+ end
207
327
  else
208
- process_ran = CreateProcess(
209
- hash['app_name'], # App name
210
- hash['command_line'], # Command line
328
+ bool = CreateProcessW(
329
+ app, # App name
330
+ cmd, # Command line
211
331
  process_security, # Process attributes
212
332
  thread_security, # Thread attributes
213
- hash['inherit'], # Inherit handles?
333
+ inherit, # Inherit handles?
214
334
  hash['creation_flags'], # Creation flags
215
335
  env, # Environment
216
- hash['cwd'], # Working directory
336
+ cwd, # Working directory
217
337
  startinfo, # Startup Info
218
338
  procinfo # Process Info
219
339
  )
220
- end
221
340
 
222
- # TODO: Close stdin, stdout and stderr handles in the si_hash unless
223
- # they're pointing to one of the standard handles already. [Maybe]
224
- if !process_ran
225
- raise_last_error("CreateProcess()")
341
+ unless bool
342
+ raise SystemCallError.new("CreateProcessW", FFI.errno)
343
+ end
226
344
  end
227
345
 
228
346
  # Automatically close the process and thread handles in the
229
347
  # PROCESS_INFORMATION struct unless explicitly told not to.
230
348
  if hash['close_handles']
231
- CloseHandle(procinfo[0,4].unpack('L').first)
232
- CloseHandle(procinfo[4,4].unpack('L').first)
349
+ CloseHandle(procinfo[:hProcess])
350
+ CloseHandle(procinfo[:hThread])
351
+ CloseHandle(token)
233
352
  end
234
353
 
235
354
  ProcessInfo.new(
236
- procinfo[0,4].unpack('L').first, # hProcess
237
- procinfo[4,4].unpack('L').first, # hThread
238
- procinfo[8,4].unpack('L').first, # hProcessId
239
- procinfo[12,4].unpack('L').first # hThreadId
355
+ procinfo[:hProcess],
356
+ procinfo[:hThread],
357
+ procinfo[:dwProcessId],
358
+ procinfo[:dwThreadId]
240
359
  )
241
360
  end
242
361
 
243
- def self.raise_last_error(operation)
244
- error_string = "#{operation} failed: #{get_last_error}"
245
- last_error_code = GetLastError()
246
- if ERROR_CODE_MAP.has_key?(last_error_code)
247
- raise ERROR_CODE_MAP[last_error_code], error_string
248
- else
249
- raise Error, error_string
250
- end
251
- end
252
-
253
- # List from ruby/win32/win32.c
254
- ERROR_CODE_MAP = {
255
- ERROR_INVALID_FUNCTION => Errno::EINVAL,
256
- ERROR_FILE_NOT_FOUND => Errno::ENOENT,
257
- ERROR_PATH_NOT_FOUND => Errno::ENOENT,
258
- ERROR_TOO_MANY_OPEN_FILES => Errno::EMFILE,
259
- ERROR_ACCESS_DENIED => Errno::EACCES,
260
- ERROR_INVALID_HANDLE => Errno::EBADF,
261
- ERROR_ARENA_TRASHED => Errno::ENOMEM,
262
- ERROR_NOT_ENOUGH_MEMORY => Errno::ENOMEM,
263
- ERROR_INVALID_BLOCK => Errno::ENOMEM,
264
- ERROR_BAD_ENVIRONMENT => Errno::E2BIG,
265
- ERROR_BAD_FORMAT => Errno::ENOEXEC,
266
- ERROR_INVALID_ACCESS => Errno::EINVAL,
267
- ERROR_INVALID_DATA => Errno::EINVAL,
268
- ERROR_INVALID_DRIVE => Errno::ENOENT,
269
- ERROR_CURRENT_DIRECTORY => Errno::EACCES,
270
- ERROR_NOT_SAME_DEVICE => Errno::EXDEV,
271
- ERROR_NO_MORE_FILES => Errno::ENOENT,
272
- ERROR_WRITE_PROTECT => Errno::EROFS,
273
- ERROR_BAD_UNIT => Errno::ENODEV,
274
- ERROR_NOT_READY => Errno::ENXIO,
275
- ERROR_BAD_COMMAND => Errno::EACCES,
276
- ERROR_CRC => Errno::EACCES,
277
- ERROR_BAD_LENGTH => Errno::EACCES,
278
- ERROR_SEEK => Errno::EIO,
279
- ERROR_NOT_DOS_DISK => Errno::EACCES,
280
- ERROR_SECTOR_NOT_FOUND => Errno::EACCES,
281
- ERROR_OUT_OF_PAPER => Errno::EACCES,
282
- ERROR_WRITE_FAULT => Errno::EIO,
283
- ERROR_READ_FAULT => Errno::EIO,
284
- ERROR_GEN_FAILURE => Errno::EACCES,
285
- ERROR_LOCK_VIOLATION => Errno::EACCES,
286
- ERROR_SHARING_VIOLATION => Errno::EACCES,
287
- ERROR_WRONG_DISK => Errno::EACCES,
288
- ERROR_SHARING_BUFFER_EXCEEDED => Errno::EACCES,
289
- # ERROR_BAD_NETPATH => Errno::ENOENT,
290
- # ERROR_NETWORK_ACCESS_DENIED => Errno::EACCES,
291
- # ERROR_BAD_NET_NAME => Errno::ENOENT,
292
- ERROR_FILE_EXISTS => Errno::EEXIST,
293
- ERROR_CANNOT_MAKE => Errno::EACCES,
294
- ERROR_FAIL_I24 => Errno::EACCES,
295
- ERROR_INVALID_PARAMETER => Errno::EINVAL,
296
- ERROR_NO_PROC_SLOTS => Errno::EAGAIN,
297
- ERROR_DRIVE_LOCKED => Errno::EACCES,
298
- ERROR_BROKEN_PIPE => Errno::EPIPE,
299
- ERROR_DISK_FULL => Errno::ENOSPC,
300
- ERROR_INVALID_TARGET_HANDLE => Errno::EBADF,
301
- ERROR_INVALID_HANDLE => Errno::EINVAL,
302
- ERROR_WAIT_NO_CHILDREN => Errno::ECHILD,
303
- ERROR_CHILD_NOT_COMPLETE => Errno::ECHILD,
304
- ERROR_DIRECT_ACCESS_HANDLE => Errno::EBADF,
305
- ERROR_NEGATIVE_SEEK => Errno::EINVAL,
306
- ERROR_SEEK_ON_DEVICE => Errno::EACCES,
307
- ERROR_DIR_NOT_EMPTY => Errno::ENOTEMPTY,
308
- # ERROR_DIRECTORY => Errno::ENOTDIR,
309
- ERROR_NOT_LOCKED => Errno::EACCES,
310
- ERROR_BAD_PATHNAME => Errno::ENOENT,
311
- ERROR_MAX_THRDS_REACHED => Errno::EAGAIN,
312
- # ERROR_LOCK_FAILED => Errno::EACCES,
313
- ERROR_ALREADY_EXISTS => Errno::EEXIST,
314
- ERROR_INVALID_STARTING_CODESEG => Errno::ENOEXEC,
315
- ERROR_INVALID_STACKSEG => Errno::ENOEXEC,
316
- ERROR_INVALID_MODULETYPE => Errno::ENOEXEC,
317
- ERROR_INVALID_EXE_SIGNATURE => Errno::ENOEXEC,
318
- ERROR_EXE_MARKED_INVALID => Errno::ENOEXEC,
319
- ERROR_BAD_EXE_FORMAT => Errno::ENOEXEC,
320
- ERROR_ITERATED_DATA_EXCEEDS_64k => Errno::ENOEXEC,
321
- ERROR_INVALID_MINALLOCSIZE => Errno::ENOEXEC,
322
- ERROR_DYNLINK_FROM_INVALID_RING => Errno::ENOEXEC,
323
- ERROR_IOPL_NOT_ENABLED => Errno::ENOEXEC,
324
- ERROR_INVALID_SEGDPL => Errno::ENOEXEC,
325
- ERROR_AUTODATASEG_EXCEEDS_64k => Errno::ENOEXEC,
326
- ERROR_RING2SEG_MUST_BE_MOVABLE => Errno::ENOEXEC,
327
- ERROR_RELOC_CHAIN_XEEDS_SEGLIM => Errno::ENOEXEC,
328
- ERROR_INFLOOP_IN_RELOC_CHAIN => Errno::ENOEXEC,
329
- ERROR_FILENAME_EXCED_RANGE => Errno::ENOENT,
330
- ERROR_NESTING_NOT_ALLOWED => Errno::EAGAIN,
331
- # ERROR_PIPE_LOCAL => Errno::EPIPE,
332
- ERROR_BAD_PIPE => Errno::EPIPE,
333
- ERROR_PIPE_BUSY => Errno::EAGAIN,
334
- ERROR_NO_DATA => Errno::EPIPE,
335
- ERROR_PIPE_NOT_CONNECTED => Errno::EPIPE,
336
- ERROR_OPERATION_ABORTED => Errno::EINTR,
337
- # ERROR_NOT_ENOUGH_QUOTA => Errno::ENOMEM,
338
- ERROR_MOD_NOT_FOUND => Errno::ENOENT,
339
- WSAEINTR => Errno::EINTR,
340
- WSAEBADF => Errno::EBADF,
341
- # WSAEACCES => Errno::EACCES,
342
- WSAEFAULT => Errno::EFAULT,
343
- WSAEINVAL => Errno::EINVAL,
344
- WSAEMFILE => Errno::EMFILE,
345
- WSAEWOULDBLOCK => Errno::EWOULDBLOCK,
346
- WSAEINPROGRESS => Errno::EINPROGRESS,
347
- WSAEALREADY => Errno::EALREADY,
348
- WSAENOTSOCK => Errno::ENOTSOCK,
349
- WSAEDESTADDRREQ => Errno::EDESTADDRREQ,
350
- WSAEMSGSIZE => Errno::EMSGSIZE,
351
- WSAEPROTOTYPE => Errno::EPROTOTYPE,
352
- WSAENOPROTOOPT => Errno::ENOPROTOOPT,
353
- WSAEPROTONOSUPPORT => Errno::EPROTONOSUPPORT,
354
- WSAESOCKTNOSUPPORT => Errno::ESOCKTNOSUPPORT,
355
- WSAEOPNOTSUPP => Errno::EOPNOTSUPP,
356
- WSAEPFNOSUPPORT => Errno::EPFNOSUPPORT,
357
- WSAEAFNOSUPPORT => Errno::EAFNOSUPPORT,
358
- WSAEADDRINUSE => Errno::EADDRINUSE,
359
- WSAEADDRNOTAVAIL => Errno::EADDRNOTAVAIL,
360
- WSAENETDOWN => Errno::ENETDOWN,
361
- WSAENETUNREACH => Errno::ENETUNREACH,
362
- WSAENETRESET => Errno::ENETRESET,
363
- WSAECONNABORTED => Errno::ECONNABORTED,
364
- WSAECONNRESET => Errno::ECONNRESET,
365
- WSAENOBUFS => Errno::ENOBUFS,
366
- WSAEISCONN => Errno::EISCONN,
367
- WSAENOTCONN => Errno::ENOTCONN,
368
- WSAESHUTDOWN => Errno::ESHUTDOWN,
369
- WSAETOOMANYREFS => Errno::ETOOMANYREFS,
370
- # WSAETIMEDOUT => Errno::ETIMEDOUT,
371
- WSAECONNREFUSED => Errno::ECONNREFUSED,
372
- WSAELOOP => Errno::ELOOP,
373
- WSAENAMETOOLONG => Errno::ENAMETOOLONG,
374
- WSAEHOSTDOWN => Errno::EHOSTDOWN,
375
- WSAEHOSTUNREACH => Errno::EHOSTUNREACH,
376
- # WSAEPROCLIM => Errno::EPROCLIM,
377
- # WSAENOTEMPTY => Errno::ENOTEMPTY,
378
- WSAEUSERS => Errno::EUSERS,
379
- WSAEDQUOT => Errno::EDQUOT,
380
- WSAESTALE => Errno::ESTALE,
381
- WSAEREMOTE => Errno::EREMOTE
382
- }
383
-
384
362
  module_function :create
385
363
  end
metadata CHANGED
@@ -1,19 +1,19 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mixlib-shellout
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
5
- prerelease:
4
+ version: 1.2.0.rc.0
5
+ prerelease: 6
6
6
  platform: x86-mingw32
7
7
  authors:
8
8
  - Opscode
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-08-06 00:00:00.000000000Z
12
+ date: 2013-05-03 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
16
- requirement: &11516480 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,18 +21,44 @@ dependencies:
21
21
  version: '0'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *11516480
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: ap
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
25
46
  - !ruby/object:Gem::Dependency
26
47
  name: win32-process
27
- requirement: &11586780 !ruby/object:Gem::Requirement
48
+ requirement: !ruby/object:Gem::Requirement
28
49
  none: false
29
50
  requirements:
30
51
  - - ~>
31
52
  - !ruby/object:Gem::Version
32
- version: 0.6.5
53
+ version: 0.7.0
33
54
  type: :runtime
34
55
  prerelease: false
35
- version_requirements: *11586780
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 0.7.0
36
62
  description: Run external commands on Unix or Windows
37
63
  email: info@opscode.com
38
64
  executables: []
@@ -43,12 +69,12 @@ extra_rdoc_files:
43
69
  files:
44
70
  - LICENSE
45
71
  - README.md
46
- - lib/mixlib/shellout.rb
47
- - lib/mixlib/shellout/windows/core_ext.rb
48
72
  - lib/mixlib/shellout/exceptions.rb
49
- - lib/mixlib/shellout/version.rb
50
73
  - lib/mixlib/shellout/unix.rb
74
+ - lib/mixlib/shellout/version.rb
75
+ - lib/mixlib/shellout/windows/core_ext.rb
51
76
  - lib/mixlib/shellout/windows.rb
77
+ - lib/mixlib/shellout.rb
52
78
  homepage: http://wiki.opscode.com/
53
79
  licenses: []
54
80
  post_install_message:
@@ -64,12 +90,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
64
90
  required_rubygems_version: !ruby/object:Gem::Requirement
65
91
  none: false
66
92
  requirements:
67
- - - ! '>='
93
+ - - ! '>'
68
94
  - !ruby/object:Gem::Version
69
- version: '0'
95
+ version: 1.3.1
70
96
  requirements: []
71
97
  rubyforge_project:
72
- rubygems_version: 1.8.17
98
+ rubygems_version: 1.8.23
73
99
  signing_key:
74
100
  specification_version: 3
75
101
  summary: Run external commands on Unix or Windows