#!/bin/bash
function setup() {
shopt -s nocasematch
export MSYS2_ARG_CONV_EXCL="*"
export WSLENV=PATH/l
while getopts "e:p:r:t:c:qmi" opt; do
case "$opt" in
e) PATHTOOL="$OPTARG" ;;
p) DRIVEPREFIX="$OPTARG" ;;
r) ENVROOT="$OPTARG" ;;
t) WINTEMP="$OPTARG" ;;
c) CMD="$OPTARG" ;;
q) QUIET=true ;;
m) MIXEDMODE=true ;;
i) IGNOREFAILURES=true ;;
?)
exit 2
;;
esac
done
shift $((OPTIND-1))
ACTION="$1"
if [[ -z ${PATHTOOL+x} ]]; then
PATHTOOL="$(type -p cygpath)"
if [[ $PATHTOOL == "" ]]; then
PATHTOOL="$(type -p wslpath)"
if [[ $PATHTOOL == "" ]]; then
if [[ $QUIET != true ]]; then
echo fixpath: failure: Cannot locate cygpath or wslpath >&2
fi
exit 2
fi
fi
fi
if [[ -z ${DRIVEPREFIX+x} ]]; then
winroot="$($PATHTOOL -u c:/)"
DRIVEPREFIX="${winroot%/c/}"
else
if [[ $DRIVEPREFIX == "NONE" ]]; then
DRIVEPREFIX=""
fi
fi
if [[ -z ${ENVROOT+x} ]]; then
unixroot="$($PATHTOOL -w / 2> /dev/null)"
ENVROOT="${unixroot%\\}"
elif [[ "$ENVROOT" == "[unavailable]" ]]; then
ENVROOT=""
fi
if [[ -z ${CMD+x} ]]; then
CMD="$DRIVEPREFIX/c/windows/system32/cmd.exe"
fi
if [[ -z ${WINTEMP+x} ]]; then
wintemp_win="$($CMD /q /c echo %TEMP% 2>/dev/null | tr -d \\n\\r)"
WINTEMP="$($PATHTOOL -u "$wintemp_win")"
fi
}
TEMPDIRS=""
trap "cleanup" EXIT
function cleanup() {
if [[ "$TEMPDIRS" != "" ]]; then
rm -rf $TEMPDIRS
fi
}
function import_path() {
path="$1"
path="${path#"${path%%[![:space:]]*}"}"
path="${path%"${path##*[![:space:]]}"}"
if [[ $path =~ ^.:[/\\].*$ ]] || [[ "$path" =~ ^"$ENVROOT"\\.*$ ]] ; then
path="$($PATHTOOL -u "$path")"
else
dirpart="$(dirname "$path")"
dirpart="$(cd "$dirpart" 2>&1 > /dev/null && pwd)"
if [[ $? -ne 0 ]]; then
if [[ $QUIET != true ]]; then
echo fixpath: failure: Directory containing path "'"$path"'" does not exist >&2
fi
if [[ $IGNOREFAILURES != true ]]; then
exit 1
else
path=""
fi
else
basepart="$(basename "$path")"
if [[ $dirpart == / ]]; then
dirpart=""
fi
if [[ $basepart == / ]]; then
basepart=""
fi
path="$dirpart/$basepart"
fi
fi
if [[ "$path" != "" ]]; then
unixpath="$path"
if [[ ! -e "$unixpath" ]]; then
unixpath="$unixpath.exe"
fi
winpath="$($PATHTOOL -w "$unixpath" 2>/dev/null)"
if [[ $? -eq 0 && -e "$unixpath" ]]; then
if [[ ! "$winpath" =~ ^"$ENVROOT"\\.*$ ]] ; then
if [[ ! $winpath =~ ^[-_.:\\a-zA-Z0-9]*$ ]] ; then
shortpath="$($CMD /q /c for %I in \( "$winpath" \) do echo %~sI 2>/dev/null | tr -d \\n\\r)"
unixpath="$($PATHTOOL -u "$shortpath")"
fi
path="$(echo "$unixpath" | tr '[:upper:]' '[:lower:]')"
fi
else
if [[ ! -e $path ]]; then
if [[ -e $path.exe ]]; then
path="$path.exe"
else
if [[ $QUIET != true ]]; then
echo fixpath: warning: Path "'"$path"'" does not exist >&2
fi
fi
fi
fi
fi
if [[ "$path" =~ " " ]]; then
if [[ $QUIET != true ]]; then
echo fixpath: failure: Path "'"$path"'" contains space >&2
fi
if [[ $IGNOREFAILURES != true ]]; then
exit 1
else
path=""
fi
fi
result="$path"
}
function import_command_line() {
imported=""
old_ifs="$IFS"
IFS=";"
for arg in $1; do
if ! [[ $arg =~ ^" "+$ ]]; then
import_path "$arg"
if [[ "$result" != "" && "$imported" = "" ]]; then
imported="$result"
else
imported="$imported:$result"
fi
fi
done
IFS="$old_ifs"
result="$imported"
}
function convert_pathlist() {
converted_list=""
pathlist_args="$1"
IFS=':' read -r -a arg_array <<< "$pathlist_args"
for arg in "${arg_array[@]}"; do
winpath=""
if [[ $arg =~ ^($DRIVEPREFIX/)([a-z])(/[^/]+.*$) ]] ; then
winpath="${BASH_REMATCH[2]}:${BASH_REMATCH[3]}"
if [[ $MIXEDMODE != true ]]; then
winpath="${winpath//'/'/'\'}"
else
winpath="${winpath//'\'/'/'}"
fi
elif [[ $arg =~ ^(/[-_.*a-zA-Z0-9]+(/[-_.*a-zA-Z0-9]+)+.*$) ]] ; then
pathmatch="${BASH_REMATCH[1]}"
if [[ $ENVROOT == "" ]]; then
if [[ $QUIET != true ]]; then
echo fixpath: failure: Path "'"$pathmatch"'" cannot be converted to Windows path >&2
fi
exit 1
fi
winpath="$ENVROOT$pathmatch"
if [[ $MIXEDMODE != true ]]; then
winpath="${winpath//'/'/'\'}"
else
winpath="${winpath//'\'/'/'}"
fi
else
result=""
return 1
fi
if [[ "$converted_list" = "" ]]; then
converted_list="$winpath"
else
converted_list="$converted_list;$winpath"
fi
done
result="$converted_list"
return 0
}
function convert_path() {
if [[ $1 =~ : ]]; then
convert_pathlist "$1"
if [[ $? -eq 0 ]]; then
return 0
fi
fi
arg="$1"
winpath=""
if [[ $arg =~ ^([^/]*|-[^:=]*[:=]|.*file://|/[a-zA-Z:]{1,3}:?)($DRIVEPREFIX/)([a-z])(/[^/]+.*$) ]] ; then
prefix="${BASH_REMATCH[1]}"
winpath="${BASH_REMATCH[3]}:${BASH_REMATCH[4]}"
if [[ ${#prefix} -eq 2 && "${prefix:0:1}" == "/" ]]; then
possiblepath="${BASH_REMATCH[1]}/${BASH_REMATCH[3]}${BASH_REMATCH[4]}"
if [[ -e "$possiblepath" || -e "$(dirname $possiblepath)" || -e "$(echo $possiblepath | cut -d / -f 1-5)" ]] ; then
prefix=
drivepart="${possiblepath:1:1}"
pathpart="${possiblepath:2}"
winpath="$drivepart:$pathpart"
fi
fi
if [[ $MIXEDMODE != true ]]; then
winpath="${winpath//'/'/'\'}"
else
winpath="${winpath//'\'/'/'}"
fi
elif [[ $arg =~ ^([^/]*|-[^:=]*[:=]|(.*file://))(/([-_.+a-zA-Z0-9]+)(/[-_.+a-zA-Z0-9]+)+)(.*)?$ ]] ; then
prefix="${BASH_REMATCH[1]}"
pathmatch="${BASH_REMATCH[3]}"
firstdir="${BASH_REMATCH[4]}"
suffix="${BASH_REMATCH[6]}"
if [[ -d "/$firstdir" ]]; then
if [[ $ENVROOT == "" ]]; then
if [[ $QUIET != true ]]; then
echo fixpath: failure: Path "'"$pathmatch"'" cannot be converted to Windows path >&2
fi
exit 1
fi
winpath="$ENVROOT$pathmatch"
if [[ $MIXEDMODE != true ]]; then
winpath="${winpath//'/'/'\'}"
else
winpath="${winpath//'\'/'/'}"
fi
winpath="$winpath$suffix"
fi
fi
if [[ $winpath != "" ]]; then
result="$prefix$winpath"
else
result="$arg"
fi
}
function convert_file() {
infile="$1"
outfile="$2"
if [[ -e $outfile ]] ; then
rm $outfile
fi
while read line; do
convert_path "$line"
echo "$result" >> $outfile
done < $infile
}
function convert_at_file() {
infile="$1"
if [[ -e $infile ]] ; then
tempdir=$(mktemp -dt fixpath.XXXXXX -p "$WINTEMP")
TEMPDIRS="$TEMPDIRS $tempdir"
while read line; do
convert_path "$line"
echo "$result" >> $tempdir/atfile
done < $infile
convert_path "$tempdir/atfile"
result="@$result"
else
result="@$infile"
fi
}
function print_command_line() {
converted_args=""
for arg in "$@" ; do
if [[ $arg =~ ^@(.*$) ]] ; then
convert_at_file "${BASH_REMATCH[1]}"
else
convert_path "$arg"
fi
converted_args="$converted_args$result "
done
result="${converted_args% }"
}
function verify_current_dir() {
arg="$PWD"
if [[ $arg =~ ^($DRIVEPREFIX/)([a-z])(/[^/]+.*$) ]] ; then
return 0
elif [[ $arg =~ ^(/[^/]+.*$) ]] ; then
if [[ $ENVROOT == "" || $ENVROOT =~ ^\\\\.* ]]; then
return 1
fi
return 0
fi
return 1
}
function exec_command_line() {
verify_current_dir
if [[ $? -ne 0 ]]; then
cd "$WINTEMP"
if [[ $QUIET != true ]]; then
echo fixpath: warning: Changing directory to $WINTEMP >&2
fi
fi
collected_args=()
command=""
for arg in "$@" ; do
if [[ $command == "" ]]; then
if [[ $arg =~ ^(.*)=(.*)$ ]]; then
key="${BASH_REMATCH[1]}"
arg="${BASH_REMATCH[2]}"
convert_path "$arg"
export $key="$result"
export WSLENV=$WSLENV:$key/w
else
command="$arg"
fi
else
if [[ $arg =~ ^@(.*$) ]] ; then
convert_at_file "${BASH_REMATCH[1]}"
else
convert_path "$arg"
fi
collected_args=("${collected_args[@]}" "$result")
fi
done
if [[ -v DEBUG_FIXPATH ]]; then
echo fixpath: debug: input: "$@" >&2
echo fixpath: debug: output: "$command" "${collected_args[@]}" >&2
fi
if [[ ! -e "$command" ]]; then
if [[ -e "$command.exe" ]]; then
command="$command.exe"
fi
fi
if [[ $ENVROOT != "" || ! -x /bin/grep ]]; then
"$command" "${collected_args[@]}"
else
"$command" "${collected_args[@]}" 2> >(/bin/grep -v "ERROR: UtilTranslatePathList" 1>&2)
fi
}
function verify_command_line() {
arg="$1"
if [[ $arg =~ ^($DRIVEPREFIX/)([a-z])(/[^/]+.*$) ]] ; then
return 0
elif [[ $arg =~ ^(/[^/]+/[^/]+.*$) ]] ; then
if [[ $ENVROOT != "" ]]; then
return 0
fi
fi
return 1
}
setup "$@"
shift $((OPTIND))
if [[ "$ACTION" == "import" ]] ; then
import_command_line "$@"
echo "$result"
elif [[ "$ACTION" == "print" ]] ; then
print_command_line "$@"
echo "$result"
elif [[ "$ACTION" == "convert" ]] ; then
convert_file "$@"
elif [[ "$ACTION" == "exec" ]] ; then
exec_command_line "$@"
exit $?
elif [[ "$ACTION" == "verify" ]] ; then
verify_command_line "$@"
exit $?
else
if [[ $QUIET != true ]]; then
echo Unknown operation: "$ACTION" >&2
echo Supported operations: import print exec verify >&2
fi
exit 2
fi