From 84d10dce570d351e364281dc3965a7f90e7ff51e Mon Sep 17 00:00:00 2001
From: Jesse Keating <omgjlk@us.ibm.com>
Date: Thu, 18 May 2017 11:09:32 -0700
Subject: [PATCH] Remove use of 'which'.

Instead, either use the bash built-in of type to ensure it exists. Since
which is an external dep, things can fail oddly in a constrained
environment.

Also add a dib-lint test for this.

Change-Id: I645029f5b5bfe1198c89ce10fd3246be8636e8af
Signed-off-by: Jesse Keating <omgjlk@us.ibm.com>
---
 bin/dib-lint                                    | 17 +++++++++++++++++
 .../bootloader/finalise.d/50-bootloader         |  6 +++---
 .../post-install.d/99-build-dracut-ramdisk      |  2 +-
 .../elements/hwdiscovery/init.d/60-hwdiscovery  |  2 +-
 .../post-install.d/01-ensure-binaries           |  2 +-
 .../ramdisk/post-install.d/99-build-ramdisk     |  2 +-
 .../finalise.d/90-selinux-fixfiles-restore      |  2 +-
 diskimage_builder/lib/disk-image-create         | 10 +++++-----
 diskimage_builder/lib/ramdisk-functions         |  2 +-
 tests/run_output_format_test.sh                 |  2 +-
 10 files changed, 32 insertions(+), 15 deletions(-)

diff --git a/bin/dib-lint b/bin/dib-lint
index c622e0e75..ba528bdb2 100755
--- a/bin/dib-lint
+++ b/bin/dib-lint
@@ -209,6 +209,23 @@ for i in $(find $ELEMENTS_DIR -type f \
         fi
     fi
 
+    # check that which calls are not used. It is not built in and is missing
+    # from some constrained environments
+    if ! excluded which; then
+        while read LINE
+        do
+            if [[ $LINE =~ "which " ]]; then
+                #  Don't match:
+                #  - explicitly ignored
+                #  - commented
+                if [[ $LINE =~ (dib-lint: which|^#) ]]; then
+                    continue
+                fi
+                error "$i : potential use of which\n -- $LINE"
+            fi
+        done < $i
+    fi
+
 done
 
 echo "Checking indents..."
diff --git a/diskimage_builder/elements/bootloader/finalise.d/50-bootloader b/diskimage_builder/elements/bootloader/finalise.d/50-bootloader
index a23086603..a7536889d 100755
--- a/diskimage_builder/elements/bootloader/finalise.d/50-bootloader
+++ b/diskimage_builder/elements/bootloader/finalise.d/50-bootloader
@@ -60,9 +60,9 @@ function install_grub2 {
 
     # XXX: grub-probe on the nbd0/loop0 device returns nothing - workaround, manually
     # specify modules. https://bugs.launchpad.net/ubuntu/+source/grub2/+bug/1073731
-    GRUBNAME=$(which grub-install) || echo "trying grub2-install"
+    GRUBNAME=$(type -p grub-install) || echo "trying grub2-install"
     if [ -z "$GRUBNAME" ]; then
-        GRUBNAME=$(which grub2-install)
+        GRUBNAME=$(type -p grub2-install)
     fi
 
     # If no GRUB2 is found, fallback to extlinux
@@ -136,7 +136,7 @@ function install_grub2 {
     echo 'GRUB_GFXPAYLOAD_LINUX=text' >>/etc/default/grub
     echo 'GRUB_CMDLINE_LINUX_DEFAULT="console=tty0 console=ttyS0,115200 no_timer_check"' >>/etc/default/grub
     echo 'GRUB_SERIAL_COMMAND="serial --speed=115200 --unit=0 --word=8 --parity=no --stop=1"' >>/etc/default/grub
-    if which grub2-mkconfig >/dev/null; then
+    if type grub2-mkconfig >/dev/null; then
         GRUB_MKCONFIG="grub2-mkconfig -o $GRUB_CFG"
     else
         GRUB_MKCONFIG="grub-mkconfig -o $GRUB_CFG"
diff --git a/diskimage_builder/elements/dracut-ramdisk/post-install.d/99-build-dracut-ramdisk b/diskimage_builder/elements/dracut-ramdisk/post-install.d/99-build-dracut-ramdisk
index a4ef693a8..e7d939b9f 100755
--- a/diskimage_builder/elements/dracut-ramdisk/post-install.d/99-build-dracut-ramdisk
+++ b/diskimage_builder/elements/dracut-ramdisk/post-install.d/99-build-dracut-ramdisk
@@ -46,7 +46,7 @@ mv "$TMP_MOUNT_PATH/init" "$MODULE_PATH/80deploy-ramdisk/init.sh"
 # been released for all of our supported platforms we can remove this.  Until then
 # this makes --include work correctly and will be a noop if we're running a fixed
 # Dracut version.
-sed -i 's|cp --reflink=auto --sparse=auto -fa -t "$s" "$i"$|cp --reflink=auto --sparse=auto -fa -t "${initdir}/${tgt}" "$i"|g' $(which dracut)
+sed -i 's|cp --reflink=auto --sparse=auto -fa -t "$s" "$i"$|cp --reflink=auto --sparse=auto -fa -t "${initdir}/${tgt}" "$i"|g' $(type -p dracut)
 
 # Notes on the options passed to Dracut:
 # -N: Do not build a host-specific ramdisk.  We want to be able to run this ramdisk
diff --git a/diskimage_builder/elements/hwdiscovery/init.d/60-hwdiscovery b/diskimage_builder/elements/hwdiscovery/init.d/60-hwdiscovery
index a87aed04b..0b5115ba7 100644
--- a/diskimage_builder/elements/hwdiscovery/init.d/60-hwdiscovery
+++ b/diskimage_builder/elements/hwdiscovery/init.d/60-hwdiscovery
@@ -20,7 +20,7 @@ function pxe_mac() {
       # boot interface with no problems.
       _mac="${BASH_REMATCH[1]//-/:}"
       _mac="${_mac#*:}"
-  elif [[ -d /sys/firmware/efi ]] && which efibootmgr &>/dev/null; then
+  elif [[ -d /sys/firmware/efi ]] && type efibootmgr &>/dev/null; then
       # Likewise, if we booted via the network while running in UEFI mode, and
       # efibootmgr is installed, we can determine the MAC address of the nic we
       # booted from.  It would be good to have code that can also do this using
diff --git a/diskimage_builder/elements/ramdisk-base/post-install.d/01-ensure-binaries b/diskimage_builder/elements/ramdisk-base/post-install.d/01-ensure-binaries
index 82c29f66b..9483852b0 100755
--- a/diskimage_builder/elements/ramdisk-base/post-install.d/01-ensure-binaries
+++ b/diskimage_builder/elements/ramdisk-base/post-install.d/01-ensure-binaries
@@ -32,7 +32,7 @@ for _FILE in $(ls ${TARGET_DIR}/binary-deps.d/) ; do
 done
 
 for _BIN in $BINARY_DEPS ; do
-    _LOCATION=$(which "$_BIN" || echo "")
+    _LOCATION=$(type -p "$_BIN" || echo "")
     if [ -z "$_LOCATION" ]; then
         echo "$_BIN is not found in PATH. Please ensure your elements install it"
         exit 1
diff --git a/diskimage_builder/elements/ramdisk/post-install.d/99-build-ramdisk b/diskimage_builder/elements/ramdisk/post-install.d/99-build-ramdisk
index 44fbc8124..80948dba6 100755
--- a/diskimage_builder/elements/ramdisk/post-install.d/99-build-ramdisk
+++ b/diskimage_builder/elements/ramdisk/post-install.d/99-build-ramdisk
@@ -33,7 +33,7 @@ FIRMWARE_DIR=$MODULE_ROOT/lib/firmware
 LIB_UDEV=$LIB_UDEV_ROOT/lib/udev
 INIT="$_LIB/scripts/init"
 FUNCTIONS_D="$_LIB/scripts/d"
-BUSYBOX=${BUSYBOX:-$(which busybox)}
+BUSYBOX=${BUSYBOX:-$(type -p busybox)}
 # NOTE(bnemec): IMAGE_ELEMENT is normally set in disk-image-create, but we're
 # not using that to build the image here.
 IMAGE_ELEMENT=
diff --git a/diskimage_builder/elements/rpm-distro/finalise.d/90-selinux-fixfiles-restore b/diskimage_builder/elements/rpm-distro/finalise.d/90-selinux-fixfiles-restore
index 0598d63ee..9abdda0bf 100755
--- a/diskimage_builder/elements/rpm-distro/finalise.d/90-selinux-fixfiles-restore
+++ b/diskimage_builder/elements/rpm-distro/finalise.d/90-selinux-fixfiles-restore
@@ -6,7 +6,7 @@ fi
 set -eu
 set -o pipefail
 
-SETFILES=$(which setfiles || true)
+SETFILES=$(type -p setfiles || true)
 if [ -e /etc/selinux/targeted/contexts/files/file_contexts -a -x "${SETFILES}" ]; then
     # get all mounpoints in the system
     IFS='|' read -ra SPLIT_MOUNTS <<< "$DIB_MOUNTPOINTS"
diff --git a/diskimage_builder/lib/disk-image-create b/diskimage_builder/lib/disk-image-create
index 88c64ed32..d810f02d1 100644
--- a/diskimage_builder/lib/disk-image-create
+++ b/diskimage_builder/lib/disk-image-create
@@ -208,7 +208,7 @@ fi
 for X in ${!IMAGE_TYPES[@]}; do
     case "${IMAGE_TYPES[$X]}" in
         qcow2)
-            if [ -z "$(which qemu-img)" ]; then
+            if ! type qemu-img > /dev/null 2>&1; then
                 echo "qcow2 output format specified but qemu-img executable not found."
                 exit 1
             fi
@@ -218,19 +218,19 @@ for X in ${!IMAGE_TYPES[@]}; do
             IMAGE_TYPES+=('tar')
             ;;
         vhd)
-            if [ -z "$(which vhd-util)" ]; then
+            if ! type vhd-util > /dev/null 2>&1; then
                 echo "vhd output format specified but no vhd-util executable found."
                 exit 1
             fi
             ;;
         squashfs)
-            if [ -z "$(which mksquashfs)" ]; then
+            if ! type mksquashfs > /dev/null 2>&1; then
                 echo "squashfs output format specified but no mksquashfs executable found."
                 exit 1
             fi
             ;;
         docker)
-            if [ -z "$(which docker)" ]; then
+            if ! type docker > /dev/null 2>&1; then
                 echo "docker output format specified but no docker executable found."
                 exit 1
             fi
@@ -244,7 +244,7 @@ done
 
 # NOTE: fstrim is on most all recent systems. It is provided by the util-linux
 # package.
-if [[ -z "$(which fstrim)" ]]; then
+if ! type fstrim > /dev/null 2>&1; then
     echo "fstrim utility is not found. This is provided by util-linux package"
     echo "Please check your PATH variable is set correctly"
     exit 1
diff --git a/diskimage_builder/lib/ramdisk-functions b/diskimage_builder/lib/ramdisk-functions
index 6797114d1..68bea8396 100644
--- a/diskimage_builder/lib/ramdisk-functions
+++ b/diskimage_builder/lib/ramdisk-functions
@@ -163,7 +163,7 @@ function populate_lib () {
     if busybox_list | grep -v "^ip$" | grep "^$i\$" >/dev/null; then
       continue
     fi
-    path=`which $i 2>/dev/null` || path=$i
+    path=`type -p $i 2>/dev/null` || path=$i
     if ! [ -x "$path" ]; then
       echo "$i is not found in PATH" 2>&1
       exit 1
diff --git a/tests/run_output_format_test.sh b/tests/run_output_format_test.sh
index 8f2e968ad..bbff162fa 100755
--- a/tests/run_output_format_test.sh
+++ b/tests/run_output_format_test.sh
@@ -61,7 +61,7 @@ function build_test_image() {
 
 test_formats="tar tgz squashfs raw qcow2 docker aci"
 for binary in qemu-img docker mksquashfs; do
-    if [ -z "$(which $binary)" ]; then
+    if [ -z "$(type $binary)" ]; then
         echo "Warning: No $binary binary found, cowardly refusing to run tests."
         exit 1
     fi