#!/bin/bash source ScriptFunctions Import File Import GoboLinux Import OptionParser Import String Import Directories Import UnionFS helpOnNoArguments=yes scriptDescription="Runs 'make install', using a sandbox environment." scriptCredits="Copyright (C) Hisham Muhammad, 2001-2005 - Released under the GNU GPL." scriptUsage="[] [ -- ]" scriptExample="--makefile makefile.unix --target install_shared WeirdSuperLib 2.4" scriptNotes=" Normally you'll want to use Compile(1) instead. '$scriptName' is called by Compile(1). " Add_Option_Entry "t" "target" "Makefile target to be used." "install" Add_Option_Entry "f" "makefile" "Specify which makefile to use." "Makefile" Add_Option_Entry "m" "make" "Use the given variant of make (ie: cmake). Use in recipe_type={makefile,configure}" "ColorMake" Add_Option_Entry "c" "command" "Use the given command instead of make (ie: python). Options --target and --makefile are then ignored." Add_Option_Entry "a" "add-allowed" "Specify additional allowed directories or files. Colon separated list." Add_Option_Entry "u" "unmanaged-files" "Specify allowed directories or files, which should be handled as unmanaged. Colon separated list." Add_Option_Boolean "F" "no-sandbox" "Do not protect the installation with a sandbox." Add_Option_Entry "e" "expand-sandbox" "By default, the sandbox is built relative to the current "\ "directory, '.'. Passing 1 to this option will build it relative to the parent directory, '..',"\ "passing 2 relative to '../..', and so on." "" Add_Option_Boolean "l" "allow-leftovers" "When using UnionFS, do not return a failure code when it catches files outside the sandbox." Parse_Options "$@" Boolean "verbose" && verbose="--verbose" Dir_Set Sandbox || Set_Boolean "no-sandbox" if Dir_Set Sandbox then Is_Writable "$goboExecutables" || Verify_Superuser fi ### Version #################################################################### # TODO: this code is copy-and-pasted from SymlinkProgram. # It should move into functions. [ "$(Arg 2)" ] || Die "Argument missing: specify program and version." unset unionsandbox if ! Boolean "no-sandbox" then if [ "$NO_UNIONFS" ] then Log_Terse "unionfs was bypassed with NO_UNIONFS. Fallback to FiboSandbox." elif ! Union_Is_Supported then Log_Terse "unionfs is unavailable. Fallback to FiboSandbox." else Log_Normal "$(Union_Backend) is available. Using UnionSandbox." unionsandbox=yes fi fi package="`basename "$(Arg 1)" /`" package="`GuessProgramCase "$(Arg 1)"`" packageDir=`Get_Dir runtime "$package" ''` if ! Is_Directory "$packageDir" then Die "Directory $packageDir does not exist." fi installPackageDir=`Get_Dir install "$package" ''` current="$packageDir/Current" requested_version=$(Arg 2) vdir=`Get_Dir runtime "$package" "$requested_version"` if { ! Is_Directory "$vdir" ;} && { ! Boolean "no-sandbox" ;} then Die "There is no version $requested_version for package $package." fi Dir_Set Current && [ -n "$version" -a "$version" != "$requested_version" ] && ln -sfn `basename "$vdir"` "$current" version="$requested_version" # exports to UnionSandbox export unionfsPackageDir="$installPackageDir/$version" if Dir_Set Current && ! Exists "$current" then youngestdir=`ls --sort=time "$packageDir" | head -n 1` ln -s "$youngestdir" "$current" fi ### Install #################################################################### function cleanup() { # If not using UnionSandbox (including --no-sandbox" and rootless) # undo symlink from Settings to Defaults/Settings settings="$installPackageDir/Settings" if ! [ "$unionsandbox" ] then if [ -z "$ROOTLESS_GOBOLINUX" ] then umount "${default_settings}" else Is_Link "${settings}" && rm "${settings}" Is_Directory "${settings}.hold" && mv "${settings}.hold" "${settings}" fi fi } function installation_failed() { cleanup Die "${1}" } trap "installation_failed 'Caught signal. Exiting...'" SIGHUP SIGINT SIGTERM Log_Normal "Installing $package..." unset $expandsandbox if Is_Entry "expand-sandbox" then for i in $(seq $(Entry "expand-sandbox")) do expandsandbox=$expandsandbox/.. done fi allowed=".$expandsandbox:$installPackageDir/$version:$packageDir/Settings" Is_Entry "add-allowed" && allowed="$allowed:$(Entry "add-allowed")" Is_Entry "unmanaged-files" && eval $(Split_String "unmanagedarray" "$(Entry "unmanaged-files")" ":") Log_Verbose "Sandbox options:" Log_Verbose "Allowed directories: ${allowed}" Log_Verbose "Unmanaged directories: ${unmanagedarray[@]}" settings="$installPackageDir/Settings" default_settings="$installPackageDir/$version/Resources/Defaults/Settings" for unmanaged in "${unmanagedarray[@]}" do # If it's not a directory (it's possible that it's a non-existant directory, but that's ok), strip one level # Also remove any $goboPrefix, since we will add it later to ensure that it is used even for recipes that don't use it [ ! -d "${unmanaged}" ] && unmanaged=$(echo "${unmanaged}" | sed -e 's,\(.*\)/[^/]*,\1,') [ "$goboPrefix" ] && unmanaged=$(echo "${unmanaged}" | sed -e 's,'"$goboPrefix"',,' ) # Make sure the directories exist Assert_Dir "${goboPrefix}${unmanaged}" Assert_Dir "${installPackageDir}/${version}/Resources/Unmanaged${unmanaged}" # Map them unmanagedmap="${installPackageDir}/${version}/Resources/Unmanaged${unmanaged}=${goboPrefix}${unmanaged}${unmanagedmap:+:${unmanagedmap}}" done if [ -n "$unionsandbox" ] then sandbox_rw="$installPackageDir/$version/.SandboxInstall_Root" rm -rf -- "$sandbox_rw" map_settings="--map ${default_settings}=${settings}${unmanagedmap:+:${unmanagedmap}}" sandbox="UnionSandbox $verbose --writedir $sandbox_rw --sandbox $allowed $map_settings -- " else sandbox="FiboSandbox $verbose --sandbox $allowed ${unmanagedmap:+--map ${unmanagedmap}} --" fi Boolean "no-sandbox" && sandbox= [ "$ROOTLESS_GOBOLINUX" ] && sandbox= # If not using UnionSandbox (including --no-sandbox" and rootless) # symlink Settings to Defaults/Settings if [ -z "$unionsandbox" ] then Assert_Dir $default_settings if [ -z "$ROOTLESS_GOBOLINUX" ] then mount --bind "${default_settings}" "${settings}" else Is_Directory "${settings}" && mv "${settings}" "${settings}.hold" ln -s "${default_settings}" "${settings}" fi fi eval `Args_To_Array args 3` if Is_Entry_Set "make" then makecmd=`Entry "make"` else makecmd="${compileMakeCommand:-ColorMake}" fi if Is_Entry "command" then $sandbox `Entry "command"` "${args[@]}" || installation_failed else $sandbox $makecmd -f "`Entry "makefile"`" installprefix="${installPackageDir}/${version}" INSIDE_GOBO_SANDBOX=1 "${args[@]}" `Entry "target"` || installation_failed fi result="$?" if [ "$unionsandbox" ] then # Postprocess contents of $sandbox_rw here Log_Normal "Postprocessing Sandbox" Quiet pushd $sandbox_rw rm -rf System/Variable/tmp/{*,.*} &> /dev/null rm -rf System/Kernel/Objects rm -f System/Kernel/Modules/*/modules.* rm -rf Files/Compile/Sources rm -f Programs/Glibc/Settings/ld.so.cache rm -f System/Variable/cache/ldconfig/aux-cache rm -rf System/Variable/cache/fontconfig rm -rf System/Variable/scrollkeeper rm -f System/Variable/log/scrollkeeper.log if [ "$package" != "Python" -a -d Programs/Python ] then find Programs/Python -type f -name "*.pyc" -or -name "*.pyo" | xargs rm -f &> /dev/null fi rm -f System/Settings/{passwd,passwd-,group,group-} rm -f System/Settings/mtab rm -f System/Kernel/Devices/null rm -f System/Kernel/Devices/tty rm -rf Users/*/.distcc find -type f -name "*__dir_opaque" | xargs rm -f &> /dev/null find -type f -name "*_HIDDEN~" | xargs rm -f &> /dev/null find -type f -name "*_DELETED~" | xargs rm -f &> /dev/null find -type f -name "\.wh.*" | xargs rm -f &> /dev/null find -type d | xargs rmdir -p --ignore-fail-on-non-empty &> /dev/null if [ "$goboIndex" ] then # Sometimes writes to symlinks let files appear in a previous directory of the same program. # We try to detect these cases here, moving files written there to the appropriate place. if wrong_version=`ls "./$installPackageDir" 2> /dev/null | grep -qv "$version\|Current\|Settings\|Variable"` then cp -a ./$installPackageDir/$wrong_version/* $installPackageDir/$version/ rm -rf ./Programs fi cp -a $sandbox_rw/$goboIndex/* $installPackageDir/$version rm -rf $sandbox_rw/$goboIndex rmdir $sandbox_rw/System 2> /dev/null fi Quiet popd [ -d "$sandbox_rw" ] && leftovers=`(cd $sandbox_rw; find *) 2>/dev/null` [ "$leftovers" ] && { Log_Normal "Left over files:\n$leftovers" if ! Boolean "allow-leftovers" then exit 21 # Remember Fibo. fi } Quiet rmdir $sandbox_rw fi cleanup exit $result