"Fossies" - the Fresh Open Source Software Archive

Member "vagrant-2.2.14/plugins/guests/darwin/cap/mount_vmware_shared_folder.rb" (20 Nov 2020, 5101 Bytes) of package /linux/misc/vagrant-2.2.14.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Ruby source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. See also the latest Fossies "Diffs" side-by-side code changes report for "mount_vmware_shared_folder.rb": 2.2.13_vs_2.2.14.

    1 require "securerandom"
    2 
    3 module VagrantPlugins
    4   module GuestDarwin
    5     module Cap
    6       class MountVmwareSharedFolder
    7 
    8         MACOS_BIGSUR_DARWIN_VERSION = 20.freeze
    9 
   10         # Entry point for hook to called delayed actions
   11         # which finalizing the synced folders setup on
   12         # the guest
   13         def self.write_apfs_firmlinks(env)
   14           if env && env[:machine] && delayed = apfs_firmlinks_delayed.delete(env[:machine].id)
   15             delayed.call
   16           end
   17         end
   18 
   19         # @return [Hash] storage location for delayed actions
   20         def self.apfs_firmlinks_delayed
   21           if !@_apfs_firmlinks
   22             @_apfs_firmlinks = {}
   23           end
   24           @_apfs_firmlinks
   25         end
   26 
   27         # we seem to be unable to ask 'mount -t vmhgfs' to mount the roots
   28         # of specific shares, so instead we symlink from what is already
   29         # mounted by the guest tools
   30         # (ie. the behaviour of the VMware_fusion provider prior to 0.8.x)
   31 
   32         def self.mount_vmware_shared_folder(machine, name, guestpath, options)
   33           # Use this variable to determine which machines
   34           # have been registered with after hook
   35           @apply_firmlinks ||= Hash.new{ |h, k| h[k] = {bootstrap: false, content: []} }
   36 
   37           machine.communicate.tap do |comm|
   38             # check if we are dealing with an APFS root container
   39             if comm.test("test -d /System/Volumes/Data")
   40               parts = Pathname.new(guestpath).descend.to_a
   41               firmlink = parts[1].to_s
   42               firmlink.slice!(0, 1) if firmlink.start_with?("/")
   43               if parts.size > 2
   44                 guestpath = File.join("/System/Volumes/Data", guestpath)
   45               else
   46                 guestpath = nil
   47               end
   48             end
   49 
   50             # Remove existing symlink or directory if defined
   51             if guestpath
   52               if comm.test("test -L \"#{guestpath}\"")
   53                 comm.sudo("rm -f \"#{guestpath}\"")
   54               elsif comm.test("test -d \"#{guestpath}\"")
   55                 comm.sudo("rm -Rf \"#{guestpath}\"")
   56               end
   57 
   58               # create intermediate directories if needed
   59               intermediate_dir = File.dirname(guestpath)
   60               if intermediate_dir != "/"
   61                 comm.sudo("mkdir -p \"#{intermediate_dir}\"")
   62               end
   63 
   64               comm.sudo("ln -s \"/Volumes/VMware Shared Folders/#{name}\" \"#{guestpath}\"")
   65             end
   66 
   67             if firmlink && !system_firmlink?(firmlink)
   68               if guestpath.nil?
   69                 guestpath = "/Volumes/VMware Shared Folders/#{name}"
   70               else
   71                 guestpath = File.join("/System/Volumes/Data", firmlink)
   72               end
   73 
   74               share_line = "#{firmlink}\t#{guestpath}"
   75 
   76               # Check if the line is already defined. If so, bail since we are done
   77               if !comm.test("[[ \"$(</etc/synthetic.conf)\" = *\"#{share_line}\"* ]]")
   78                 @apply_firmlinks[machine.id][:bootstrap] = true
   79               end
   80 
   81               # If we haven't already added our hook to apply firmlinks, do it now
   82               if @apply_firmlinks[machine.id][:content].empty?
   83                 apfs_firmlinks_delayed[machine.id] = proc do
   84                   content = @apply_firmlinks[machine.id][:content].join("\n")
   85                   # Write out the synthetic file
   86                   comm.sudo("echo -e #{content.inspect} > /etc/synthetic.conf")
   87                   if @apply_firmlinks[machine.id][:bootstrap]
   88                     if machine.guest.capability("darwin_major_version").to_i < MACOS_BIGSUR_DARWIN_VERSION
   89                       apfs_bootstrap_flag = "-B"
   90                       expected_rc = 0
   91                     else
   92                       apfs_bootstrap_flag = "-t"
   93                       expected_rc = 253
   94                     end
   95                     # Re-bootstrap the root container to pick up firmlink updates
   96                     comm.sudo("/System/Library/Filesystems/apfs.fs/Contents/Resources/apfs.util #{apfs_bootstrap_flag}", good_exit: [expected_rc])
   97                   end
   98                 end
   99               end
  100               @apply_firmlinks[machine.id][:content] << share_line
  101             end
  102           end
  103         end
  104 
  105         # Check if firmlink is provided by the system
  106         #
  107         # @param [String] firmlink Firmlink path
  108         # @return [Boolean]
  109         def self.system_firmlink?(firmlink)
  110           if !@_firmlinks
  111             if File.exist?("/usr/share/firmlinks")
  112               @_firmlinks = File.readlines("/usr/share/firmlinks").map do |line|
  113                 line.split.first
  114               end
  115             else
  116               @_firmlinks = []
  117             end
  118           end
  119           firmlink = "/#{firmlink}" if !firmlink.start_with?("/")
  120           @_firmlinks.include?(firmlink)
  121         end
  122 
  123         # @private
  124         # Reset the cached values for capability. This is not considered a public
  125         # API and should only be used for testing.
  126         def self.reset!
  127           instance_variables.each(&method(:remove_instance_variable))
  128         end
  129       end
  130     end
  131   end
  132 end