Class: Vagrant::Util::Platform

Inherits:
Object
  • Object
show all
Defined in:
lib/vagrant/util/platform.rb

Overview

This class just contains some platform checking code.

Constant Summary collapse

MOUNT_PATTERN =

Mount pattern for extracting local mount information

/^(?<device>.+?) on (?<mount>.+?) type (?<type>.+?) \((?<options>.+)\)/.freeze

Class Method Summary collapse

Class Method Details

.cygwin?Boolean

Returns:

  • (Boolean)

24
25
26
27
28
29
30
31
# File 'lib/vagrant/util/platform.rb', line 24

def cygwin?
  if !defined?(@_cygwin)
    @_cygwin = ENV["VAGRANT_DETECTED_OS"].to_s.downcase.include?("cygwin") ||
      platform.include?("cygwin") ||
      ENV["OSTYPE"].to_s.downcase.include?("cygwin")
  end
  @_cygwin
end

.cygwin_path(path) ⇒ String

This takes any path and converts it from a Windows path to a Cygwin style path.

Parameters:

  • path (String)

Returns:

  • (String)

163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
# File 'lib/vagrant/util/platform.rb', line 163

def cygwin_path(path)
  begin
    cygpath = Vagrant::Util::Which.which("cygpath")
    if cygpath.nil?
      # If Which can't find it, just attempt to invoke it directly
      cygpath = "cygpath"
    else
      cygpath.gsub!("/", '\\')
    end

    process = Subprocess.execute(
      cygpath, "-u", "-a", path.to_s)
    return process.stdout.chomp
  rescue Errors::CommandUnavailableWindows => e
    # Sometimes cygpath isn't available (msys). Instead, do what we
    # can with bash tricks.
    process = Subprocess.execute(
      "bash",
      "--noprofile",
      "--norc",
      "-c", "cd #{Shellwords.escape(path)} && pwd")
    return process.stdout.chomp
  end
end

.cygwin_windows_path(path) ⇒ String

This takes any path and converts it to a full-length Windows path on Windows machines in Cygwin.

Returns:

  • (String)

212
213
214
215
216
217
218
219
220
221
# File 'lib/vagrant/util/platform.rb', line 212

def cygwin_windows_path(path)
  return path if !cygwin?

  # Replace all "\" with "/", otherwise cygpath doesn't work.
  path = unix_windows_path(path)

  # Call out to cygpath and gather the result
  process = Subprocess.execute("cygpath", "-w", "-l", "-a", path.to_s)
  return process.stdout.chomp
end

.format_windows_path(path, *args) ⇒ String

Takes a windows path and formats it to the 'unix' style (i.e. /cygdrive/c or /c/)

Parameters:

  • path (Pathname, String)

    Path to convert

  • hash (Hash)

    of arguments

Returns:

  • (String)

480
481
482
483
484
485
486
487
488
489
# File 'lib/vagrant/util/platform.rb', line 480

def format_windows_path(path, *args)
  path = cygwin_path(path) if cygwin?
  path = msys_path(path) if msys?
  path = wsl_to_windows_path(path) if wsl?
  if windows? || wsl?
    path = windows_unc_path(path) if !args.include?(:disable_unc)
  end

  path
end

.fs_case_sensitive?Boolean

This checks if the filesystem is case sensitive. This is not a 100% correct check, since it is possible that the temporary directory runs a different filesystem than the root directory. However, this works in many cases.

Returns:

  • (Boolean)

234
235
236
237
238
239
240
241
242
243
244
245
246
247
# File 'lib/vagrant/util/platform.rb', line 234

def fs_case_sensitive?
  return @_fs_case_sensitive if defined?(@_fs_case_sensitive)
  @_fs_case_sensitive = Dir.mktmpdir("vagrant-fs-case-sensitive") do |dir|
    tmp_file = File.join(dir, "FILE")
    File.open(tmp_file, "w") do |f|
      f.write("foo")
    end

    # The filesystem is case sensitive if the lowercased version
    # of the filename is NOT reported as existing.
    !File.file?(File.join(dir, "file"))
  end
  return @_fs_case_sensitive
end

.fs_real_path(path, **opts) ⇒ Object

This expands the path and ensures proper casing of each part of the path.


251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
# File 'lib/vagrant/util/platform.rb', line 251

def fs_real_path(path, **opts)
  path = Pathname.new(File.expand_path(path))

  if path.exist? && !fs_case_sensitive?
    # If the path contains a Windows short path, then we attempt to
    # expand. The require below is embedded here since it requires
    # windows to work.
    if windows? && path.to_s =~ /~\d(\/|\\)/
      require_relative "windows_path"
      path = Pathname.new(WindowsPath.longname(path.to_s))
    end

    # Build up all the parts of the path
    original = []
    while !path.root?
      original.unshift(path.basename.to_s)
      path = path.parent
    end

    # Traverse each part and join it into the resulting path
    original.each do |single|
      Dir.entries(path).each do |entry|
        begin
          single = single.encode("filesystem").to_s
        rescue ArgumentError => err
          Vagrant.global_logger.warn("path encoding failed - part=#{single} err=#{err.class} msg=#{err}")
          # NOTE: Depending on the Windows environment the above
          # encode will generate an "input string invalid" when
          # attempting to encode. If that happens, continue on
        end
        if entry.downcase == single.downcase
          path = path.join(entry)
        end
      end
    end
  end

  if windows?
    # Fix the drive letter to be uppercase.
    path = path.to_s
    if path[1] == ":"
      path[0] = path[0].upcase
    end

    path = Pathname.new(path)
  end

  path
end

.loggerObject


17
18
19
20
21
22
# File 'lib/vagrant/util/platform.rb', line 17

def logger
  if !defined?(@_logger)
    @_logger = Log4r::Logger.new("vagrant::util::platform")
  end
  @_logger
end

.msys?Boolean

Returns:

  • (Boolean)

33
34
35
36
37
38
39
40
# File 'lib/vagrant/util/platform.rb', line 33

def msys?
  if !defined?(@_msys)
    @_msys = ENV["VAGRANT_DETECTED_OS"].to_s.downcase.include?("msys") ||
      platform.include?("msys") ||
      ENV["OSTYPE"].to_s.downcase.include?("msys")
  end
  @_msys
end

.msys_path(path) ⇒ String

This takes any path and converts it from a Windows path to a msys style path.

Parameters:

  • path (String)

Returns:

  • (String)

193
194
195
196
197
198
199
200
201
202
203
204
205
206
# File 'lib/vagrant/util/platform.rb', line 193

def msys_path(path)
  begin
    # We have to revert to the old env
    # path here, otherwise it looks like
    # msys2 ends up using the wrong cygpath
    # binary and ends up with a `/cygdrive`
    # when it doesn't exist in msys2
    original_path_env = ENV['PATH']
    ENV['PATH'] = ENV['VAGRANT_OLD_ENV_PATH']
    cygwin_path(path)
  ensure
    ENV['PATH'] = original_path_env
  end
end

.platformObject


336
337
338
339
340
# File 'lib/vagrant/util/platform.rb', line 336

def platform
  return @_platform if defined?(@_platform)
  @_platform = RbConfig::CONFIG["host_os"].downcase
  return @_platform
end

.reset!Object

Reset the cached values for platform. This is not considered a public API and should only be used for testing.


699
700
701
# File 'lib/vagrant/util/platform.rb', line 699

def reset!
  instance_variables.each(&method(:remove_instance_variable))
end

.systemd?Boolean

systemd is in use

Returns:

  • (Boolean)

684
685
686
687
688
689
690
691
692
693
694
# File 'lib/vagrant/util/platform.rb', line 684

def systemd?
  if !defined?(@_systemd)
    if !windows?
      result = Vagrant::Util::Subprocess.execute("ps", "-o", "comm=", "1")
      @_systemd = result.stdout.chomp == "systemd"
    else
      @_systemd = false
    end
  end
  @_systemd
end

.terminal_supports_colors?Boolean

Returns a boolean noting whether the terminal supports color. output.

Returns:

  • (Boolean)

321
322
323
324
325
326
327
328
329
330
331
332
333
334
# File 'lib/vagrant/util/platform.rb', line 321

def terminal_supports_colors?
  return @_terminal_supports_colors if defined?(@_terminal_supports_colors)
  @_terminal_supports_colors = -> {
    if windows?
      return true if ENV.key?("ANSICON")
      return true if cygwin?
      return true if ENV["TERM"] == "cygwin"
      return false
    end

    return true
  }.call
  return @_terminal_supports_colors
end

.unix_windows_path(path) ⇒ String

This takes any path and converts Windows-style path separators to Unix-like path separators.

Returns:

  • (String)

226
227
228
# File 'lib/vagrant/util/platform.rb', line 226

def unix_windows_path(path)
  path.gsub("\\", "/")
end

.windows?Boolean

Returns:

  • (Boolean)

64
65
66
67
68
# File 'lib/vagrant/util/platform.rb', line 64

def windows?
  return @_windows if defined?(@_windows)
  @_windows = %w[mingw mswin].any? { |t| platform.include?(t) }
  return @_windows
end

.windows_admin?Boolean

Checks if the user running Vagrant on Windows has administrative privileges.

From: https://support.microsoft.com/en-us/kb/243330 SID: S-1-5-19

Returns:

  • (Boolean)

77
78
79
80
81
82
83
84
85
86
87
# File 'lib/vagrant/util/platform.rb', line 77

def windows_admin?
  return @_windows_admin if defined?(@_windows_admin)

  @_windows_admin = -> {
    ps_cmd = '(new-object System.Security.Principal.WindowsPrincipal([System.Security.Principal.WindowsIdentity]::GetCurrent())).IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator)'
    output = Vagrant::Util::PowerShell.execute_cmd(ps_cmd)
    return output == 'True'
  }.call

  return @_windows_admin
end

.windows_hyperv_admin?Boolean

Checks if Hyper-V is accessible to the local user. It will check if user is in the "Hyper-V Administrators" group, is a Domain administrator, and finally will run a manual interaction with Hyper-V to determine if Hyper-V is usable for the current user.

From: https://support.microsoft.com/en-us/kb/243330 SID: S-1-5-32-578 Name: BUILTIN\Hyper-V Administrators SID: S-1-5-21DOMAIN-512 Name: Domain Admins

Returns:

  • (Boolean)

101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/vagrant/util/platform.rb', line 101

def windows_hyperv_admin?
  return @_windows_hyperv_admin if defined?(@_windows_hyperv_admin)

  if ENV["VAGRANT_IS_HYPERV_ADMIN"]
    return @_windows_hyperv_admin = true
  end

  ps_cmd = "Write-Output ([System.Security.Principal.WindowsIdentity]::GetCurrent().Groups | " \
    "Select-Object Value | ConvertTo-JSON)"
  output = Vagrant::Util::PowerShell.execute_cmd(ps_cmd)
  if output
    groups = begin
               JSON.load(output)
             rescue JSON::ParserError
               []
             end
    admin_group = groups.detect do |g|
      g["Value"].to_s == "S-1-5-32-578" ||
        (g["Value"].start_with?("S-1-5-21") && g["Value"].to_s.end_with?("-512"))
    end

    if admin_group
      return @_windows_hyperv_admin = true
    end
  end

  ps_cmd = "$x = (Get-VMHost).Name; if($x -eq [System.Net.Dns]::GetHostName()){ Write-Output 'true'}"
  output = Vagrant::Util::PowerShell.execute_cmd(ps_cmd)
  result = output == "true"

  return @_windows_hyperv_admin = result
end

.windows_hyperv_enabled?Boolean

Checks if Hyper-V is enabled on the host system and returns true if enabled.

Returns:

  • (Boolean)

138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/vagrant/util/platform.rb', line 138

def windows_hyperv_enabled?
  return @_windows_hyperv_enabled if defined?(@_windows_hyperv_enabled)

  @_windows_hyperv_enabled = -> {
    ["Get-WindowsOptionalFeature", "Get-WindowsFeature"].each do |cmd_name|
      ps_cmd = "$(#{cmd_name} -FeatureName Microsoft-Hyper-V-Hypervisor).State"
      begin
        output = Vagrant::Util::PowerShell.execute_cmd(ps_cmd)
        return true if output == "Enabled"
      rescue Errors::PowerShellInvalidVersion
        logger.warn("Invalid PowerShell version detected during Hyper-V enable check")
        return false
      end
    end
    return false
  }.call

  return @_windows_hyperv_enabled
end

.windows_path(path) ⇒ String

Automatically convert a given path to a Windows path. Will only be applied if running on a Windows host. If running on Windows host within the WSL, the actual Windows path will be returned.

Parameters:

  • path (Pathname, String)

    Path to convert

Returns:

  • (String)

497
498
499
500
501
502
503
504
# File 'lib/vagrant/util/platform.rb', line 497

def windows_path(path)
  path = cygwin_windows_path(path)
  path = wsl_to_windows_path(path)
  if windows? || wsl?
    path = windows_unc_path(path)
  end
  path
end

.windows_unc_path(path) ⇒ String

Converts a given path to UNC format by adding a prefix and converting slashes.

Parameters:

  • path (String)

    Path to convert to UNC for Windows

Returns:

  • (String)

304
305
306
307
308
309
310
311
312
313
314
315
316
317
# File 'lib/vagrant/util/platform.rb', line 304

def windows_unc_path(path)
  path = path.gsub("/", "\\")

  # Convert to UNC path
  if path =~ /^[a-zA-Z]:\\?$/
    # If the path is just a drive letter, then return that as-is
    path + "\\"
  elsif path.start_with?("\\\\")
    # If the path already starts with `\\` assume UNC and return as-is
    path
  else
    "\\\\?\\" + path.gsub("/", "\\")
  end
end

.wsl?Boolean

Returns:

  • (Boolean)

42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/vagrant/util/platform.rb', line 42

def wsl?
  if !defined?(@_wsl)
    @_wsl = false
    SilenceWarnings.silence! do
      # Find 'microsoft' in /proc/version indicative of WSL
      if File.file?('/proc/version')
        osversion = File.open('/proc/version', &:gets)
        if osversion.downcase.include?("microsoft")
          @_wsl = true
        end
      end
    end
  end
  @_wsl
end

.wsl_drvfs_mountsArray<String>

Get list of local mount paths that are DrvFs file systems

@todo(chrisroberts): Constantize types for check

Returns:

  • (Array<String>)

558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
# File 'lib/vagrant/util/platform.rb', line 558

def wsl_drvfs_mounts
  if !defined?(@_wsl_drvfs_mounts)
    @_wsl_drvfs_mounts = []
    if wsl?
      result = Util::Subprocess.execute("mount")
      result.stdout.each_line do |line|
        info = line.match(MOUNT_PATTERN)
        if info && (info[:type] == "drvfs" || info[:type] == "9p")
          @_wsl_drvfs_mounts << info[:mount]
        end
      end
    end
  end
  @_wsl_drvfs_mounts
end

.wsl_drvfs_path?(path) ⇒ Boolean

Check if given path is located on DrvFs file system

Parameters:

  • path (String, Pathname)

    Path to check

Returns:

  • (Boolean)

578
579
580
581
582
583
584
585
# File 'lib/vagrant/util/platform.rb', line 578

def wsl_drvfs_path?(path)
  if wsl?
    wsl_drvfs_mounts.each do |mount_path|
      return true if path.to_s.start_with?(mount_path)
    end
  end
  false
end

.wsl_init(env, logger = nil) ⇒ Object

If running within the Windows Subsystem for Linux, this will provide simple setup to allow sharing of the user's VAGRANT_HOME directory within the subsystem

Parameters:

  • env (Environment)
  • logger (Logger) (defaults to: nil)

    Optional logger to display information


593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
# File 'lib/vagrant/util/platform.rb', line 593

def wsl_init(env, logger=nil)
  if wsl?
    if ENV["VAGRANT_WSL_ENABLE_WINDOWS_ACCESS"]
      wsl_validate_matching_vagrant_versions!
      shared_user = ENV["VAGRANT_WSL_WINDOWS_ACCESS_USER"]
      if shared_user.to_s.empty?
        shared_user = wsl_windows_username
      end
      if logger
        logger.warn("Windows Subsystem for Linux detected. Allowing access to user: #{shared_user}")
        logger.warn("Vagrant will be allowed to control Vagrant managed machines within the user's home path.")
      end
      if ENV["VAGRANT_HOME"] || ENV["VAGRANT_WSL_DISABLE_VAGRANT_HOME"]
        logger.warn("VAGRANT_HOME environment variable already set. Not overriding!") if logger
      else
        home_path = wsl_windows_accessible_path.to_s
        ENV["VAGRANT_HOME"] = File.join(home_path, ".vagrant.d")
        if logger
          logger.info("Overriding VAGRANT_HOME environment variable to configured windows user. (#{ENV["VAGRANT_HOME"]})")
        end
        true
      end
    else
      if env.local_data_path.to_s.start_with?("/mnt/")
        raise Vagrant::Errors::WSLVagrantAccessError
      end
    end
  end
end

.wsl_path?(path) ⇒ Boolean

Determine if given path is within the WSL rootfs. Returns true if within the subsystem, or false if outside the subsystem.

Parameters:

  • path (String)

    Path to check

Returns:

  • (Boolean)

    path is within subsystem


347
348
349
# File 'lib/vagrant/util/platform.rb', line 347

def wsl_path?(path)
  wsl? && !path.to_s.downcase.start_with?("/mnt/")
end

.wsl_rootfsString

Compute the path to rootfs of currently active WSL.

Returns:

  • (String)

    A path to rootfs of a current WSL instance.


354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
# File 'lib/vagrant/util/platform.rb', line 354

def wsl_rootfs
  return @_wsl_rootfs if defined?(@_wsl_rootfs)

  if wsl?
    # Mark our filesystem with a temporary file having an unique name.
    marker = Tempfile.new(Time.now.to_i.to_s)
    logger = Log4r::Logger.new("vagrant::util::platform::wsl")

    # Check for lxrun installation first
    lxrun_path = [wsl_windows_appdata_local, "lxss"].join("\\")
    paths = [lxrun_path]

    logger.debug("checking registry for WSL installation path")
    paths += PowerShell.execute_cmd(
      '(Get-ChildItem HKCU:\Software\Microsoft\Windows\CurrentVersion\Lxss ' \
        '| ForEach-Object {Get-ItemProperty $_.PSPath}).BasePath').to_s.split("\r\n").map(&:strip)
    paths.delete_if{|path| path.to_s.empty?}

    paths.each do |path|
      # Lowercase the drive letter, skip the next symbol (which is a
      # colon from a Windows path) and convert path to UNIX style.
      check_path = "/mnt/#{path[0, 1].downcase}#{path[2..-1].tr('\\', '/')}/rootfs"
      begin
        process = Subprocess.execute("wslpath", "-u", "-a", path)
        check_path = "#{process.stdout.chomp}/rootfs" if process.exit_code == 0
      rescue Errors::CommandUnavailable => e
        # pass
      end

      logger.debug("checking `#{path}` for current WSL instance")
      begin
        # https://blogs.msdn.microsoft.com/wsl/2016/06/15/wsl-file-system-support
        # Current WSL instance doesn't have an access to its mount from
        # within itself despite all others are available. That's the
        # hacky way we're using to determine current instance.
        # For example we have three WSL instances:
        # A -> C:\User\USER\AppData\Local\Packages\A\LocalState\rootfs
        # B -> C:\User\USER\AppData\Local\Packages\B\LocalState\rootfs
        # C -> C:\User\USER\AppData\Local\Packages\C\LocalState\rootfs
        # If we're in "A" WSL at the moment, then its path will not be
        # accessible since it's mounted for exactly the instance we're
        # in. All others can be opened.
        Dir.open(check_path) do |fs|
          # A fallback for a case if our trick will stop working. For
          # that we've created a temporary file with an unique name in
          # a current WSL and now seeking it among all WSL.
          if File.exist?("#{fs.path}/#{marker.path}")
            @_wsl_rootfs = path
            break
          end
        end
      rescue Errno::EACCES
        @_wsl_rootfs = path
        # You can create and simultaneously run multiple WSL instances,
        # comment out the "break", run this script within each one and
        # it'll return only single value.
        break
      rescue Errno::ENOENT
        # Warn about data discrepancy between Winreg and file system
        # states. For the sake of justice, it's worth mentioning that
        # it is possible only when someone will manually break WSL by
        # removing a directory of its base path (kinda "stupid WSL
        # uninstallation by removing hidden and system directory").
        logger.warn("WSL instance at `#{path} is broken or no longer exists")
      end
      # All other exceptions have to be raised since they will mean
      # something unpredictably terrible.
    end

    marker.close!

    raise Vagrant::Errors::WSLRootFsNotFoundError if @_wsl_rootfs.nil?
  end

  # Attach the rootfs leaf to the path
  if @_wsl_rootfs != lxrun_path
    @_wsl_rootfs = "#{@_wsl_rootfs}\\rootfs"
  end

  logger.debug("detected `#{@_wsl_rootfs}` as current WSL instance")

  @_wsl_rootfs
end

.wsl_to_windows_path(path) ⇒ String

Convert a WSL path to the local Windows path. This is useful for conversion when calling out to Windows executables from the WSL

Parameters:

  • path (String, Pathname)

    Path to convert

Returns:

  • (String)

444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
# File 'lib/vagrant/util/platform.rb', line 444

def wsl_to_windows_path(path)
  path = path.to_s
  if wsl? && wsl_windows_access? && !path.match(/^[a-zA-Z]:/)
    path = File.expand_path(path)
    begin
      process = Subprocess.execute("wslpath", "-w", "-a", path)
      return process.stdout.chomp if process.exit_code == 0
    rescue Errors::CommandUnavailable => e
      # pass
    end
    if wsl_path?(path)
      parts = path.split("/")
      parts.delete_if(&:empty?)
      root_path = wsl_rootfs
      # lxrun splits home separate so we need to account
      # for it's specialness here when we build the path
      if root_path.end_with?("lxss") && !(["root", "home"].include?(parts.first))
        root_path = "#{root_path}\\rootfs"
      end
      path = [root_path, *parts].join("\\")
    else
      path = path.sub("/mnt/", "")
      parts = path.split("/")
      parts.first << ":"
      path = parts.join("\\")
    end
  end
  path
end

.wsl_validate_matching_vagrant_versions!Object

Confirm Vagrant versions installed within the WSL and the Windows system are the same. Raise error if they do not match.


664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
# File 'lib/vagrant/util/platform.rb', line 664

def wsl_validate_matching_vagrant_versions!
  valid = false
  if Util::Which.which("vagrant.exe")
    result = Util::Subprocess.execute("vagrant.exe", "--version")
    if result.exit_code == 0
      windows_version = result.stdout.match(/Vagrant (?<version>[\w.-]+)/)
      if windows_version
        windows_version = windows_version[:version].strip
        valid = windows_version == Vagrant::VERSION
      end
    end
    if !valid
      raise Vagrant::Errors::WSLVagrantVersionMismatch,
        wsl_version: Vagrant::VERSION,
        windows_version: windows_version || "unknown"
    end
  end
end

.wsl_windows_access?Boolean

Allow Vagrant to access Vagrant managed machines outside the Windows Subsystem for Linux

Returns:

  • (Boolean)

510
511
512
513
514
515
# File 'lib/vagrant/util/platform.rb', line 510

def wsl_windows_access?
  if !defined?(@_wsl_windows_access)
    @_wsl_windows_access = wsl? && ENV["VAGRANT_WSL_ENABLE_WINDOWS_ACCESS"]
  end
  @_wsl_windows_access
end

.wsl_windows_access_bypass?(path) ⇒ Boolean

Checks given path to determine if Vagrant is allowed to bypass checks

Parameters:

  • path (String)

    Path to check

Returns:

  • (Boolean)

    Vagrant is allowed to bypass checks


546
547
548
549
# File 'lib/vagrant/util/platform.rb', line 546

def wsl_windows_access_bypass?(path)
  wsl? && wsl_windows_access? &&
    path.to_s.start_with?(wsl_windows_accessible_path.to_s)
end

.wsl_windows_accessible_pathPathname

The allowed windows system path Vagrant can manage from the Windows Subsystem for Linux

Returns:

  • (Pathname)

521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
# File 'lib/vagrant/util/platform.rb', line 521

def wsl_windows_accessible_path
  if !defined?(@_wsl_windows_accessible_path)
    access_path = ENV["VAGRANT_WSL_WINDOWS_ACCESS_USER_HOME_PATH"]
    if access_path.to_s.empty?
      begin
        process = Subprocess.execute("wslpath", "-u", "-a", wsl_windows_home)
        access_path = process.stdout.chomp if process.exit_code == 0
      rescue Errors::CommandUnavailable => e
        # pass
      end
    end
    if access_path.to_s.empty?
      access_path = wsl_windows_home.gsub("\\", "/").sub(":", "")
      access_path[0] = access_path[0].downcase
      access_path = "/mnt/#{access_path}"
    end
    @_wsl_windows_accessible_path = Pathname.new(access_path)
  end
  @_wsl_windows_accessible_path
end

.wsl_windows_appdata_localString, Nil

Fetch the Windows user local app data directory

Returns:

  • (String, Nil)

652
653
654
655
656
657
658
659
660
# File 'lib/vagrant/util/platform.rb', line 652

def wsl_windows_appdata_local
  if !@_wsl_windows_appdata_local
    result = Util::Subprocess.execute("cmd.exe", "/c", "echo %LOCALAPPDATA%")
    if result.exit_code == 0
      @_wsl_windows_appdata_local = result.stdout.gsub("\"", "").strip
    end
  end
  @_wsl_windows_appdata_local
end

.wsl_windows_homeString, Nil

Fetch the Windows user home directory

Returns:

  • (String, Nil)

639
640
641
642
643
644
645
646
647
# File 'lib/vagrant/util/platform.rb', line 639

def wsl_windows_home
  if !@_wsl_windows_home
    result = Util::Subprocess.execute("cmd.exe", "/c" "echo %USERPROFILE%")
    if result.exit_code == 0
      @_wsl_windows_home = result.stdout.gsub("\"", "").strip
    end
  end
  @_wsl_windows_home
end

.wsl_windows_usernameString, Nil

Fetch the Windows username currently in use

Returns:

  • (String, Nil)

626
627
628
629
630
631
632
633
634
# File 'lib/vagrant/util/platform.rb', line 626

def wsl_windows_username
  if !@_wsl_windows_username
    result = Util::Subprocess.execute("cmd.exe", "/c", "echo %USERNAME%")
    if result.exit_code == 0
      @_wsl_windows_username = result.stdout.strip
    end
  end
  @_wsl_windows_username
end