# encoding: utf-8## Phusion Passenger - https://www.phusionpassenger.com/# Copyright (c) 2014 Phusion## "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.## Permission is hereby granted, free of charge, to any person obtaining a copy# of this software and associated documentation files (the "Software"), to deal# in the Software without restriction, including without limitation the rights# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell# copies of the Software, and to permit persons to whom the Software is# furnished to do so, subject to the following conditions:## The above copyright notice and this permission notice shall be included in# all copies or substantial portions of the Software.## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN# THE SOFTWARE.require'fileutils'require'pathname'require'etc'PhusionPassenger.require_passenger_lib'constants'PhusionPassenger.require_passenger_lib'ruby_core_enhancements'PhusionPassenger.require_passenger_lib'console_text_template'PhusionPassenger.require_passenger_lib'platform_info/ruby'PhusionPassenger.require_passenger_lib'platform_info/depcheck'PhusionPassenger.require_passenger_lib'utils/ansi_colors'modulePhusionPassengermoduleConfigmoduleInstallationUtilsextendself# Make methods available as class methods.defself.included(klass)# When included into another class, make sure that Utils# methods are made private.public_instance_methods(false).eachdo|method_name|klass.send(:private,method_name)endenddeffind_or_create_writable_support_binaries_dir!ifFile.exist?(PhusionPassenger.support_binaries_dir)result=directory_writable?(PhusionPassenger.support_binaries_dir)ifresult==true# return value can be a SystemCallErrorreturnPhusionPassenger.support_binaries_direndifProcess.euid==0ifresult==falseprint_installation_error_headerrender_template'installation_utils/support_binaries_dir_not_writable_despite_running_as_root',:dir=>PhusionPassenger.support_binaries_dir,:myself=>myselfelserender_template'installation_utils/unexpected_filesystem_problem',:dir=>PhusionPassenger.support_binaries_dir,:exception=>resultendabortelsereturnfind_or_create_writable_user_support_binaries_dir!endelseifProcess.euid==0mkdir_p_preserve_parent_owner(PhusionPassenger.support_binaries_dir)returnPhusionPassenger.support_binaries_direlsereturnfind_or_create_writable_user_support_binaries_dir!endendenddefcheck_for_download_tool!PlatformInfo::Depcheck.load('depcheck_specs/utilities')result=PlatformInfo::Depcheck.find('download-tool').check# Don't output anything if there is a download tool.# We want to be as quiet as possible.returnifresult&&result[:found]colors=@colors||Utils::AnsiColors.newputscolors.ansi_colorize("<banner>Checking for basic prerequities...</banner>")putsrunner=PlatformInfo::Depcheck::ConsoleRunner.newrunner.add('download-tool')result=runner.check_allputsif!resultputs"---------------------------------------"putsrender_template'installation_utils/download_tool_missing',:runner=>runnerabortendend# Override this method to print a different headerdefprint_installation_error_headerif@colorsred=@colors.redreset=@colors.resetelsered=nilreset=nilend@logger.warn"------------------------------------------"if@loggerputs"#{red}Cannot proceed with installation#{reset}"putsenddefrakereturn"env NOEXEC_DISABLE=1 #{PlatformInfo.rake_command}"enddefrun_rake_task!(target)total_lines=`#{rake}#{target} --dry-run STDERR_TO_STDOUT=1`.split("\n").size-1backlog=""command="#{rake}#{target} --trace STDERR_TO_STDOUT=1"IO.popen(command,"rb")do|io|progress=1while!io.eof?line=io.readlineyield(progress,total_lines)ifline=~/^\*\* /backlog.replace("")progress+=1elsebacklog<<lineendendendif$?.exitstatus!=0stderr=@stderr||STDERRstderr.putsstderr.puts"*** ERROR: the following command failed:"stderr.puts(backlog)exit1endendprivate# We can't use File.writable() and friends here because they# don't always work right with ACLs. Instead of we use 'real'# checks.defdirectory_writable?(path)filename="#{path}/.__test_#{object_id}__.txt"@logger.debug"Checking whether we can write to #{path}..."if@loggerbeginFile.new(filename,"w").close@logger.debug"Yes"if@loggerreturntruerescueErrno::EACCES@logger.debug"No"if@loggerreturnfalserescueSystemCallError=>e@logger.warn"Unable to check whether we can write to #{path}: #{e}"if@loggerreturneensureFile.unlink(filename)rescuenilendenddeffind_or_create_writable_user_support_binaries_dir!if!File.exist?(PhusionPassenger.user_support_binaries_dir)create_user_support_binaries_dir!endresult=directory_writable?(PhusionPassenger.user_support_binaries_dir)caseresultwhentruereturnPhusionPassenger.user_support_binaries_dirwhenfalseprint_installation_error_headerrender_template'installation_utils/user_support_binaries_dir_not_writable'abortelseprint_installation_error_headerrender_template'installation_utils/unexpected_filesystem_problem',:dir=>PhusionPassenger.support_binaries_dir,:exception=>resultabortendenddefcreate_user_support_binaries_dir!dir=PhusionPassenger.user_support_binaries_dirbeginmkdir_p_preserve_parent_owner(dir)rescueErrno::EACCESprint_installation_error_headerrender_template'installation_utils/cannot_create_user_support_binaries_dir',:dir=>dir,:myself=>myselfabortrescueSystemCallErrorprint_installation_error_headerrender_template'installation_utils/unexpected_filesystem_problem',:dir=>dir,:exception=>resultabortendend# When creating PhusionPassenger.support_binaries_dir, preserve the# parent directory's UID and GID. This way, running `passenger-config compile-agent`# with sudo privileged, even though Phusion Passenger isn't installed as root,# won't mess up permissions.defmkdir_p_preserve_parent_owner(path)Pathname.new(path).descenddo|subpath|if!subpath.exist?stat=subpath.parent.statDir.mkdir(subpath.to_s)ifProcess.euid==0File.chown(stat.uid,stat.gid,subpath.to_s)endendendenddefmyselfreturn`whoami`.stripenddefrender_template(name,options={})options.merge!(:colors=>@colors||PhusionPassenger::Utils::AnsiColors.new)putsConsoleTextTemplate.new({:file=>"config/#{name}"},options).resultendendend# module Configend# module PhusionPassenger