microwave 0.1004.6 → 0.1006.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,90 @@
1
+ #
2
+ # Author:: Daniel DeLeo (<dan@opscode.com>)
3
+ # Copyright:: Copyright (c) 2011 Opscode, Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ require 'chef/mixin/shell_out'
20
+
21
+ class Chef
22
+ class Resource
23
+ class Conditional
24
+ include Chef::Mixin::ShellOut
25
+
26
+ # We only create these via the `not_if` or `only_if` constructors, and
27
+ # not the default constructor
28
+ class << self
29
+ private :new
30
+ end
31
+
32
+ def self.not_if(command=nil, command_opts={}, &block)
33
+ new(:not_if, command, command_opts, &block)
34
+ end
35
+
36
+ def self.only_if(command=nil, command_opts={}, &block)
37
+ new(:only_if, command, command_opts, &block)
38
+ end
39
+
40
+ attr_reader :positivity
41
+ attr_reader :command
42
+ attr_reader :command_opts
43
+ attr_reader :block
44
+
45
+ def initialize(positivity, command=nil, command_opts={}, &block)
46
+ @positivity = positivity
47
+ case command
48
+ when String
49
+ @command, @command_opts = command, command_opts
50
+ @block = nil
51
+ when nil
52
+ raise ArgumentError, "only_if/not_if requires either a command or a block" unless block_given?
53
+ @command, @command_opts = nil, nil
54
+ @block = block
55
+ else
56
+ raise ArgumentError, "Invalid only_if/not_if command: #{command.inspect} (#{command.class})"
57
+ end
58
+ end
59
+
60
+ def continue?
61
+ case @positivity
62
+ when :only_if
63
+ evaluate
64
+ when :not_if
65
+ !evaluate
66
+ else
67
+ raise "Cannot evaluate resource conditional of type #{@positivity}"
68
+ end
69
+ end
70
+
71
+ def evaluate
72
+ @command ? evaluate_command : evaluate_block
73
+ end
74
+
75
+ def evaluate_command
76
+ shell_out(@command, @command_opts).status.success?
77
+ end
78
+
79
+ def evaluate_block
80
+ @block.call
81
+ end
82
+
83
+ def description
84
+ cmd_or_block = @command ? "command `#{@command}`" : "ruby block"
85
+ "#{@positivity} #{cmd_or_block}"
86
+ end
87
+
88
+ end
89
+ end
90
+ end
@@ -21,7 +21,6 @@ require 'tmpdir'
21
21
  require 'chef/log'
22
22
  require 'fcntl'
23
23
  require 'chef/exceptions'
24
- require 'chef/shell_out/unix'
25
24
 
26
25
  class Chef
27
26
 
@@ -1,5 +1,6 @@
1
1
  #--
2
2
  # Author:: Daniel DeLeo (<dan@opscode.com>)
3
+ # Author:: John Keiser (<jkeiser@opscode.com>)
3
4
  # Copyright:: Copyright (c) 2011 Opscode, Inc.
4
5
  # License:: Apache License, Version 2.0
5
6
  #
@@ -16,83 +17,541 @@
16
17
  # limitations under the License.
17
18
  #
18
19
 
19
- require 'timeout'
20
- if RUBY_VERSION =~ /^1\.8/
21
- require 'win32/open3'
22
- else
23
- require 'open3'
24
- end
20
+ require 'win32/process'
21
+ require 'windows/handle'
22
+ require 'windows/process'
23
+ require 'windows/synchronize'
25
24
 
26
25
  class Chef
27
26
  class ShellOut
28
27
  module Windows
29
28
 
29
+ include ::Windows::Handle
30
+ include ::Windows::Process
31
+ include ::Windows::Synchronize
32
+
33
+ TIME_SLICE = 0.05
34
+
30
35
  #--
31
36
  # Missing lots of features from the UNIX version, such as
32
- # environment, cwd, etc.
37
+ # uid, etc.
33
38
  def run_command
34
- # win32 open4 is really just open3.
35
- Open3.popen3(@command) do |stdin,stdout,stderr|
36
- @finished_stdout = false
37
- @finished_stderr = false
38
- stdin.close
39
- stdout.sync = true
40
- stderr.sync = true
41
-
42
- # TBH, I really don't know what this will do when it times out.
43
- # However, I'm powerless to make windows have non-blocking IO, so
44
- # thread party it is.
45
- Timeout.timeout(timeout) do
46
- out_reader = Thread.new do
47
- loop do
48
- read_stdout(stdout)
49
- break if @finished_stdout
50
- end
51
- end
52
- err_reader = Thread.new do
53
- loop do
54
- read_stderr(stderr)
55
- break if @finished_stderr
39
+
40
+ #
41
+ # Create pipes to capture stdout and stderr,
42
+ #
43
+ stdout_read, stdout_write = IO.pipe
44
+ stderr_read, stderr_write = IO.pipe
45
+ open_streams = [ stdout_read, stderr_read ]
46
+
47
+ begin
48
+
49
+ #
50
+ # Set cwd, environment, appname, etc.
51
+ #
52
+ app_name, command_line = command_to_run
53
+ create_process_args = {
54
+ :app_name => app_name,
55
+ :command_line => command_line,
56
+ :startup_info => {
57
+ :stdout => stdout_write,
58
+ :stderr => stderr_write
59
+ },
60
+ :environment => inherit_environment.map { |k,v| "#{k}=#{v}" },
61
+ :close_handles => false
62
+ }
63
+ create_process_args[:cwd] = cwd if cwd
64
+
65
+ #
66
+ # Start the process
67
+ #
68
+ process = Process.create(create_process_args)
69
+ begin
70
+
71
+ #
72
+ # Wait for the process to finish, consuming output as we go
73
+ #
74
+ start_wait = Time.now
75
+ while true
76
+ wait_status = WaitForSingleObject(process.process_handle, 0)
77
+ case wait_status
78
+ when WAIT_OBJECT_0
79
+ # Get process exit code
80
+ exit_code = [0].pack('l')
81
+ unless GetExitCodeProcess(process.process_handle, exit_code)
82
+ raise get_last_error
83
+ end
84
+ @status = ThingThatLooksSortOfLikeAProcessStatus.new
85
+ @status.exitstatus = exit_code.unpack('l').first
86
+
87
+ return self
88
+ when WAIT_TIMEOUT
89
+ # Kill the process
90
+ if (Time.now - start_wait) > timeout
91
+ raise Chef::Exceptions::CommandTimeout, "command timed out:\n#{format_for_exception}"
92
+ end
93
+
94
+ consume_output(open_streams, stdout_read, stderr_read)
95
+ else
96
+ raise "Unknown response from WaitForSingleObject(#{process.process_handle}, #{timeout*1000}): #{wait_status}"
56
97
  end
98
+
57
99
  end
58
100
 
59
- out_reader.join
60
- err_reader.join
101
+ ensure
102
+ CloseHandle(process.thread_handle)
103
+ CloseHandle(process.process_handle)
61
104
  end
105
+
106
+ ensure
107
+ #
108
+ # Consume all remaining data from the pipes until they are closed
109
+ #
110
+ stdout_write.close
111
+ stderr_write.close
112
+
113
+ while consume_output(open_streams, stdout_read, stderr_read)
114
+ end
115
+ end
116
+ end
117
+
118
+ private
119
+
120
+ class ThingThatLooksSortOfLikeAProcessStatus
121
+ attr_accessor :exitstatus
122
+ def success?
123
+ exitstatus == 0
62
124
  end
125
+ end
126
+
127
+ def consume_output(open_streams, stdout_read, stderr_read)
128
+ return false if open_streams.length == 0
129
+ ready = IO.select(open_streams, nil, nil, READ_WAIT_TIME)
130
+ return true if ! ready
63
131
 
64
- @status = $?
132
+ if ready.first.include?(stdout_read)
133
+ begin
134
+ next_chunk = stdout_read.readpartial(READ_SIZE)
135
+ @stdout << next_chunk
136
+ @live_stream << next_chunk if @live_stream
137
+ rescue EOFError
138
+ stdout_read.close
139
+ open_streams.delete(stdout_read)
140
+ end
141
+ end
65
142
 
66
- self
143
+ if ready.first.include?(stderr_read)
144
+ begin
145
+ @stderr << stderr_read.readpartial(READ_SIZE)
146
+ rescue EOFError
147
+ stderr_read.close
148
+ open_streams.delete(stderr_read)
149
+ end
150
+ end
67
151
 
68
- rescue Timeout::Error
69
- raise Chef::Exceptions::CommandTimeout, "command timed out:\n#{format_for_exception}"
152
+ return true
70
153
  end
71
154
 
72
- def read_stdout(stdout)
73
- return nil if @finished_stdout
74
- if chunk = stdout.sysread(8096)
75
- @stdout << chunk
155
+ SHOULD_USE_CMD = /['"<>|&%]|\b(?:assoc|break|call|cd|chcp|chdir|cls|color|copy|ctty|date|del|dir|echo|endlocal|erase|exit|for|ftype|goto|if|lfnfor|lh|lock|md|mkdir|move|path|pause|popd|prompt|pushd|rd|rem|ren|rename|rmdir|set|setlocal|shift|start|time|title|truename|type|unlock|ver|verify|vol)\b/
156
+
157
+ def command_to_run
158
+ if command =~ SHOULD_USE_CMD
159
+ [ ENV['COMSPEC'], "cmd /c #{command}" ]
76
160
  else
77
- @finished_stdout = true
161
+ [ which(command[0,command.index(/\s/) || command.length]), command ]
78
162
  end
79
- rescue EOFError
80
- @finished_stdout = true
81
- rescue Errno::EAGAIN
82
163
  end
83
164
 
84
- def read_stderr(stderr)
85
- return nil if @finished_stderr
86
- if chunk = stderr.sysread(8096)
87
- @stderr << chunk
165
+ def inherit_environment
166
+ result = {}
167
+ ENV.each_pair do |k,v|
168
+ result[k] = v
169
+ end
170
+
171
+ environment.each_pair do |k,v|
172
+ if v == nil
173
+ result.delete(k)
174
+ else
175
+ result[k] = v
176
+ end
177
+ end
178
+ result
179
+ end
180
+
181
+ def which(cmd)
182
+ return cmd if File.executable? cmd
183
+ exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') + [''] : ['']
184
+ ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
185
+ exts.each { |ext|
186
+ exe = "#{path}/#{cmd}#{ext}"
187
+ return exe if File.executable? exe
188
+ }
189
+ end
190
+ return nil
191
+ end
192
+ end # class
193
+ end
194
+ end
195
+
196
+ #
197
+ # Override module Windows::Process.CreateProcess to fix bug when
198
+ # using both app_name and command_line
199
+ #
200
+ module Windows
201
+ module Process
202
+ API.new('CreateProcess', 'SPPPLLLPPP', 'B')
203
+ end
204
+ end
205
+
206
+ #
207
+ # Override Win32::Process.create to take a proper environment hash
208
+ # so that variables can contain semicolons
209
+ # (submitted patch to owner)
210
+ #
211
+ module Process
212
+ def create(args)
213
+ unless args.kind_of?(Hash)
214
+ raise TypeError, 'Expecting hash-style keyword arguments'
215
+ end
216
+
217
+ valid_keys = %w/
218
+ app_name command_line inherit creation_flags cwd environment
219
+ startup_info thread_inherit process_inherit close_handles with_logon
220
+ domain password
221
+ /
222
+
223
+ valid_si_keys = %/
224
+ startf_flags desktop title x y x_size y_size x_count_chars
225
+ y_count_chars fill_attribute sw_flags stdin stdout stderr
226
+ /
227
+
228
+ # Set default values
229
+ hash = {
230
+ 'app_name' => nil,
231
+ 'creation_flags' => 0,
232
+ 'close_handles' => true
233
+ }
234
+
235
+ # Validate the keys, and convert symbols and case to lowercase strings.
236
+ args.each{ |key, val|
237
+ key = key.to_s.downcase
238
+ unless valid_keys.include?(key)
239
+ raise ArgumentError, "invalid key '#{key}'"
240
+ end
241
+ hash[key] = val
242
+ }
243
+
244
+ si_hash = {}
245
+
246
+ # If the startup_info key is present, validate its subkeys
247
+ if hash['startup_info']
248
+ hash['startup_info'].each{ |key, val|
249
+ key = key.to_s.downcase
250
+ unless valid_si_keys.include?(key)
251
+ raise ArgumentError, "invalid startup_info key '#{key}'"
252
+ end
253
+ si_hash[key] = val
254
+ }
255
+ end
256
+
257
+ # The +command_line+ key is mandatory unless the +app_name+ key
258
+ # is specified.
259
+ unless hash['command_line']
260
+ if hash['app_name']
261
+ hash['command_line'] = hash['app_name']
262
+ hash['app_name'] = nil
263
+ else
264
+ raise ArgumentError, 'command_line or app_name must be specified'
265
+ end
266
+ end
267
+
268
+ # The environment string should be passed as an array of A=B paths, or
269
+ # as a string of ';' separated paths.
270
+ if hash['environment']
271
+ env = hash['environment']
272
+ if !env.respond_to?(:join)
273
+ # Backwards compat for ; separated paths
274
+ env = hash['environment'].split(File::PATH_SEPARATOR)
275
+ end
276
+ # The argument format is a series of null-terminated strings, with an additional null terminator.
277
+ env = env.map { |e| e + "\0" }.join("") + "\0"
278
+ if hash['with_logon']
279
+ env = env.multi_to_wide(e)
280
+ end
281
+ env = [env].pack('p*').unpack('L').first
282
+ else
283
+ env = nil
284
+ end
285
+
286
+ startinfo = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
287
+ startinfo = startinfo.pack('LLLLLLLLLLLLSSLLLL')
288
+ procinfo = [0,0,0,0].pack('LLLL')
289
+
290
+ # Process SECURITY_ATTRIBUTE structure
291
+ process_security = 0
292
+ if hash['process_inherit']
293
+ process_security = [0,0,0].pack('LLL')
294
+ process_security[0,4] = [12].pack('L') # sizeof(SECURITY_ATTRIBUTE)
295
+ process_security[8,4] = [1].pack('L') # TRUE
296
+ end
297
+
298
+ # Thread SECURITY_ATTRIBUTE structure
299
+ thread_security = 0
300
+ if hash['thread_inherit']
301
+ thread_security = [0,0,0].pack('LLL')
302
+ thread_security[0,4] = [12].pack('L') # sizeof(SECURITY_ATTRIBUTE)
303
+ thread_security[8,4] = [1].pack('L') # TRUE
304
+ end
305
+
306
+ # Automatically handle stdin, stdout and stderr as either IO objects
307
+ # or file descriptors. This won't work for StringIO, however.
308
+ ['stdin', 'stdout', 'stderr'].each{ |io|
309
+ if si_hash[io]
310
+ if si_hash[io].respond_to?(:fileno)
311
+ handle = get_osfhandle(si_hash[io].fileno)
88
312
  else
89
- @finished_stderr = true
313
+ handle = get_osfhandle(si_hash[io])
314
+ end
315
+
316
+ if handle == INVALID_HANDLE_VALUE
317
+ raise Error, get_last_error
90
318
  end
91
- rescue EOFError
92
- @finished_stderr = true
93
- rescue Errno::EAGAIN
319
+
320
+ # Most implementations of Ruby on Windows create inheritable
321
+ # handles by default, but some do not. RF bug #26988.
322
+ bool = SetHandleInformation(
323
+ handle,
324
+ HANDLE_FLAG_INHERIT,
325
+ HANDLE_FLAG_INHERIT
326
+ )
327
+
328
+ raise Error, get_last_error unless bool
329
+
330
+ si_hash[io] = handle
331
+ si_hash['startf_flags'] ||= 0
332
+ si_hash['startf_flags'] |= STARTF_USESTDHANDLES
333
+ hash['inherit'] = true
94
334
  end
335
+ }
336
+
337
+ # The bytes not covered here are reserved (null)
338
+ unless si_hash.empty?
339
+ startinfo[0,4] = [startinfo.size].pack('L')
340
+ startinfo[8,4] = [si_hash['desktop']].pack('p*') if si_hash['desktop']
341
+ startinfo[12,4] = [si_hash['title']].pack('p*') if si_hash['title']
342
+ startinfo[16,4] = [si_hash['x']].pack('L') if si_hash['x']
343
+ startinfo[20,4] = [si_hash['y']].pack('L') if si_hash['y']
344
+ startinfo[24,4] = [si_hash['x_size']].pack('L') if si_hash['x_size']
345
+ startinfo[28,4] = [si_hash['y_size']].pack('L') if si_hash['y_size']
346
+ startinfo[32,4] = [si_hash['x_count_chars']].pack('L') if si_hash['x_count_chars']
347
+ startinfo[36,4] = [si_hash['y_count_chars']].pack('L') if si_hash['y_count_chars']
348
+ startinfo[40,4] = [si_hash['fill_attribute']].pack('L') if si_hash['fill_attribute']
349
+ startinfo[44,4] = [si_hash['startf_flags']].pack('L') if si_hash['startf_flags']
350
+ startinfo[48,2] = [si_hash['sw_flags']].pack('S') if si_hash['sw_flags']
351
+ startinfo[56,4] = [si_hash['stdin']].pack('L') if si_hash['stdin']
352
+ startinfo[60,4] = [si_hash['stdout']].pack('L') if si_hash['stdout']
353
+ startinfo[64,4] = [si_hash['stderr']].pack('L') if si_hash['stderr']
354
+ end
355
+
356
+ if hash['with_logon']
357
+ logon = multi_to_wide(hash['with_logon'])
358
+ domain = multi_to_wide(hash['domain'])
359
+ app = hash['app_name'].nil? ? nil : multi_to_wide(hash['app_name'])
360
+ cmd = hash['command_line'].nil? ? nil : multi_to_wide(hash['command_line'])
361
+ cwd = multi_to_wide(hash['cwd'])
362
+ passwd = multi_to_wide(hash['password'])
363
+
364
+ hash['creation_flags'] |= CREATE_UNICODE_ENVIRONMENT
365
+
366
+ process_ran = CreateProcessWithLogonW(
367
+ logon, # User
368
+ domain, # Domain
369
+ passwd, # Password
370
+ LOGON_WITH_PROFILE, # Logon flags
371
+ app, # App name
372
+ cmd, # Command line
373
+ hash['creation_flags'], # Creation flags
374
+ env, # Environment
375
+ cwd, # Working directory
376
+ startinfo, # Startup Info
377
+ procinfo # Process Info
378
+ )
379
+ else
380
+ process_ran = CreateProcess(
381
+ hash['app_name'], # App name
382
+ hash['command_line'], # Command line
383
+ process_security, # Process attributes
384
+ thread_security, # Thread attributes
385
+ hash['inherit'], # Inherit handles?
386
+ hash['creation_flags'], # Creation flags
387
+ env, # Environment
388
+ hash['cwd'], # Working directory
389
+ startinfo, # Startup Info
390
+ procinfo # Process Info
391
+ )
392
+ end
95
393
 
394
+ # TODO: Close stdin, stdout and stderr handles in the si_hash unless
395
+ # they're pointing to one of the standard handles already. [Maybe]
396
+ if !process_ran
397
+ raise_last_error("CreateProcess()")
96
398
  end
399
+
400
+ # Automatically close the process and thread handles in the
401
+ # PROCESS_INFORMATION struct unless explicitly told not to.
402
+ if hash['close_handles']
403
+ CloseHandle(procinfo[0,4].unpack('L').first)
404
+ CloseHandle(procinfo[4,4].unpack('L').first)
405
+ end
406
+
407
+ ProcessInfo.new(
408
+ procinfo[0,4].unpack('L').first, # hProcess
409
+ procinfo[4,4].unpack('L').first, # hThread
410
+ procinfo[8,4].unpack('L').first, # hProcessId
411
+ procinfo[12,4].unpack('L').first # hThreadId
412
+ )
97
413
  end
98
- end
414
+
415
+ def self.raise_last_error(operation)
416
+ error_string = "#{operation} failed: #{get_last_error}"
417
+ last_error_code = GetLastError()
418
+ if ERROR_CODE_MAP.has_key?(last_error_code)
419
+ raise ERROR_CODE_MAP[last_error_code], error_string
420
+ else
421
+ raise Error, error_string
422
+ end
423
+ end
424
+
425
+ # List from ruby/win32/win32.c
426
+ ERROR_CODE_MAP = {
427
+ ERROR_INVALID_FUNCTION => Errno::EINVAL,
428
+ ERROR_FILE_NOT_FOUND => Errno::ENOENT,
429
+ ERROR_PATH_NOT_FOUND => Errno::ENOENT,
430
+ ERROR_TOO_MANY_OPEN_FILES => Errno::EMFILE,
431
+ ERROR_ACCESS_DENIED => Errno::EACCES,
432
+ ERROR_INVALID_HANDLE => Errno::EBADF,
433
+ ERROR_ARENA_TRASHED => Errno::ENOMEM,
434
+ ERROR_NOT_ENOUGH_MEMORY => Errno::ENOMEM,
435
+ ERROR_INVALID_BLOCK => Errno::ENOMEM,
436
+ ERROR_BAD_ENVIRONMENT => Errno::E2BIG,
437
+ ERROR_BAD_FORMAT => Errno::ENOEXEC,
438
+ ERROR_INVALID_ACCESS => Errno::EINVAL,
439
+ ERROR_INVALID_DATA => Errno::EINVAL,
440
+ ERROR_INVALID_DRIVE => Errno::ENOENT,
441
+ ERROR_CURRENT_DIRECTORY => Errno::EACCES,
442
+ ERROR_NOT_SAME_DEVICE => Errno::EXDEV,
443
+ ERROR_NO_MORE_FILES => Errno::ENOENT,
444
+ ERROR_WRITE_PROTECT => Errno::EROFS,
445
+ ERROR_BAD_UNIT => Errno::ENODEV,
446
+ ERROR_NOT_READY => Errno::ENXIO,
447
+ ERROR_BAD_COMMAND => Errno::EACCES,
448
+ ERROR_CRC => Errno::EACCES,
449
+ ERROR_BAD_LENGTH => Errno::EACCES,
450
+ ERROR_SEEK => Errno::EIO,
451
+ ERROR_NOT_DOS_DISK => Errno::EACCES,
452
+ ERROR_SECTOR_NOT_FOUND => Errno::EACCES,
453
+ ERROR_OUT_OF_PAPER => Errno::EACCES,
454
+ ERROR_WRITE_FAULT => Errno::EIO,
455
+ ERROR_READ_FAULT => Errno::EIO,
456
+ ERROR_GEN_FAILURE => Errno::EACCES,
457
+ ERROR_LOCK_VIOLATION => Errno::EACCES,
458
+ ERROR_SHARING_VIOLATION => Errno::EACCES,
459
+ ERROR_WRONG_DISK => Errno::EACCES,
460
+ ERROR_SHARING_BUFFER_EXCEEDED => Errno::EACCES,
461
+ # ERROR_BAD_NETPATH => Errno::ENOENT,
462
+ # ERROR_NETWORK_ACCESS_DENIED => Errno::EACCES,
463
+ # ERROR_BAD_NET_NAME => Errno::ENOENT,
464
+ ERROR_FILE_EXISTS => Errno::EEXIST,
465
+ ERROR_CANNOT_MAKE => Errno::EACCES,
466
+ ERROR_FAIL_I24 => Errno::EACCES,
467
+ ERROR_INVALID_PARAMETER => Errno::EINVAL,
468
+ ERROR_NO_PROC_SLOTS => Errno::EAGAIN,
469
+ ERROR_DRIVE_LOCKED => Errno::EACCES,
470
+ ERROR_BROKEN_PIPE => Errno::EPIPE,
471
+ ERROR_DISK_FULL => Errno::ENOSPC,
472
+ ERROR_INVALID_TARGET_HANDLE => Errno::EBADF,
473
+ ERROR_INVALID_HANDLE => Errno::EINVAL,
474
+ ERROR_WAIT_NO_CHILDREN => Errno::ECHILD,
475
+ ERROR_CHILD_NOT_COMPLETE => Errno::ECHILD,
476
+ ERROR_DIRECT_ACCESS_HANDLE => Errno::EBADF,
477
+ ERROR_NEGATIVE_SEEK => Errno::EINVAL,
478
+ ERROR_SEEK_ON_DEVICE => Errno::EACCES,
479
+ ERROR_DIR_NOT_EMPTY => Errno::ENOTEMPTY,
480
+ # ERROR_DIRECTORY => Errno::ENOTDIR,
481
+ ERROR_NOT_LOCKED => Errno::EACCES,
482
+ ERROR_BAD_PATHNAME => Errno::ENOENT,
483
+ ERROR_MAX_THRDS_REACHED => Errno::EAGAIN,
484
+ # ERROR_LOCK_FAILED => Errno::EACCES,
485
+ ERROR_ALREADY_EXISTS => Errno::EEXIST,
486
+ ERROR_INVALID_STARTING_CODESEG => Errno::ENOEXEC,
487
+ ERROR_INVALID_STACKSEG => Errno::ENOEXEC,
488
+ ERROR_INVALID_MODULETYPE => Errno::ENOEXEC,
489
+ ERROR_INVALID_EXE_SIGNATURE => Errno::ENOEXEC,
490
+ ERROR_EXE_MARKED_INVALID => Errno::ENOEXEC,
491
+ ERROR_BAD_EXE_FORMAT => Errno::ENOEXEC,
492
+ ERROR_ITERATED_DATA_EXCEEDS_64k => Errno::ENOEXEC,
493
+ ERROR_INVALID_MINALLOCSIZE => Errno::ENOEXEC,
494
+ ERROR_DYNLINK_FROM_INVALID_RING => Errno::ENOEXEC,
495
+ ERROR_IOPL_NOT_ENABLED => Errno::ENOEXEC,
496
+ ERROR_INVALID_SEGDPL => Errno::ENOEXEC,
497
+ ERROR_AUTODATASEG_EXCEEDS_64k => Errno::ENOEXEC,
498
+ ERROR_RING2SEG_MUST_BE_MOVABLE => Errno::ENOEXEC,
499
+ ERROR_RELOC_CHAIN_XEEDS_SEGLIM => Errno::ENOEXEC,
500
+ ERROR_INFLOOP_IN_RELOC_CHAIN => Errno::ENOEXEC,
501
+ ERROR_FILENAME_EXCED_RANGE => Errno::ENOENT,
502
+ ERROR_NESTING_NOT_ALLOWED => Errno::EAGAIN,
503
+ # ERROR_PIPE_LOCAL => Errno::EPIPE,
504
+ ERROR_BAD_PIPE => Errno::EPIPE,
505
+ ERROR_PIPE_BUSY => Errno::EAGAIN,
506
+ ERROR_NO_DATA => Errno::EPIPE,
507
+ ERROR_PIPE_NOT_CONNECTED => Errno::EPIPE,
508
+ ERROR_OPERATION_ABORTED => Errno::EINTR,
509
+ # ERROR_NOT_ENOUGH_QUOTA => Errno::ENOMEM,
510
+ ERROR_MOD_NOT_FOUND => Errno::ENOENT,
511
+ WSAEINTR => Errno::EINTR,
512
+ WSAEBADF => Errno::EBADF,
513
+ # WSAEACCES => Errno::EACCES,
514
+ WSAEFAULT => Errno::EFAULT,
515
+ WSAEINVAL => Errno::EINVAL,
516
+ WSAEMFILE => Errno::EMFILE,
517
+ WSAEWOULDBLOCK => Errno::EWOULDBLOCK,
518
+ WSAEINPROGRESS => Errno::EINPROGRESS,
519
+ WSAEALREADY => Errno::EALREADY,
520
+ WSAENOTSOCK => Errno::ENOTSOCK,
521
+ WSAEDESTADDRREQ => Errno::EDESTADDRREQ,
522
+ WSAEMSGSIZE => Errno::EMSGSIZE,
523
+ WSAEPROTOTYPE => Errno::EPROTOTYPE,
524
+ WSAENOPROTOOPT => Errno::ENOPROTOOPT,
525
+ WSAEPROTONOSUPPORT => Errno::EPROTONOSUPPORT,
526
+ WSAESOCKTNOSUPPORT => Errno::ESOCKTNOSUPPORT,
527
+ WSAEOPNOTSUPP => Errno::EOPNOTSUPP,
528
+ WSAEPFNOSUPPORT => Errno::EPFNOSUPPORT,
529
+ WSAEAFNOSUPPORT => Errno::EAFNOSUPPORT,
530
+ WSAEADDRINUSE => Errno::EADDRINUSE,
531
+ WSAEADDRNOTAVAIL => Errno::EADDRNOTAVAIL,
532
+ WSAENETDOWN => Errno::ENETDOWN,
533
+ WSAENETUNREACH => Errno::ENETUNREACH,
534
+ WSAENETRESET => Errno::ENETRESET,
535
+ WSAECONNABORTED => Errno::ECONNABORTED,
536
+ WSAECONNRESET => Errno::ECONNRESET,
537
+ WSAENOBUFS => Errno::ENOBUFS,
538
+ WSAEISCONN => Errno::EISCONN,
539
+ WSAENOTCONN => Errno::ENOTCONN,
540
+ WSAESHUTDOWN => Errno::ESHUTDOWN,
541
+ WSAETOOMANYREFS => Errno::ETOOMANYREFS,
542
+ # WSAETIMEDOUT => Errno::ETIMEDOUT,
543
+ WSAECONNREFUSED => Errno::ECONNREFUSED,
544
+ WSAELOOP => Errno::ELOOP,
545
+ WSAENAMETOOLONG => Errno::ENAMETOOLONG,
546
+ WSAEHOSTDOWN => Errno::EHOSTDOWN,
547
+ WSAEHOSTUNREACH => Errno::EHOSTUNREACH,
548
+ # WSAEPROCLIM => Errno::EPROCLIM,
549
+ # WSAENOTEMPTY => Errno::ENOTEMPTY,
550
+ WSAEUSERS => Errno::EUSERS,
551
+ WSAEDQUOT => Errno::EDQUOT,
552
+ WSAESTALE => Errno::ESTALE,
553
+ WSAEREMOTE => Errno::EREMOTE
554
+ }
555
+
556
+ module_function :create
557
+ end