#!/bin/bash # ^ Requires GNU bash 2.xx or later (not ash nor sh) # ############################################################################# # # Copyright (C) 2005 Lasse Collin # # Redistribution and use of this script, with or without modification, is # permitted provided that the following conditions are met: # # 1. Redistributions of this script must retain the above copyright # notice, this list of conditions and the following disclaimer. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ############################################################################# # # Last modified: 2005-06-27 # ############################################################################# # Check how we are called; we need at least two parameters. if [ "$2" = "" -o "$1" = "--help" ]; then cat << EOF fakedestdir is an utility to help creating packages if makefile does not support DESTDIR or similar feature. fakedestdir is used as a replacement for the command 'make install'. Because fakedestdir is a script that makes a couple ugly tricks to achieve its destination, you should use it only when the makefile doesn't have a better alternative. Usage: fakedestdir Two log files, 'fakedestdir_make.log' and 'fakedestdir_faked.log', are created to the current directory. They can be useful in case of problems. Common and recommended use: ./configure --prefix=/usr make fakedestdir /tmp/mypkg install Sometimes it might be needed to combine fakedestdir with DESTDIR or prefix: ./configure --prefix=/usr make fakedestdir /tmp/package DESTDIR=/tmp/mypkg prefix=/tmp/mypkg/usr install WARNING: Don't use fakedestdir as root unless you know what you are doing! EOF exit 0 fi __fakedestdir_validate__() { # No spaces, dots or other problematic characters! [ "$(echo "$1" | sed -n '/^\/[a-zA-Z0-9._/-]*$/p')" = "" ] || return 0 echo "$(basename "$0"): $2" \ "a-z, A-Z, 0-9, dot (.), underscore (_) and hyphen (-)." exit 1 } if [ "${__FAKEDESTDIR_DESTDIR__}" = "" ]; then # Validate the path to the fakedestdir script: __fakedestdir_validate__ "$0" \ "The full path to the script '$0' can" \ "contain only characters" # Validate the PATH where we are installing from: __fakedestdir_validate__ "$PWD" \ "The full path to the current directory" \ "characters other than" # Validate the given DESTDIR. We want it to be simple and absolute # path so we can be lazier later. __fakedestdir_validate__ "$1" \ "Destination directory must be an absolute path" \ "(i.e. begin with '/') and can contain only characters" # Make sure the destdir exists: if [ ! -d "$1" ]; then mkdir -p "$1" || exit $? # mkdir shows an error message. fi export __FAKEDESTDIR_DESTDIR__="/.$1" # Prevent destdir being replaced. export __FAKEDESTDIR_SOURCEDIR__=$(echo "$PWD" | sed 's,\.,\\.,g') export __FAKEDESTDIR_LOG__="$PWD/fakedestdir_faked.log" rm -f "${__FAKEDESTDIR_LOG__}" shift 1 set -o pipefail make "SHELL=/.$0" "$@" 2>&1 | tee fakedestdir_make.log exit $? fi # The tricks begin... # make can call us with or without '-c' but we don't need it: [ "$1" = "-c" ] && shift 1 __FAKEDESTDIR_CMD__=$* ROOTDIRS='(bin|boot|dev|etc|home|lib|media|mnt|opt|sbin|tmp|usr|var)' # Everybody loves sed, right? ;-) __FAKEDESTDIR_CMD__=$(echo "${__FAKEDESTDIR_CMD__}" | sed -r " # Protect the paths pointing to the source directory tree: s,${__FAKEDESTDIR_SOURCEDIR__},/.&,g # libtool commands: s,(libtool )((--[^ ]* *)* )(/*${ROOTDIRS})\b,\1\2/.\4,g # Redirects to /dev/null or other devs: s,(>+ *)(/dev/[a-zA-Z0-9]+),\1/.\2,g # Other command names: s,(^|; *|; *do +|&& +|\|\| +)(/+${ROOTDIRS})\b,\1/.\2,g # Finaly replace paths pointing to directories in the filesystem root: s,( |'|:|=|-D)(/+${ROOTDIRS})\b,\1${__FAKEDESTDIR_DESTDIR__}\2,g") # Argument manipulation complete, good luck. unset ROOTDIRS echo "${__FAKEDESTDIR_CMD__}" >> "${__FAKEDESTDIR_LOG__}" eval "${__FAKEDESTDIR_CMD__}" # EOF