From e9ce0316ebcbddcc07d0ee0a47324d94c70ca8c7 Mon Sep 17 00:00:00 2001
From: Christoph Reiter <reiter.christoph@gmail.com>
Date: Thu, 3 Jun 2021 16:22:43 +0200
Subject: [PATCH 01/N] Msysize

---
 lib/libalpm/add.c                             |   2 +
 .../lint_package/build_references.sh.in       |   8 +
 scripts/libmakepkg/tidy/staticlibs.sh.in      |   4 +-
 scripts/libmakepkg/tidy/strip.sh.in           | 180 ++++++++++++------
 scripts/libmakepkg/utils_fixed_path.sh.in     |  34 ++++
 scripts/makepkg.sh.in                         | 174 +++++++----------
 scripts/pacman-db-upgrade.sh.in               |  12 +-
 scripts/pacman-key.sh.in                      |  22 +--
 scripts/repo-add.sh.in                        |  11 +-
 scripts/wrapper.sh.in                         |   2 +-
 src/pacman/callback.c                         |   7 +-
 src/pacman/check.c                            |   2 +
 src/pacman/pacman.c                           |   4 +
 test/pacman/pmtest.py                         |  19 +-
 14 files changed, 283 insertions(+), 198 deletions(-)
 create mode 100644 scripts/libmakepkg/utils_fixed_path.sh.in

diff --git a/lib/libalpm/add.c b/lib/libalpm/add.c
index f806e5b..f0af886 100644
--- a/lib/libalpm/add.c
+++ b/lib/libalpm/add.c
@@ -266,6 +266,7 @@ static int extract_single_file(alpm_handle_t *handle, struct archive *archive,
 					"filesystem: %o  package: %o\n", filename, lsbuf.st_mode & mask,
 					entrymode & mask);
 		}
+#ifndef __MSYS__
 
 #if 0
 		/* Disable this warning until our user management in packages has improved.
@@ -283,6 +284,7 @@ static int extract_single_file(alpm_handle_t *handle, struct archive *archive,
 		}
 #endif
 
+#endif
 		_alpm_log(handle, ALPM_LOG_DEBUG, "extract: skipping dir extraction of %s\n",
 				filename);
 		archive_read_data_skip(archive);
diff --git a/scripts/libmakepkg/lint_package/build_references.sh.in b/scripts/libmakepkg/lint_package/build_references.sh.in
index 9b7ffab..a5fc455 100644
--- a/scripts/libmakepkg/lint_package/build_references.sh.in
+++ b/scripts/libmakepkg/lint_package/build_references.sh.in
@@ -37,5 +37,13 @@ warn_build_references() {
 			printf '%s\n' "${refs[@]#"$pkgdir/"}" >&2
 		fi
 	done
+
+	# Check for Windows-style MSYS2 root path
+	if find "${pkgdir}" -type f -print0 | xargs -0 grep -iFqI "$(cygpath -m /)" ; then
+		warning "$(gettext "Package contains reference to %s")" "\$(cygpath -m /)"
+	fi
+	if find "${pkgdir}" -type f -print0 | xargs -0 grep -iFqI "$(cygpath -w /)" ; then
+		warning "$(gettext "Package contains reference to %s")" "\$(cygpath -w /)"
+	fi
 	return 0
 }
diff --git a/scripts/libmakepkg/tidy/staticlibs.sh.in b/scripts/libmakepkg/tidy/staticlibs.sh.in
index 498518c..e9d514a 100644
--- a/scripts/libmakepkg/tidy/staticlibs.sh.in
+++ b/scripts/libmakepkg/tidy/staticlibs.sh.in
@@ -35,9 +35,9 @@ tidy_staticlibs() {
 		msg2 "$(gettext "Removing static library files...")"
 		local l
 		while IFS= read -rd '' l; do
-			if [[ -f "${l%.a}.so" || -h "${l%.a}.so" ]]; then
+			if [[ -f "${l%.a}.dll.a" || -h "${l%.a}.dll.a" ]]; then
 				rm "$l"
 			fi
-		done < <(find . ! -type d -name "*.a" -print0)
+		done < <(find . ! -type d \( -name "*.a" ! -name "*.dll.a" \) -print0)
 	fi
 }
diff --git a/scripts/libmakepkg/tidy/strip.sh.in b/scripts/libmakepkg/tidy/strip.sh.in
index 9660253..c376a39 100644
--- a/scripts/libmakepkg/tidy/strip.sh.in
+++ b/scripts/libmakepkg/tidy/strip.sh.in
@@ -31,10 +31,6 @@ packaging_options+=('strip' 'debug')
 tidy_modify+=('tidy_strip')
 
 
-build_id() {
-	LANG=C readelf -n "$1" | sed -n '/Build ID/ { s/.*: //p; q; }'
-}
-
 source_files() {
 	LANG=C readelf "$1" --debug-dump 2>/dev/null | \
 		awk '/DW_AT_name +:/{name=$NF}/DW_AT_comp_dir +:/{{if (name == "<artificial>") next}{if (name !~ /^[<\/]/) {printf "%s/", $NF}}{print name}}'
@@ -43,58 +39,63 @@ source_files() {
 strip_file() {
 	local binary=$1; shift
 
-	if check_option "debug" "y"; then
-		local bid=$(build_id "$binary")
-
-		# has this file already been stripped
-		if [[ -n "$bid" ]]; then
-			if [[ -f "$dbgdir/.build-id/${bid:0:2}/${bid:2}.debug" ]]; then
+	case "$(file -bi "$binary")" in
+	*application/x-dosexec*)
+		if check_option "debug" "y"; then
+			if [[ -f "$dbgdir/$binary.debug" ]]; then
 				return
 			fi
-		elif [[ -f "$dbgdir/$binary.debug" ]]; then
-			return
-		fi
 
-		# copy source files to debug directory
-		local file dest t
-		while IFS= read -r t; do
-			file=${t/${dbgsrcdir}/"$srcdir"}
-			dest="${dbgsrc/"$dbgsrcdir"/}$t"
-			if ! [[ -f $dest ]]; then
-				mkdir -p "${dest%/*}"
-				cp -- "$file" "$dest"
-			fi
-		done < <(source_files "$binary")
+			# copy source files to debug directory
+			local file dest t
+			while IFS= read -r t; do
+				file=${t/${dbgsrcdir}/"$srcdir"}
+				dest="${dbgsrc/"$dbgsrcdir"/}$t"
+				if ! [[ -f $dest ]]; then
+					mkdir -p "${dest%/*}"
+					cp -- "$file" "$dest"
+				fi
+			done < <(source_files "$binary")
+
+			# copy debug symbols to debug directory
+			mkdir -p "$dbgdir/${binary%/*}"
+			msg2 "Separating debug info from $binary into $dbgdir/$binary.debug"
+			# create a dbg file with proper debug info:
+			objcopy --only-keep-debug "$binary" "$dbgdir/$binary.debug"
+
+			msg2 "Creating a debuginfo link to $dbgdir/$binary.debug in $binary"
+			local tempfile=$(mktemp "$binary.XXXXXX")
+			objcopy --add-gnu-debuglink="$dbgdir/${binary#/}.debug" "$binary" "$tempfile"
+			cat "$tempfile" > "$binary"
+			rm "$tempfile"
+
+			msg2 "Separating (again) debug info from $binary into $dbgdir/$binary.debug"
+			objcopy --only-keep-debug "$binary" "$dbgdir/$binary.debug"
+
+			msg2 "Removing old .gnu_debuglink section from $binary"
+			objcopy --remove-section=.gnu_debuglink "$binary"
+
+			# strip debug-info from the original file
+			objcopy --strip-debug "$binary"
+			msg2 "Creating (again) a debuginfo link to $dbgdir/$binary.debug in $binary"
+			tempfile=$(mktemp "$binary.XXXXXX")
+			objcopy --add-gnu-debuglink="$dbgdir/${binary#/}.debug" "$binary" "$tempfile"
+			cat "$tempfile" > "$binary"
+			rm "$tempfile"
+			# This way dbg file gets a .gnu_debuglink section (doesn't matter where
+			# it's pointing), and its contents pass the CRC32 check
+
+			# create any needed hardlinks
+			while IFS= read -rd '' file ; do
+				if [[ "${binary}" -ef "${file}" && ! -f "$dbgdir/${file}.debug" ]]; then
+					mkdir -p "$dbgdir/${file%/*}"
+					ln "$dbgdir/${binary}.debug" "$dbgdir/${file}.debug"
+				fi
+			done < <(find . -type f -perm -u+w -print0 2>/dev/null)
 
-		# copy debug symbols to debug directory
-		mkdir -p "$dbgdir/${binary%/*}"
-		objcopy --only-keep-debug "$binary" "$dbgdir/$binary.debug"
-		local tempfile=$(mktemp "$binary.XXXXXX")
-		objcopy --add-gnu-debuglink="$dbgdir/${binary#/}.debug" "$binary" "$tempfile"
-		cat "$tempfile" > "$binary"
-		rm "$tempfile"
-
-		# create any needed hardlinks
-		while IFS= read -rd '' file ; do
-			if [[ "${binary}" -ef "${file}" && ! -f "$dbgdir/${file}.debug" ]]; then
-				mkdir -p "$dbgdir/${file%/*}"
-				ln "$dbgdir/${binary}.debug" "$dbgdir/${file}.debug"
-			fi
-		done < <(find . -type f -perm -u+w -print0 2>/dev/null)
-
-		if [[ -n "$bid" ]]; then
-			local target
-			mkdir -p "$dbgdir/.build-id/${bid:0:2}"
-
-			target="../../../../../${binary#./}"
-			target="${target/..\/..\/usr\/lib\/}"
-			target="${target/..\/usr\/}"
-			ln -s "$target" "$dbgdir/.build-id/${bid:0:2}/${bid:2}"
-
-			target="../../${binary#./}.debug"
-			ln -s "$target" "$dbgdir/.build-id/${bid:0:2}/${bid:2}.debug"
 		fi
-	fi
+		;;
+	esac
 
 	local tempfile=$(mktemp "$binary.XXXXXX")
 	if strip "$@" "$binary" -o "$tempfile"; then
@@ -123,17 +124,86 @@ tidy_strip() {
 
 		if check_option "debug" "y"; then
 
-			dbgdir="$pkgdirbase/$pkgbase-@DEBUGSUFFIX@/usr/lib/debug"
+			dbgdir="$pkgdirbase/$pkgbase-@DEBUGSUFFIX@"
 			dbgsrcdir="${DBGSRCDIR:-/usr/src/debug}"
 			dbgsrc="$pkgdirbase/$pkgbase-@DEBUGSUFFIX@$dbgsrcdir"
 			mkdir -p "$dbgdir" "$dbgsrc"
 		fi
 
 		local binary strip_flags
-		find . -type f -perm -u+w -print0 2>/dev/null | while IFS= read -rd '' binary ; do
+		# *.so: Apache2 modules, OCaml stublibs, Ruby modules
+		# *.oct: Octave modules
+		# *.cmxs: OCaml natdynlink modules: http://gallium.inria.fr/~frisch/ndl.txt
+		find * -type f ! -name '*.dll.a' ! -name '*.lib' \
+			-a \( -name '*.a' -o -name '*.dll' -o -name '*.exe' -o -name '*.so' -o -name '*.so.*' -o -name '*.oct' -o -name '*.cmxs' \) -print0 \
+			-o -type f -executable ! -name '*.dll' ! -name '*.exe' ! -name '*.so' ! -name '*.so.[0-9]*' ! -name '*.oct' ! -name '*.cmxs' ! -name '*.a' ! -name '*.la' ! -name '*.lib' ! -name '*.exe.manifest' ! -name '*.exe.config' ! -name '*.dll.config' ! -name '*.mdb' ! -name '*-config' ! -name '*.csh' ! -name '*.sh' ! -name '*.pl' ! -name '*.pm' ! -name '*.py' ! -name '*.rb' ! -name '*.tcl' -print0 | \
+		while IFS= read -d $'\0' binary
+		do
 			local STRIPLTO=0
-			case "$(LC_ALL=C readelf -h "$binary" 2>/dev/null)" in
-				*Type:*'DYN (Shared object file)'*) # Libraries (.so) or Relocatable binaries
+			# Skip thin archives from stripping
+			case "${binary##*/}" in
+				*.a)
+					if [ "$(head -c 7 "${binary}")" = '!<thin>' ]
+					then
+						continue
+					fi
+				;;
+			esac
+
+			# assure this is actually a binary object
+			if [ "$(head -c 2 "${binary}")" = '#!' ]
+			then
+				# sometimes .exe will be appended where it does not belong
+				case "${exe}" in
+					usr/lib/hevea/*.exe) ;;
+					*.exe)	mv "${binary}" "${binary%.exe}" ;;
+				esac
+				continue
+			fi
+
+			# OCaml bytecode must not be stripped
+			# Magic number is at end of file:
+			# http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=256900#74
+			# http://cygwin.com/ml/cygwin-apps/2010-10/msg00057.html
+			#
+			# Perl Archive (PAR) binaries must not be stripped
+			# https://rt.cpan.org/Public/Bug/Display.html?id=18536
+			# http://cygwin.com/ml/cygwin-apps/2012-07/msg00088.html
+			case $(tail -c 12 "${binary}" | tr '\012\0' '%') in
+				%PAR\.pm%)  continue ;;
+				Caml1999X0[0-9][0-9])  continue ;;
+			esac
+
+			# Mono assemblies must not be stripped, but remove .mdb debug symbols,
+			# and make them non-executable so they're not launched by MS .NET
+			if LC_ALL=C file -b "${binary}" 2>&1 | grep -q "Mono/\.Net assembly"
+			then
+				chmod 0644 "${binary}"
+				rm -f "${binary}.mdb"
+				continue
+			fi
+
+			# check for .exe from non-automake Makefile which install(1) didn't fix
+			# strip(1) used to take care of this, but not anymore
+			case ${CHOST} in
+			*-*-cygwin*|*-*-mingw*|*-*-msys*)
+				case "${binary##*/}" in
+				*.dll|*.exe|*.sfx|*.so|*.so.[0-9]*|*.oct|*.cmxs) ;;
+				# make sure this isn't some oddly named DLL
+				*)	if LANG=en_US.UTF-8 LC_ALL=C objdump -f "${binary}" | grep -Eq '^start address 0x(0000000[01])?00401[0-9a-e][0-9a-e]0'
+					then
+						mv "${binary}" "${binary}.exe"
+						binary+=.exe
+					fi ;;
+				esac
+				;;
+			esac
+			chmod 0755 "${binary}";
+
+			case "$(@FILECMD@ -bi "$binary")" in
+				*application/x-dosexec*) # Windows executables and dlls
+					strip_flags="$STRIP_SHARED";;
+				*application/x-sharedlib*)  # Libraries (.so)
 					strip_flags="$STRIP_SHARED";;
 				*Type:*'DYN (Position-Independent Executable file)'*) # Relocatable binaries
 					strip_flags="$STRIP_SHARED";;
diff --git a/scripts/libmakepkg/utils_fixed_path.sh.in b/scripts/libmakepkg/utils_fixed_path.sh.in
new file mode 100644
index 0000000..e3a06bc
--- /dev/null
+++ b/scripts/libmakepkg/utils_fixed_path.sh.in
@@ -0,0 +1,34 @@
+if [[ -n "$MSYSTEM" ]]; then
+  readonly -a UTILS_NAME=('bsdtar'
+                          'bzip2'
+                          'bzr'
+                          'cat'
+                          'ccache'
+                          'distcc'
+                          'git'
+                          'gpg'
+                          'gzip'
+                          'hg'
+                          'lzip'
+                          'lzop'
+                          'openssl'
+                          'svn'
+                          'tput'
+                          'uncompress'
+                          'xargs'
+                          'xz'
+                          'zstd'
+                         )
+
+  for wrapper in ${UTILS_NAME[@]}; do
+    eval "
+    ${wrapper}"'() {
+      local UTILS_PATH="/usr/bin/"
+      if ! type -p ${UTILS_PATH}${FUNCNAME[0]} >/dev/null; then
+        error "$(gettext "Cannot find the %s binary required for makepkg.")" "${UTILS_PATH}${FUNCNAME[0]}"
+        exit 1
+      fi
+      ${UTILS_PATH}${FUNCNAME[0]} "$@"
+    }'
+  done
+fi
diff --git a/scripts/makepkg.sh.in b/scripts/makepkg.sh.in
index e58edfa..6c8446b 100644
--- a/scripts/makepkg.sh.in
+++ b/scripts/makepkg.sh.in
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
 #
 #   makepkg - make packages compatible for use with pacman
 #
@@ -26,7 +26,7 @@
 
 # makepkg uses quite a few external programs during its execution. You
 # need to have at least the following installed for makepkg to function:
-#   awk, bsdtar (libarchive), bzip2, coreutils, fakeroot, file, find (findutils),
+#   awk, bsdtar (libarchive), bzip2, coreutils, file, find (findutils),
 #   gettext, gpg, grep, gzip, sed, tput (ncurses), xz
 
 # gettext initialization
@@ -59,7 +59,6 @@ FORCE=0
 GENINTEG=0
 HOLDVER=0
 IGNOREARCH=0
-INFAKEROOT=0
 INSTALL=0
 LOGGING=0
 NEEDED=0
@@ -105,10 +104,9 @@ done
 trap_exit() {
 	local signal=$1; shift
 
-	if (( ! INFAKEROOT )); then
-		echo
-		error "$@"
-	fi
+	echo
+	error "$@"
+
 	[[ -n $srclinks ]] && rm -rf "$srclinks"
 
 	# unset the trap for this signal, and then call the default handler
@@ -123,11 +121,6 @@ trap_exit() {
 clean_up() {
 	local EXIT_CODE=$?
 
-	if (( INFAKEROOT )); then
-		# Don't clean up when leaving fakeroot, we're not done yet.
-		return 0
-	fi
-
 	if [[ -p $logpipe ]]; then
 		rm "$logpipe"
 	fi
@@ -137,7 +130,7 @@ clean_up() {
 
 		# If it's a clean exit and -c/--clean has been passed...
 		msg "$(gettext "Cleaning up...")"
-		rm -rf "$pkgdirbase" "$srcdir"
+		rm -rf "$pkgdirbase" "$srcdir" "$destdir"
 		if [[ -n $pkgbase ]]; then
 			local fullver=$(get_full_version)
 			# Can't do this unless the BUILDSCRIPT has been sourced.
@@ -179,11 +172,6 @@ clean_up() {
 	fi
 }
 
-enter_fakeroot() {
-	msg "$(gettext "Entering %s environment...")" "fakeroot"
-	fakeroot -- bash -$- "${BASH_SOURCE[0]}" -F "${ARGLIST[@]}" || exit $?
-}
-
 # Automatically update pkgver variable if a pkgver() function is provided
 # Re-sources the PKGBUILD afterwards to allow for other variables that use $pkgver
 update_pkgver() {
@@ -237,10 +225,6 @@ run_pacman() {
 			else
 				cmd=("${PACMAN_AUTH[@]}" "${cmd[@]}")
 			fi
-		elif type -p sudo >/dev/null; then
-			cmd=(sudo "${cmd[@]}")
-		else
-			cmd=(su root -c "$cmdescape")
 		fi
 		local lockfile="$(pacman-conf DBPath)/db.lck"
 		while [[ -f $lockfile ]]; do
@@ -440,7 +424,7 @@ run_function() {
 
 		$pkgfunc &>"$logpipe"
 
-		wait -f $teepid
+		wait $teepid
 		rm "$logpipe"
 	else
 		"$pkgfunc"
@@ -468,7 +452,7 @@ find_libdepends() {
 
 	sodepends=0
 	for d in "${depends[@]}"; do
-		if [[ $d = *.so ]]; then
+		if [[ $d = *.dll ]]; then
 			sodepends=1
 			break
 		fi
@@ -479,28 +463,33 @@ find_libdepends() {
 		return 0
 	fi
 
-	local libdeps filename soarch sofile soname soversion
+	local libdeps filename soarch sofile soname
 	declare -A libdeps
 
 	while IFS= read -rd '' filename; do
-		# get architecture of the file; if soarch is empty it's not an ELF binary
-		soarch=$(LC_ALL=C readelf -h "$filename" 2>/dev/null | sed -n 's/.*Class.*ELF\(32\|64\)/\1/p')
+		# get architecture of the file; if soarch is empty it's not an binary
+		soarch=$(LANG=en_US.UTF-8 LC_ALL=C objdump -a "$filename" | sed -n 's/.*file format.*pei-\(i386\|x86-64\)/\1/p')
 		[[ -n "$soarch" ]] || continue
+		case "$soarch" in
+			i386)
+				soarch=i686
+			;;
+			x86-64)
+				soarch=x86_64
+			;;
+		esac
 
 		# process all libraries needed by the binary
-		for sofile in $(LC_ALL=C readelf -d "$filename" 2>/dev/null | sed -nr 's/.*Shared library: \[(.*)\].*/\1/p')
+		for sofile in $(LC_ALL=C objdump -x "$filename" 2>/dev/null | sed -nr 's/.*DLL Name: (.*).*/\1/p')
 		do
-			# extract the library name: libfoo.so
-			soname="${sofile%.so?(+(.+([0-9])))}".so
-			# extract the major version: 1
-			soversion="${sofile##*\.so\.}"
+			soname=${sofile}
 
 			if [[ ${libdeps[$soname]} ]]; then
-				if [[ ${libdeps[$soname]} != *${soversion}-${soarch}* ]]; then
-					libdeps[$soname]+=" ${soversion}-${soarch}"
+				if [[ ${libdeps[$soname]} != *${soarch}* ]]; then
+					libdeps[$soname]+=" ${soarch}"
 				fi
 			else
-				libdeps[$soname]="${soversion}-${soarch}"
+				libdeps[$soname]="${soarch}"
 			fi
 		done
 	done < <(find "$pkgdir" -type f -perm -u+x -print0)
@@ -508,7 +497,7 @@ find_libdepends() {
 	local libdepends v
 	for d in "${depends[@]}"; do
 		case "$d" in
-			*.so)
+			*.dll)
 				if [[ ${libdeps[$d]} ]]; then
 					for v in ${libdeps[$d]}; do
 						libdepends+=("$d=$v")
@@ -534,30 +523,23 @@ find_libprovides() {
 		missing=0
 		versioned_provides=()
 		case "$p" in
-			*.so)
-				mapfile -t filename < <(find "$pkgdir" -type f -name $p\* | LC_ALL=C sort)
+			*.dll)
+				mapfile -t filename < <(find "$pkgdir" -type f -name $p)
 				if [[ $filename ]]; then
 					# packages may provide multiple versions of the same library
 					for fn in "${filename[@]}"; do
-						# check if we really have a shared object
-						if LC_ALL=C readelf -h "$fn" 2>/dev/null | grep -q '.*Type:.*DYN (Shared object file).*'; then
-							# get the string binaries link to (e.g. libfoo.so.1.2 -> libfoo.so.1)
-							local sofile=$(LC_ALL=C readelf -d "$fn" 2>/dev/null | sed -n 's/.*Library soname: \[\(.*\)\].*/\1/p')
-							if [[ -z "$sofile" ]]; then
-								warning "$(gettext "Library listed in %s is not versioned: %s")" "'provides'" "$p"
-								continue
-							fi
-
-							# get the library architecture (32 or 64 bit)
-							local soarch=$(LC_ALL=C readelf -h "$fn" | sed -n 's/.*Class.*ELF\(32\|64\)/\1/p')
-
-							# extract the library major version
-							local soversion="${sofile##*\.so\.}"
-
-							versioned_provides+=("${p}=${soversion}-${soarch}")
-						else
-							warning "$(gettext "Library listed in %s is not a shared object: %s")" "'provides'" "$p"
-						fi
+						# get the library architecture (32 or 64 bit)
+						local soarch=$(LC_ALL=C objdump -a "$fn" | sed -n 's/.*file format.*pei-\(i386\|x86-64\)/\1/p')
+						case "$soarch" in
+							i386)
+								soarch=i686
+							;;
+							x86-64)
+								soarch=x86_64
+							;;
+						esac
+
+						versioned_provides+=("${p}=${soarch}")
 					done
 				else
 					missing=1
@@ -597,7 +579,6 @@ write_pkginfo() {
 	merge_arch_attrs
 
 	printf "# Generated by makepkg %s\n" "$makepkg_version"
-	printf "# using %s\n" "$(fakeroot -v)"
 
 	write_kv_pair "pkgname" "$pkgname"
 	write_kv_pair "pkgbase" "$pkgbase"
@@ -750,7 +731,7 @@ create_debug_package() {
 	local pkgdir="$pkgdirbase/$pkgbase-@DEBUGSUFFIX@"
 
 	# check if we have any debug symbols to package
-	if dir_is_empty "$pkgdir/usr/lib/debug"; then
+	if dir_is_empty "$pkgdir"; then
 		return 0
 	fi
 
@@ -939,6 +920,11 @@ restore_package_variables() {
 
 run_single_packaging() {
 	local pkgdir="$pkgdirbase/$pkgname"
+		# clean existing pkg directory
+		if [[ -d "$pkgdir" ]]; then
+			msg "$(gettext "Removing existing %s directory...")" "\$pkgdir/"
+			rm -rf "$pkgdir"
+		fi
 	mkdir "$pkgdir"
 	if [[ -n $1 ]] || (( PKGFUNC )); then
 		run_package $1
@@ -1032,12 +1018,16 @@ if ! type -p gettext >/dev/null; then
 	gettext() {
 		printf "%s\n" "$@"
 	}
+else
+	gettext() {
+		/usr/bin/gettext "$@"
+	}
 fi
 
 ARGLIST=("$@")
 
 # Parse Command Line Options.
-OPT_SHORT="AcCdefFghiLmop:rRsSV"
+OPT_SHORT="AcCdefghiLmop:rRsSV"
 OPT_LONG=('allsource' 'check' 'clean' 'cleanbuild' 'config:' 'force' 'geninteg'
           'help' 'holdver' 'ignorearch' 'install' 'key:' 'log' 'noarchive' 'nobuild'
           'nocolor' 'nocheck' 'nodeps' 'noextract' 'noprepare' 'nosign' 'packagelist'
@@ -1071,7 +1061,6 @@ while true; do
 		-d|--nodeps)      NODEPS=1 ;;
 		-e|--noextract)   NOEXTRACT=1 ;;
 		-f|--force)       FORCE=1 ;;
-		-F)               INFAKEROOT=1 ;;
 		# generating integrity checks does not depend on architecture
 		-g|--geninteg)    BUILDPKG=0 GENINTEG=1 IGNOREARCH=1;;
 		--holdver)        HOLDVER=1 ;;
@@ -1186,19 +1175,6 @@ if (( LOGGING )) && ! ensure_writable_dir "LOGDEST" "$LOGDEST"; then
 	exit $E_FS_PERMISSIONS
 fi
 
-if (( ! INFAKEROOT )); then
-	if (( EUID == 0 )); then
-		error "$(gettext "Running %s as root is not allowed as it can cause permanent,\n\
-catastrophic damage to your system.")" "makepkg"
-		exit $E_ROOT
-	fi
-else
-	if [[ -z $FAKEROOTKEY ]]; then
-		error "$(gettext "Do not use the %s option. This option is only for internal use by %s.")" "'-F'" "makepkg"
-		exit $E_INVALID_OPTION
-	fi
-fi
-
 unset pkgname "${pkgbuild_schema_strings[@]}" "${pkgbuild_schema_arrays[@]}"
 unset "${known_hash_algos[@]/%/sums}"
 unset -f pkgver prepare build check package "${!package_@}"
@@ -1319,29 +1295,6 @@ if (( ! PKGVERFUNC )); then
 	check_build_status
 fi
 
-# Run the bare minimum in fakeroot
-if (( INFAKEROOT )); then
-	if (( SOURCEONLY )); then
-		create_srcpackage
-		msg "$(gettext "Leaving %s environment.")" "fakeroot"
-		exit $E_OK
-	fi
-
-	prepare_buildenv
-
-	chmod 755 "$pkgdirbase"
-	if (( ! SPLITPKG )); then
-		run_single_packaging
-	else
-		run_split_packaging
-	fi
-
-	create_debug_package
-
-	msg "$(gettext "Leaving %s environment.")" "fakeroot"
-	exit $E_OK
-fi
-
 msg "$(gettext "Making package: %s")" "$pkgbase $basever ($(date +%c))"
 
 # if we are creating a source-only package, go no further
@@ -1365,7 +1318,7 @@ if (( SOURCEONLY )); then
 	check_source_integrity all
 	cd_safe "$startdir"
 
-	enter_fakeroot
+	create_srcpackage
 
 	if [[ $SIGNPKG = 'y' ]]; then
 		msg "$(gettext "Signing package...")"
@@ -1415,6 +1368,9 @@ mkdir -p "$srcdir"
 chmod a-s "$srcdir"
 cd_safe "$srcdir"
 
+export MINGW_CHOST MINGW_PREFIX MINGW_PACKAGE_PREFIX
+export DXSDK_DIR ACLOCAL_PATH PKG_CONFIG_PATH
+
 if (( !REPKG )); then
 	if (( NOEXTRACT && ! VERIFYSOURCE )); then
 		warning "$(gettext "Using existing %s tree")" "\$srcdir/"
@@ -1467,15 +1423,23 @@ else
 		cd_safe "$startdir"
 	fi
 
-	enter_fakeroot
+	# if inhibiting archive creation, go no further
+	if (( NOARCHIVE )); then
+		msg "$(gettext "Package directory is ready.")"
+		exit $E_OK
+	fi
+	mkdir -p "$pkgdirbase"
+	chmod a-srwx "$pkgdirbase"
+	chmod 755 "$pkgdirbase"
+	if (( ! SPLITPKG )); then
+		run_single_packaging
+	else
+		run_split_packaging
+	fi
 
-	create_package_signatures || exit $E_PRETTY_BAD_PRIVACY
-fi
+	create_debug_package
 
-# if inhibiting archive creation, go no further
-if (( NOARCHIVE )); then
-	msg "$(gettext "Package directory is ready.")"
-	exit $E_OK
+	create_package_signatures || exit $E_PRETTY_BAD_PRIVACY
 fi
 
 msg "$(gettext "Finished making: %s")" "$pkgbase $basever ($(date +%c))"
diff --git a/scripts/pacman-db-upgrade.sh.in b/scripts/pacman-db-upgrade.sh.in
index 550d9f9..c1cb200 100644
--- a/scripts/pacman-db-upgrade.sh.in
+++ b/scripts/pacman-db-upgrade.sh.in
@@ -1,4 +1,4 @@
-#!/bin/bash -e
+#!/usr/bin/env bash
 #
 #   pacman-db-upgrade - upgrade the local pacman db to a newer format
 #
@@ -78,9 +78,13 @@ resolve_dir() {
 # PROGRAM START
 
 # determine whether we have gettext; make it a no-op if we do not
-if ! type gettext &>/dev/null; then
+if ! type -p gettext >/dev/null; then
 	gettext() {
-		echo "$@"
+		printf "%s\n" "$@"
+	}
+else
+	gettext() {
+		/usr/bin/gettext "$@"
 	}
 fi
 
@@ -137,7 +141,7 @@ lockfile="${dbroot}/db.lck"
 
 # make sure pacman isn't running
 if [[ -f $lockfile ]]; then
-	die "$(gettext "Pacman lock file was found. Cannot run while pacman is running.")"
+	die "$(/bin/gettext "Pacman lock file was found. Cannot run while pacman is running.")"
 fi
 # do not let pacman run while we do this
 touch "$lockfile"
diff --git a/scripts/pacman-key.sh.in b/scripts/pacman-key.sh.in
index f7f1dd6..591dcec 100644
--- a/scripts/pacman-key.sh.in
+++ b/scripts/pacman-key.sh.in
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
 #
 #   pacman-key - manages pacman's keyring
 #                Based on apt-key, from Debian
@@ -30,6 +30,7 @@ LIBRARY=${LIBRARY:-'@libmakepkgdir@'}
 # Import libmakepkg
 source "$LIBRARY"/util/message.sh
 source "$LIBRARY"/util/parseopts.sh
+source "$LIBRARY"/utils_fixed_path.sh
 
 # Options
 ADD=0
@@ -265,7 +266,7 @@ check_keyring() {
 		exit 1
 	fi
 
-	if (( (EXPORT || FINGER || LIST || VERIFY) && EUID != 0 )); then
+	if (( EXPORT || FINGER || LIST || VERIFY )); then
 		if ! grep -q "^[[:space:]]*lock-never[[:space:]]*$" ${PACMAN_KEYRING_DIR}/gpg.conf &>/dev/null; then
 			error "$(gettext "You do not have sufficient permissions to run this command.")"
 			msg "$(gettext "Use '%s' to correct the keyring permissions.")" "pacman-key --init"
@@ -433,7 +434,7 @@ import_trustdb() {
 	local ret=0
 	for importdir in "$@"; do
 		if [[ -f "${importdir}/trustdb.gpg" ]]; then
-			gpg --homedir "${importdir}" --export-ownertrust | \
+			/bin/gpg --homedir "${importdir}" --export-ownertrust | \
 				"${GPG_PACMAN[@]}" --import-ownertrust -
 			if (( PIPESTATUS )); then
 				error "$(gettext "%s could not be imported.")" "${importdir}/trustdb.gpg"
@@ -605,10 +606,14 @@ updatedb() {
 	fi
 }
 
-# PROGRAM START
-if ! type gettext &>/dev/null; then
+# determine whether we have gettext; make it a no-op if we do not
+if ! type -p gettext >/dev/null; then
 	gettext() {
-		echo "$@"
+		printf "%s\n" "$@"
+	}
+else
+	gettext() {
+		/usr/bin/gettext "$@"
 	}
 fi
 
@@ -672,11 +677,6 @@ if ! type -p gpg >/dev/null; then
 	exit 1
 fi
 
-if (( (ADD || DELETE || EDITKEY || IMPORT || IMPORT_TRUSTDB || INIT || LSIGNKEY || POPULATE || RECEIVE || REFRESH || UPDATEDB) && EUID != 0 )); then
-	error "$(gettext "%s needs to be run as root for this operation.")" "pacman-key"
-	exit 1
-fi
-
 CONFIG=${CONFIG:-@sysconfdir@/pacman.conf}
 if [[ ! -r "${CONFIG}" ]]; then
 	error "$(gettext "%s configuration file '%s' not found.")" "pacman" "$CONFIG"
diff --git a/scripts/repo-add.sh.in b/scripts/repo-add.sh.in
index d393839..a231699 100644
--- a/scripts/repo-add.sh.in
+++ b/scripts/repo-add.sh.in
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
 #
 #   repo-add - add a package to a given repo database file
 #   repo-remove - remove a package entry from a given repo database file
@@ -46,6 +46,7 @@ PREVENT_DOWNGRADE=0
 # Import libmakepkg
 source "$LIBRARY"/util/compress.sh
 source "$LIBRARY"/util/message.sh
+source "$LIBRARY"/utils_fixed_path.sh
 
 # ensure we have a sane umask set
 umask 0022
@@ -562,9 +563,13 @@ clean_up() {
 # PROGRAM START
 
 # determine whether we have gettext; make it a no-op if we do not
-if ! type gettext &>/dev/null; then
+if ! type -p gettext &>/dev/null; then
 	gettext() {
-		echo "$@"
+		printf "%s\n" "$@"
+	}
+else
+	gettext() {
+		/usr/bin/gettext "$@"
 	}
 fi
 
diff --git a/scripts/wrapper.sh.in b/scripts/wrapper.sh.in
index 1b28b84..504db36 100644
--- a/scripts/wrapper.sh.in
+++ b/scripts/wrapper.sh.in
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
 #
 #   @PROGNAME@ - a wrapper for running the real @PROGNAME@ in the source tree
 #
diff --git a/src/pacman/callback.c b/src/pacman/callback.c
index 75c74f8..2f07512 100644
--- a/src/pacman/callback.c
+++ b/src/pacman/callback.c
@@ -153,8 +153,11 @@ static int64_t get_update_timediff(int first_call)
 static void fill_progress(const int bar_percent, const int disp_percent,
 		const int proglen)
 {
-	/* 8 = 1 space + 1 [ + 1 ] + 5 for percent */
-	const int hashlen = proglen > 8 ? proglen - 8 : 0;
+	/* 9 = 1 space + 1 [ + 1 ] + 5 for percent + 1 blank */
+	/* Without the single blank at the end, carriage return wouldn't
+	 * work properly on most windows terminals.
+	 */
+	const int hashlen = proglen > 9 ? proglen - 9 : 0;
 	const int hash = bar_percent * hashlen / 100;
 	static int lasthash = 0, mouth = 0;
 	int i;
diff --git a/src/pacman/check.c b/src/pacman/check.c
index 091055f..188f515 100644
--- a/src/pacman/check.c
+++ b/src/pacman/check.c
@@ -75,6 +75,7 @@ static int check_file_permissions(const char *pkgname, const char *filepath,
 	int errors = 0;
 	mode_t fsmode;
 
+#ifndef __MSYS__
 	/* uid */
 	if(st->st_uid != archive_entry_uid(entry)) {
 		errors++;
@@ -92,6 +93,7 @@ static int check_file_permissions(const char *pkgname, const char *filepath,
 					pkgname, filepath);
 		}
 	}
+#endif
 
 	/* mode */
 	fsmode = st->st_mode & (S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO);
diff --git a/src/pacman/pacman.c b/src/pacman/pacman.c
index e398855..36c3b5e 100644
--- a/src/pacman/pacman.c
+++ b/src/pacman/pacman.c
@@ -1086,7 +1086,9 @@ static void cl_to_log(int argc, char *argv[])
 int main(int argc, char *argv[])
 {
 	int ret = 0;
+#ifndef __MSYS__
 	uid_t myuid = getuid();
+#endif
 
 	console_cursor_hide();
 	install_segv_handler();
@@ -1130,11 +1132,13 @@ int main(int argc, char *argv[])
 		cleanup(ret);
 	}
 
+#ifndef __MSYS__
 	/* check if we have sufficient permission for the requested operation */
 	if(myuid > 0 && needs_root()) {
 		pm_printf(ALPM_LOG_ERROR, _("you cannot perform this operation unless you are root.\n"));
 		cleanup(EXIT_FAILURE);
 	}
+#endif
 
 	/* we support reading targets from stdin if a cmdline parameter is '-' */
 	if(alpm_list_find_str(pm_targets, "-")) {
diff --git a/test/pacman/pmtest.py b/test/pacman/pmtest.py
index 94b0930..f008f22 100644
--- a/test/pacman/pmtest.py
+++ b/test/pacman/pmtest.py
@@ -239,19 +239,6 @@ class pmtest(object):
         vprint("\tpacman %s" % self.args)
 
         cmd = []
-        if os.geteuid() != 0:
-            fakeroot = util.which("fakeroot")
-            if not fakeroot:
-                tap.diag("WARNING: fakeroot not found!")
-            else:
-                cmd.append("fakeroot")
-
-            fakechroot = util.which("fakechroot")
-            if not fakechroot:
-                tap.diag("WARNING: fakechroot not found!")
-            else:
-                cmd.append("fakechroot")
-
         if pacman["gdb"]:
             cmd.extend(["libtool", "execute", "gdb", "--args"])
         if pacman["valgrind"]:
@@ -294,8 +281,10 @@ class pmtest(object):
         # Change to the tmp dir before running pacman, so that local package
         # archives are made available more easily.
         time_start = time.time()
-        self.retcode = subprocess.call(cmd, stdout=output, stderr=output,
-                cwd=os.path.join(self.root, util.TMPDIR), env={'LC_ALL': 'C'})
+        self.retcode = subprocess.call(cmd,
+                cwd=os.path.join(self.root, util.TMPDIR),
+                env={'LC_ALL': 'C', 'PATH': os.environ['PATH']},
+                stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
         time_end = time.time()
         vprint("\ttime elapsed: %.2fs" % (time_end - time_start))
 
-- 
2.33.0

