167 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Ruby
		
	
	
	
	
	
			
		
		
	
	
			167 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Ruby
		
	
	
	
	
	
| # typed: true # rubocop:disable Sorbet/StrictSigil
 | |
| # frozen_string_literal: true
 | |
| 
 | |
| require "tempfile"
 | |
| require "utils/shell"
 | |
| require "hardware"
 | |
| require "os/linux/glibc"
 | |
| require "os/linux/kernel"
 | |
| 
 | |
| module OS
 | |
|   module Linux
 | |
|     module Diagnostic
 | |
|       module Checks
 | |
|         extend T::Helpers
 | |
| 
 | |
|         requires_ancestor { Homebrew::Diagnostic::Checks }
 | |
| 
 | |
|         def fatal_preinstall_checks
 | |
|           %w[
 | |
|             check_access_directories
 | |
|             check_linuxbrew_core
 | |
|             check_linuxbrew_bottle_domain
 | |
|           ].freeze
 | |
|         end
 | |
| 
 | |
|         def supported_configuration_checks
 | |
|           %w[
 | |
|             check_glibc_minimum_version
 | |
|             check_kernel_minimum_version
 | |
|             check_supported_architecture
 | |
|           ].freeze
 | |
|         end
 | |
| 
 | |
|         def check_tmpdir_sticky_bit
 | |
|           message = generic_check_tmpdir_sticky_bit
 | |
|           return if message.nil?
 | |
| 
 | |
|           message + <<~EOS
 | |
|             If you don't have administrative privileges on this machine,
 | |
|             create a directory and set the HOMEBREW_TEMP environment variable,
 | |
|             for example:
 | |
|               install -d -m 1755 ~/tmp
 | |
|               #{Utils::Shell.set_variable_in_profile("HOMEBREW_TEMP", "~/tmp")}
 | |
|           EOS
 | |
|         end
 | |
| 
 | |
|         def check_tmpdir_executable
 | |
|           f = Tempfile.new(%w[homebrew_check_tmpdir_executable .sh], HOMEBREW_TEMP)
 | |
|           f.write "#!/bin/sh\n"
 | |
|           f.chmod 0700
 | |
|           f.close
 | |
|           return if system T.must(f.path)
 | |
| 
 | |
|           <<~EOS
 | |
|             The directory #{HOMEBREW_TEMP} does not permit executing
 | |
|             programs. It is likely mounted as "noexec". Please set HOMEBREW_TEMP
 | |
|             in your #{Utils::Shell.profile} to a different directory, for example:
 | |
|               export HOMEBREW_TEMP=~/tmp
 | |
|               echo 'export HOMEBREW_TEMP=~/tmp' >> #{Utils::Shell.profile}
 | |
|           EOS
 | |
|         ensure
 | |
|           f&.unlink
 | |
|         end
 | |
| 
 | |
|         def check_umask_not_zero
 | |
|           return unless File.umask.zero?
 | |
| 
 | |
|           <<~EOS
 | |
|             umask is currently set to 000. Directories created by Homebrew cannot
 | |
|             be world-writable. This issue can be resolved by adding "umask 002" to
 | |
|             your #{Utils::Shell.profile}:
 | |
|               echo 'umask 002' >> #{Utils::Shell.profile}
 | |
|           EOS
 | |
|         end
 | |
| 
 | |
|         def check_supported_architecture
 | |
|           return if Hardware::CPU.arch == :x86_64
 | |
| 
 | |
|           <<~EOS
 | |
|             Your CPU architecture (#{Hardware::CPU.arch}) is not supported. We only support
 | |
|             x86_64 CPU architectures. You will be unable to use binary packages (bottles).
 | |
|             #{please_create_pull_requests}
 | |
|           EOS
 | |
|         end
 | |
| 
 | |
|         def check_glibc_minimum_version
 | |
|           return unless OS::Linux::Glibc.below_minimum_version?
 | |
| 
 | |
|           <<~EOS
 | |
|             Your system glibc #{OS::Linux::Glibc.system_version} is too old.
 | |
|             We only support glibc #{OS::Linux::Glibc.minimum_version} or later.
 | |
|             #{please_create_pull_requests}
 | |
|             We recommend updating to a newer version via your distribution's
 | |
|             package manager, upgrading your distribution to the latest version,
 | |
|             or changing distributions.
 | |
|           EOS
 | |
|         end
 | |
| 
 | |
|         def check_kernel_minimum_version
 | |
|           return unless OS::Linux::Kernel.below_minimum_version?
 | |
| 
 | |
|           <<~EOS
 | |
|             Your Linux kernel #{OS.kernel_version} is too old.
 | |
|             We only support kernel #{OS::Linux::Kernel.minimum_version} or later.
 | |
|             You will be unable to use binary packages (bottles).
 | |
|             #{please_create_pull_requests}
 | |
|             We recommend updating to a newer version via your distribution's
 | |
|             package manager, upgrading your distribution to the latest version,
 | |
|             or changing distributions.
 | |
|           EOS
 | |
|         end
 | |
| 
 | |
|         def check_linuxbrew_core
 | |
|           return unless Homebrew::EnvConfig.no_install_from_api?
 | |
|           return unless CoreTap.instance.linuxbrew_core?
 | |
| 
 | |
|           <<~EOS
 | |
|             Your Linux core repository is still linuxbrew-core.
 | |
|             You must `brew update` to update to homebrew-core.
 | |
|           EOS
 | |
|         end
 | |
| 
 | |
|         def check_linuxbrew_bottle_domain
 | |
|           return unless Homebrew::EnvConfig.bottle_domain.include?("linuxbrew")
 | |
| 
 | |
|           <<~EOS
 | |
|             Your HOMEBREW_BOTTLE_DOMAIN still contains "linuxbrew".
 | |
|             You must unset it (or adjust it to not contain linuxbrew
 | |
|             e.g. by using homebrew instead).
 | |
|           EOS
 | |
|         end
 | |
| 
 | |
|         def check_gcc_dependent_linkage
 | |
|           gcc_dependents = ::Formula.installed.select do |formula|
 | |
|             next false unless formula.tap&.core_tap?
 | |
| 
 | |
|             # FIXME: This includes formulae that have no runtime dependency on GCC.
 | |
|             formula.recursive_dependencies.map(&:name).include? "gcc"
 | |
|           rescue TapFormulaUnavailableError
 | |
|             false
 | |
|           end
 | |
|           return if gcc_dependents.empty?
 | |
| 
 | |
|           badly_linked = gcc_dependents.select do |dependent|
 | |
|             keg = Keg.new(dependent.prefix)
 | |
|             keg.binary_executable_or_library_files.any? do |binary|
 | |
|               paths = binary.rpaths
 | |
|               versioned_linkage = paths.any? { |path| path.match?(%r{lib/gcc/\d+$}) }
 | |
|               unversioned_linkage = paths.any? { |path| path.match?(%r{lib/gcc/current$}) }
 | |
| 
 | |
|               versioned_linkage && !unversioned_linkage
 | |
|             end
 | |
|           end
 | |
|           return if badly_linked.empty?
 | |
| 
 | |
|           inject_file_list badly_linked, <<~EOS
 | |
|             Formulae which link to GCC through a versioned path were found. These formulae
 | |
|             are prone to breaking when GCC is updated. You should `brew reinstall` these formulae:
 | |
|           EOS
 | |
|         end
 | |
|       end
 | |
|     end
 | |
|   end
 | |
| end
 | |
| 
 | |
| Homebrew::Diagnostic::Checks.prepend(OS::Linux::Diagnostic::Checks)
 | 
