113498266Sopenharmony_ci###########################################################################
213498266Sopenharmony_ci#                                  _   _ ____  _
313498266Sopenharmony_ci#  Project                     ___| | | |  _ \| |
413498266Sopenharmony_ci#                             / __| | | | |_) | |
513498266Sopenharmony_ci#                            | (__| |_| |  _ <| |___
613498266Sopenharmony_ci#                             \___|\___/|_| \_\_____|
713498266Sopenharmony_ci#
813498266Sopenharmony_ci# Copyright (C) Evgeny Grin (Karlson2k), <k2k@narod.ru>.
913498266Sopenharmony_ci#
1013498266Sopenharmony_ci# This software is licensed as described in the file COPYING, which
1113498266Sopenharmony_ci# you should have received as part of this distribution. The terms
1213498266Sopenharmony_ci# are also available at https://curl.se/docs/copyright.html.
1313498266Sopenharmony_ci#
1413498266Sopenharmony_ci# You may opt to use, copy, modify, merge, publish, distribute and/or sell
1513498266Sopenharmony_ci# copies of the Software, and permit persons to whom the Software is
1613498266Sopenharmony_ci# furnished to do so, under the terms of the COPYING file.
1713498266Sopenharmony_ci#
1813498266Sopenharmony_ci# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
1913498266Sopenharmony_ci# KIND, either express or implied.
2013498266Sopenharmony_ci#
2113498266Sopenharmony_ci# SPDX-License-Identifier: curl
2213498266Sopenharmony_ci#
2313498266Sopenharmony_ci###########################################################################
2413498266Sopenharmony_ci
2513498266Sopenharmony_ci# This Perl package helps with path transforming when running curl tests on
2613498266Sopenharmony_ci# Win32 platform with Msys or Cygwin.
2713498266Sopenharmony_ci# Three main functions 'sys_native_abs_path', 'sys_native_path' and
2813498266Sopenharmony_ci# 'build_sys_abs_path' autodetect format of given pathnames. Following formats
2913498266Sopenharmony_ci# are supported:
3013498266Sopenharmony_ci#  (1) /some/path   - absolute path in Unix-style
3113498266Sopenharmony_ci#  (2) D:/some/path - absolute path in Win32-style
3213498266Sopenharmony_ci#  (3) some/path    - relative path
3313498266Sopenharmony_ci#  (4) D:some/path  - path relative to current directory on Win32 drive (paths
3413498266Sopenharmony_ci#                     like 'D:' are treated as 'D:./') (*)
3513498266Sopenharmony_ci#  (5) \some/path   - path from root directory on current Win32 drive (*)
3613498266Sopenharmony_ci# All forward '/' and back '\' slashes are treated identically except leading
3713498266Sopenharmony_ci# slash in forms (1) and (5).
3813498266Sopenharmony_ci# Forward slashes are simpler processed in Perl, do not require extra escaping
3913498266Sopenharmony_ci# for shell (unlike back slashes) and accepted by Win32 native programs, so
4013498266Sopenharmony_ci# all functions return paths with only forward slashes except
4113498266Sopenharmony_ci# 'sys_native_path' which returns paths with first forward slash for form (5).
4213498266Sopenharmony_ci# All returned paths don't contain any duplicated slashes, only single slashes
4313498266Sopenharmony_ci# are used as directory separators on output.
4413498266Sopenharmony_ci# On non-Windows platforms functions acts as transparent wrappers for similar
4513498266Sopenharmony_ci# Perl's functions or return unmodified string (depending on functionality),
4613498266Sopenharmony_ci# so all functions can be unconditionally used on all platforms.
4713498266Sopenharmony_ci#
4813498266Sopenharmony_ci# (*) CAUTION! Forms (4) and (5) are not recommended to use as they can be
4913498266Sopenharmony_ci#     interpreted incorrectly in Perl and Msys/Cygwin environment have low
5013498266Sopenharmony_ci#     control on Win32 current drive and Win32 current path on specific drive.
5113498266Sopenharmony_ci
5213498266Sopenharmony_cipackage pathhelp;
5313498266Sopenharmony_ci
5413498266Sopenharmony_ciuse strict;
5513498266Sopenharmony_ciuse warnings;
5613498266Sopenharmony_ciuse Cwd 'abs_path';
5713498266Sopenharmony_ci
5813498266Sopenharmony_ciBEGIN {
5913498266Sopenharmony_ci    use base qw(Exporter);
6013498266Sopenharmony_ci
6113498266Sopenharmony_ci    our @EXPORT_OK = qw(
6213498266Sopenharmony_ci        os_is_win
6313498266Sopenharmony_ci        exe_ext
6413498266Sopenharmony_ci        sys_native_abs_path
6513498266Sopenharmony_ci        sys_native_current_path
6613498266Sopenharmony_ci        build_sys_abs_path
6713498266Sopenharmony_ci        normalize_path
6813498266Sopenharmony_ci        should_use_cygpath
6913498266Sopenharmony_ci        drives_mounted_on_cygdrive
7013498266Sopenharmony_ci    );
7113498266Sopenharmony_ci}
7213498266Sopenharmony_ci
7313498266Sopenharmony_ci
7413498266Sopenharmony_ci#######################################################################
7513498266Sopenharmony_ci# Block for cached static variables
7613498266Sopenharmony_ci#
7713498266Sopenharmony_ci{
7813498266Sopenharmony_ci    # Cached static variable, Perl 5.0-compatible.
7913498266Sopenharmony_ci    my $is_win = $^O eq 'MSWin32'
8013498266Sopenharmony_ci              || $^O eq 'cygwin'
8113498266Sopenharmony_ci              || $^O eq 'msys';
8213498266Sopenharmony_ci
8313498266Sopenharmony_ci    # Returns boolean true if OS is any form of Windows.
8413498266Sopenharmony_ci    sub os_is_win {
8513498266Sopenharmony_ci        return $is_win;
8613498266Sopenharmony_ci    }
8713498266Sopenharmony_ci
8813498266Sopenharmony_ci    # Cached static variable, Perl 5.0-compatible.
8913498266Sopenharmony_ci    my $cygdrive_present;
9013498266Sopenharmony_ci
9113498266Sopenharmony_ci    # Returns boolean true if Win32 drives mounted with '/cygdrive/' prefix.
9213498266Sopenharmony_ci    sub drives_mounted_on_cygdrive {
9313498266Sopenharmony_ci        return $cygdrive_present if defined $cygdrive_present;
9413498266Sopenharmony_ci        $cygdrive_present = ((-e '/cygdrive/') && (-d '/cygdrive/')) ? 1 : 0;
9513498266Sopenharmony_ci        return $cygdrive_present;
9613498266Sopenharmony_ci    }
9713498266Sopenharmony_ci}
9813498266Sopenharmony_ci
9913498266Sopenharmony_cimy $use_cygpath;     # Only for Win32:
10013498266Sopenharmony_ci                     #  undef - autodetect
10113498266Sopenharmony_ci                     #      0 - do not use cygpath
10213498266Sopenharmony_ci                     #      1 - use cygpath
10313498266Sopenharmony_ci
10413498266Sopenharmony_ci# Returns boolean true if 'cygpath' utility should be used for path conversion.
10513498266Sopenharmony_cisub should_use_cygpath {
10613498266Sopenharmony_ci    return $use_cygpath if defined $use_cygpath;
10713498266Sopenharmony_ci    if(os_is_win()) {
10813498266Sopenharmony_ci        $use_cygpath = (qx{cygpath -u '.\\' 2>/dev/null} eq "./\n" && $? == 0);
10913498266Sopenharmony_ci    } else {
11013498266Sopenharmony_ci        $use_cygpath = 0;
11113498266Sopenharmony_ci    }
11213498266Sopenharmony_ci    return $use_cygpath;
11313498266Sopenharmony_ci}
11413498266Sopenharmony_ci
11513498266Sopenharmony_ci#######################################################################
11613498266Sopenharmony_ci# Performs path "normalization": all slashes converted to forward
11713498266Sopenharmony_ci# slashes (except leading slash), all duplicated slashes are replaced
11813498266Sopenharmony_ci# with single slashes, all relative directories ('./' and '../') are
11913498266Sopenharmony_ci# resolved if possible.
12013498266Sopenharmony_ci# Path processed as string, directories are not checked for presence so
12113498266Sopenharmony_ci# path for not yet existing directory can be "normalized".
12213498266Sopenharmony_ci#
12313498266Sopenharmony_cisub normalize_path;
12413498266Sopenharmony_ci
12513498266Sopenharmony_ci#######################################################################
12613498266Sopenharmony_ci# Returns current working directory in Win32 format on Windows.
12713498266Sopenharmony_ci#
12813498266Sopenharmony_cisub sys_native_current_path {
12913498266Sopenharmony_ci    return Cwd::getcwd() if !os_is_win();
13013498266Sopenharmony_ci
13113498266Sopenharmony_ci    my $cur_dir;
13213498266Sopenharmony_ci    if($^O eq 'msys') {
13313498266Sopenharmony_ci        # MSys shell has built-in command.
13413498266Sopenharmony_ci        chomp($cur_dir = `bash -c 'pwd -W'`);
13513498266Sopenharmony_ci        if($? != 0) {
13613498266Sopenharmony_ci            warn "Can't determine Win32 current directory.\n";
13713498266Sopenharmony_ci            return undef;
13813498266Sopenharmony_ci        }
13913498266Sopenharmony_ci        # Add final slash if required.
14013498266Sopenharmony_ci        $cur_dir .= '/' if length($cur_dir) > 3;
14113498266Sopenharmony_ci    }
14213498266Sopenharmony_ci    else {
14313498266Sopenharmony_ci        # Do not use 'cygpath' - it falsely succeed on paths like '/cygdrive'.
14413498266Sopenharmony_ci        $cur_dir = `cmd "/c;" echo %__CD__%`;
14513498266Sopenharmony_ci        if($? != 0 || substr($cur_dir, 0, 1) eq '%') {
14613498266Sopenharmony_ci            warn "Can't determine Win32 current directory.\n";
14713498266Sopenharmony_ci            return undef;
14813498266Sopenharmony_ci        }
14913498266Sopenharmony_ci        # Remove both '\r' and '\n'.
15013498266Sopenharmony_ci        $cur_dir =~ s{\n|\r}{}g;
15113498266Sopenharmony_ci
15213498266Sopenharmony_ci        # Replace back slashes with forward slashes.
15313498266Sopenharmony_ci        $cur_dir =~ s{\\}{/}g;
15413498266Sopenharmony_ci    }
15513498266Sopenharmony_ci    return $cur_dir;
15613498266Sopenharmony_ci}
15713498266Sopenharmony_ci
15813498266Sopenharmony_ci#######################################################################
15913498266Sopenharmony_ci# Returns Win32 current drive letter with colon.
16013498266Sopenharmony_ci#
16113498266Sopenharmony_cisub get_win32_current_drive {
16213498266Sopenharmony_ci    # Notice parameter "/c;" - it's required to turn off Msys's
16313498266Sopenharmony_ci    # transformation of '/c' and compatible with Cygwin.
16413498266Sopenharmony_ci    my $drive_letter = `cmd "/c;" echo %__CD__:~0,2%`;
16513498266Sopenharmony_ci    if($? != 0 || substr($drive_letter, 1, 1) ne ':') {
16613498266Sopenharmony_ci        warn "Can't determine current Win32 drive letter.\n";
16713498266Sopenharmony_ci        return undef;
16813498266Sopenharmony_ci    }
16913498266Sopenharmony_ci
17013498266Sopenharmony_ci    return substr($drive_letter, 0, 2);
17113498266Sopenharmony_ci}
17213498266Sopenharmony_ci
17313498266Sopenharmony_ci# Internal function. Converts path by using Msys's built-in transformation.
17413498266Sopenharmony_ci# Returned path may contain duplicated and back slashes.
17513498266Sopenharmony_cisub do_msys_transform;
17613498266Sopenharmony_ci
17713498266Sopenharmony_ci# Internal function. Gets two parameters: first parameter must be single
17813498266Sopenharmony_ci# drive letter ('c'), second optional parameter is path relative to drive's
17913498266Sopenharmony_ci# current working directory. Returns Win32 absolute normalized path.
18013498266Sopenharmony_cisub get_abs_path_on_win32_drive;
18113498266Sopenharmony_ci
18213498266Sopenharmony_ci# Internal function. Tries to find or guess Win32 version of given
18313498266Sopenharmony_ci# absolute Unix-style path. Other types of paths are not supported.
18413498266Sopenharmony_ci# Returned paths contain only single forward slashes (no back and
18513498266Sopenharmony_ci# duplicated slashes).
18613498266Sopenharmony_ci# Last resort. Used only when other transformations are not available.
18713498266Sopenharmony_cisub do_dumb_guessed_transform;
18813498266Sopenharmony_ci
18913498266Sopenharmony_ci#######################################################################
19013498266Sopenharmony_ci# Converts given path to system native format, i.e. to Win32 format on
19113498266Sopenharmony_ci# Windows platform. Relative paths converted to relative, absolute
19213498266Sopenharmony_ci# paths converted to absolute.
19313498266Sopenharmony_ci#
19413498266Sopenharmony_cisub sys_native_path {
19513498266Sopenharmony_ci    my ($path) = @_;
19613498266Sopenharmony_ci
19713498266Sopenharmony_ci    # Return untouched on non-Windows platforms.
19813498266Sopenharmony_ci    return $path if (!os_is_win());
19913498266Sopenharmony_ci
20013498266Sopenharmony_ci    # Do not process empty path.
20113498266Sopenharmony_ci    return $path if ($path eq '');
20213498266Sopenharmony_ci
20313498266Sopenharmony_ci    if($path =~ s{^([a-zA-Z]):$}{\u$1:}) {
20413498266Sopenharmony_ci        # Path is single drive with colon. (C:)
20513498266Sopenharmony_ci        # This type of paths is not processed correctly by 'cygpath'.
20613498266Sopenharmony_ci        # WARNING!
20713498266Sopenharmony_ci        # Be careful, this relative path can be accidentally transformed
20813498266Sopenharmony_ci        # into wrong absolute path by adding to it some '/dirname' with
20913498266Sopenharmony_ci        # slash at font.
21013498266Sopenharmony_ci        return $path;
21113498266Sopenharmony_ci    }
21213498266Sopenharmony_ci    elsif($path =~ m{^\\} || $path =~ m{^[a-zA-Z]:[^/\\]}) {
21313498266Sopenharmony_ci        # Path is a directory or filename on Win32 current drive or relative
21413498266Sopenharmony_ci        # path on current directory on specific Win32 drive.
21513498266Sopenharmony_ci        # ('\path' or 'D:path')
21613498266Sopenharmony_ci        # First type of paths is not processed by Msys transformation and
21713498266Sopenharmony_ci        # resolved to absolute path by 'cygpath'.
21813498266Sopenharmony_ci        # Second type is not processed by Msys transformation and may be
21913498266Sopenharmony_ci        # incorrectly processed by 'cygpath' (for paths like 'D:..\../.\')
22013498266Sopenharmony_ci
22113498266Sopenharmony_ci        my $first_char = ucfirst(substr($path, 0, 1));
22213498266Sopenharmony_ci
22313498266Sopenharmony_ci        # Replace any back and duplicated slashes with single forward slashes.
22413498266Sopenharmony_ci        $path =~ s{[\\/]+}{/}g;
22513498266Sopenharmony_ci
22613498266Sopenharmony_ci        # Convert leading slash back to forward slash to indicate
22713498266Sopenharmony_ci        # directory on Win32 current drive or capitalize drive letter.
22813498266Sopenharmony_ci        substr($path, 0, 1, $first_char);
22913498266Sopenharmony_ci        return $path;
23013498266Sopenharmony_ci    }
23113498266Sopenharmony_ci    elsif(should_use_cygpath()) {
23213498266Sopenharmony_ci        # 'cygpath' is available - use it.
23313498266Sopenharmony_ci
23413498266Sopenharmony_ci        # Remove leading duplicated forward and back slashes, as they may
23513498266Sopenharmony_ci        # prevent transforming and may be not processed.
23613498266Sopenharmony_ci        $path =~ s{^([\\/])[\\/]+}{$1}g;
23713498266Sopenharmony_ci
23813498266Sopenharmony_ci        my $has_final_slash = ($path =~ m{[/\\]$});
23913498266Sopenharmony_ci
24013498266Sopenharmony_ci        # Use 'cygpath', '-m' means Win32 path with forward slashes.
24113498266Sopenharmony_ci        chomp($path = `cygpath -m '$path'`);
24213498266Sopenharmony_ci        if ($? != 0) {
24313498266Sopenharmony_ci            warn "Can't convert path by \"cygpath\".\n";
24413498266Sopenharmony_ci            return undef;
24513498266Sopenharmony_ci        }
24613498266Sopenharmony_ci
24713498266Sopenharmony_ci        # 'cygpath' may remove last slash for existing directories.
24813498266Sopenharmony_ci        $path .= '/' if($has_final_slash);
24913498266Sopenharmony_ci
25013498266Sopenharmony_ci        # Remove any duplicated forward slashes (added by 'cygpath' for root
25113498266Sopenharmony_ci        # directories)
25213498266Sopenharmony_ci        $path =~ s{//+}{/}g;
25313498266Sopenharmony_ci
25413498266Sopenharmony_ci        return $path;
25513498266Sopenharmony_ci    }
25613498266Sopenharmony_ci    elsif($^O eq 'msys') {
25713498266Sopenharmony_ci        # Msys transforms automatically path to Windows native form in staring
25813498266Sopenharmony_ci        # program parameters if program is not Msys-based.
25913498266Sopenharmony_ci
26013498266Sopenharmony_ci        $path = do_msys_transform($path);
26113498266Sopenharmony_ci        return undef if !defined $path;
26213498266Sopenharmony_ci
26313498266Sopenharmony_ci        # Capitalize drive letter for Win32 paths.
26413498266Sopenharmony_ci        $path =~ s{^([a-z]:)}{\u$1};
26513498266Sopenharmony_ci
26613498266Sopenharmony_ci        # Replace any back and duplicated slashes with single forward slashes.
26713498266Sopenharmony_ci        $path =~ s{[\\/]+}{/}g;
26813498266Sopenharmony_ci        return $path;
26913498266Sopenharmony_ci    }
27013498266Sopenharmony_ci    elsif($path =~ s{^([a-zA-Z]):[/\\]}{\u$1:/}) {
27113498266Sopenharmony_ci        # Path is already in Win32 form. ('C:\path')
27213498266Sopenharmony_ci
27313498266Sopenharmony_ci        # Replace any back and duplicated slashes with single forward slashes.
27413498266Sopenharmony_ci        $path =~ s{[\\/]+}{/}g;
27513498266Sopenharmony_ci        return $path;
27613498266Sopenharmony_ci    }
27713498266Sopenharmony_ci    elsif($path !~ m{^/}) {
27813498266Sopenharmony_ci        # Path is in relative form. ('path/name', './path' or '../path')
27913498266Sopenharmony_ci
28013498266Sopenharmony_ci        # Replace any back and duplicated slashes with single forward slashes.
28113498266Sopenharmony_ci        $path =~ s{[\\/]+}{/}g;
28213498266Sopenharmony_ci        return $path;
28313498266Sopenharmony_ci    }
28413498266Sopenharmony_ci
28513498266Sopenharmony_ci    # OS is Windows, but not Msys, path is absolute, path is not in Win32
28613498266Sopenharmony_ci    # form and 'cygpath' is not available.
28713498266Sopenharmony_ci    return do_dumb_guessed_transform($path);
28813498266Sopenharmony_ci}
28913498266Sopenharmony_ci
29013498266Sopenharmony_ci#######################################################################
29113498266Sopenharmony_ci# Converts given path to system native absolute path, i.e. to Win32
29213498266Sopenharmony_ci# absolute format on Windows platform. Both relative and absolute
29313498266Sopenharmony_ci# formats are supported for input.
29413498266Sopenharmony_ci#
29513498266Sopenharmony_cisub sys_native_abs_path {
29613498266Sopenharmony_ci    my ($path) = @_;
29713498266Sopenharmony_ci
29813498266Sopenharmony_ci    if(!os_is_win()) {
29913498266Sopenharmony_ci        # Convert path to absolute form.
30013498266Sopenharmony_ci        $path = Cwd::abs_path($path);
30113498266Sopenharmony_ci
30213498266Sopenharmony_ci        # Do not process further on non-Windows platforms.
30313498266Sopenharmony_ci        return $path;
30413498266Sopenharmony_ci    }
30513498266Sopenharmony_ci
30613498266Sopenharmony_ci    if($path =~ m{^([a-zA-Z]):($|[^/\\].*$)}) {
30713498266Sopenharmony_ci        # Path is single drive with colon or relative path on Win32 drive.
30813498266Sopenharmony_ci        # ('C:' or 'C:path')
30913498266Sopenharmony_ci        # This kind of relative path is not processed correctly by 'cygpath'.
31013498266Sopenharmony_ci        # Get specified drive letter
31113498266Sopenharmony_ci        return get_abs_path_on_win32_drive($1, $2);
31213498266Sopenharmony_ci    }
31313498266Sopenharmony_ci    elsif($path eq '') {
31413498266Sopenharmony_ci        # Path is empty string. Return current directory.
31513498266Sopenharmony_ci        # Empty string processed correctly by 'cygpath'.
31613498266Sopenharmony_ci
31713498266Sopenharmony_ci        return sys_native_current_path();
31813498266Sopenharmony_ci    }
31913498266Sopenharmony_ci    elsif(should_use_cygpath()) {
32013498266Sopenharmony_ci        # 'cygpath' is available - use it.
32113498266Sopenharmony_ci
32213498266Sopenharmony_ci        my $has_final_slash = ($path =~ m{[\\/]$});
32313498266Sopenharmony_ci
32413498266Sopenharmony_ci        # Remove leading duplicated forward and back slashes, as they may
32513498266Sopenharmony_ci        # prevent transforming and may be not processed.
32613498266Sopenharmony_ci        $path =~ s{^([\\/])[\\/]+}{$1}g;
32713498266Sopenharmony_ci
32813498266Sopenharmony_ci        print "Inter result: \"$path\"\n";
32913498266Sopenharmony_ci        # Use 'cygpath', '-m' means Win32 path with forward slashes,
33013498266Sopenharmony_ci        # '-a' means absolute path
33113498266Sopenharmony_ci        chomp($path = `cygpath -m -a '$path'`);
33213498266Sopenharmony_ci        if($? != 0) {
33313498266Sopenharmony_ci            warn "Can't resolve path by usung \"cygpath\".\n";
33413498266Sopenharmony_ci            return undef;
33513498266Sopenharmony_ci        }
33613498266Sopenharmony_ci
33713498266Sopenharmony_ci        # 'cygpath' may remove last slash for existing directories.
33813498266Sopenharmony_ci        $path .= '/' if($has_final_slash);
33913498266Sopenharmony_ci
34013498266Sopenharmony_ci        # Remove any duplicated forward slashes (added by 'cygpath' for root
34113498266Sopenharmony_ci        # directories)
34213498266Sopenharmony_ci        $path =~ s{//+}{/}g;
34313498266Sopenharmony_ci
34413498266Sopenharmony_ci        return $path
34513498266Sopenharmony_ci    }
34613498266Sopenharmony_ci    elsif($path =~ s{^([a-zA-Z]):[/\\]}{\u$1:/}) {
34713498266Sopenharmony_ci        # Path is already in Win32 form. ('C:\path')
34813498266Sopenharmony_ci
34913498266Sopenharmony_ci        # Replace any possible back slashes with forward slashes,
35013498266Sopenharmony_ci        # remove any duplicated slashes, resolve relative dirs.
35113498266Sopenharmony_ci        return normalize_path($path);
35213498266Sopenharmony_ci    }
35313498266Sopenharmony_ci    elsif(substr($path, 0, 1) eq '\\' ) {
35413498266Sopenharmony_ci        # Path is directory or filename on Win32 current drive. ('\Windows')
35513498266Sopenharmony_ci
35613498266Sopenharmony_ci        my $w32drive = get_win32_current_drive();
35713498266Sopenharmony_ci        return undef if !defined $w32drive;
35813498266Sopenharmony_ci
35913498266Sopenharmony_ci        # Combine drive and path.
36013498266Sopenharmony_ci        # Replace any possible back slashes with forward slashes,
36113498266Sopenharmony_ci        # remove any duplicated slashes, resolve relative dirs.
36213498266Sopenharmony_ci        return normalize_path($w32drive . $path);
36313498266Sopenharmony_ci    }
36413498266Sopenharmony_ci
36513498266Sopenharmony_ci    if(substr($path, 0, 1) ne '/') {
36613498266Sopenharmony_ci        # Path is in relative form. Resolve relative directories in Unix form
36713498266Sopenharmony_ci        # *BEFORE* converting to Win32 form otherwise paths like
36813498266Sopenharmony_ci        # '../../../cygdrive/c/windows' will not be resolved.
36913498266Sopenharmony_ci
37013498266Sopenharmony_ci        my $cur_dir;
37113498266Sopenharmony_ci        # MSys shell has built-in command.
37213498266Sopenharmony_ci        if($^O eq 'msys') {
37313498266Sopenharmony_ci            $cur_dir = `bash -c 'pwd -L'`;
37413498266Sopenharmony_ci        }
37513498266Sopenharmony_ci        else {
37613498266Sopenharmony_ci            $cur_dir = `pwd -L`;
37713498266Sopenharmony_ci        }
37813498266Sopenharmony_ci        if($? != 0) {
37913498266Sopenharmony_ci            warn "Can't determine current working directory.\n";
38013498266Sopenharmony_ci            return undef;
38113498266Sopenharmony_ci        }
38213498266Sopenharmony_ci        chomp($cur_dir);
38313498266Sopenharmony_ci
38413498266Sopenharmony_ci        $path = $cur_dir . '/' . $path;
38513498266Sopenharmony_ci    }
38613498266Sopenharmony_ci
38713498266Sopenharmony_ci    # Resolve relative dirs.
38813498266Sopenharmony_ci    $path = normalize_path($path);
38913498266Sopenharmony_ci    return undef unless defined $path;
39013498266Sopenharmony_ci
39113498266Sopenharmony_ci    if($^O eq 'msys') {
39213498266Sopenharmony_ci        # Msys transforms automatically path to Windows native form in staring
39313498266Sopenharmony_ci        # program parameters if program is not Msys-based.
39413498266Sopenharmony_ci        $path = do_msys_transform($path);
39513498266Sopenharmony_ci        return undef if !defined $path;
39613498266Sopenharmony_ci
39713498266Sopenharmony_ci        # Replace any back and duplicated slashes with single forward slashes.
39813498266Sopenharmony_ci        $path =~ s{[\\/]+}{/}g;
39913498266Sopenharmony_ci        return $path;
40013498266Sopenharmony_ci    }
40113498266Sopenharmony_ci    # OS is Windows, but not Msys, path is absolute, path is not in Win32
40213498266Sopenharmony_ci    # form and 'cygpath' is not available.
40313498266Sopenharmony_ci
40413498266Sopenharmony_ci    return do_dumb_guessed_transform($path);
40513498266Sopenharmony_ci}
40613498266Sopenharmony_ci
40713498266Sopenharmony_ci# Internal function. Converts given Unix-style absolute path to Win32 format.
40813498266Sopenharmony_cisub simple_transform_win32_to_unix;
40913498266Sopenharmony_ci
41013498266Sopenharmony_ci#######################################################################
41113498266Sopenharmony_ci# Converts given path to build system format absolute path, i.e. to
41213498266Sopenharmony_ci# Msys/Cygwin Unix-style absolute format on Windows platform. Both
41313498266Sopenharmony_ci# relative and absolute formats are supported for input.
41413498266Sopenharmony_ci#
41513498266Sopenharmony_cisub build_sys_abs_path {
41613498266Sopenharmony_ci    my ($path) = @_;
41713498266Sopenharmony_ci
41813498266Sopenharmony_ci    if(!os_is_win()) {
41913498266Sopenharmony_ci        # Convert path to absolute form.
42013498266Sopenharmony_ci        $path = Cwd::abs_path($path);
42113498266Sopenharmony_ci
42213498266Sopenharmony_ci        # Do not process further on non-Windows platforms.
42313498266Sopenharmony_ci        return $path;
42413498266Sopenharmony_ci    }
42513498266Sopenharmony_ci
42613498266Sopenharmony_ci    if($path =~ m{^([a-zA-Z]):($|[^/\\].*$)}) {
42713498266Sopenharmony_ci        # Path is single drive with colon or relative path on Win32 drive.
42813498266Sopenharmony_ci        # ('C:' or 'C:path')
42913498266Sopenharmony_ci        # This kind of relative path is not processed correctly by 'cygpath'.
43013498266Sopenharmony_ci        # Get specified drive letter
43113498266Sopenharmony_ci
43213498266Sopenharmony_ci        # Resolve relative dirs in Win32-style path or paths like 'D:/../c/'
43313498266Sopenharmony_ci        # will be resolved incorrectly.
43413498266Sopenharmony_ci        # Replace any possible back slashes with forward slashes,
43513498266Sopenharmony_ci        # remove any duplicated slashes.
43613498266Sopenharmony_ci        $path = get_abs_path_on_win32_drive($1, $2);
43713498266Sopenharmony_ci        return undef if !defined $path;
43813498266Sopenharmony_ci
43913498266Sopenharmony_ci        return simple_transform_win32_to_unix($path);
44013498266Sopenharmony_ci    }
44113498266Sopenharmony_ci    elsif($path eq '') {
44213498266Sopenharmony_ci        # Path is empty string. Return current directory.
44313498266Sopenharmony_ci        # Empty string processed correctly by 'cygpath'.
44413498266Sopenharmony_ci
44513498266Sopenharmony_ci        # MSys shell has built-in command.
44613498266Sopenharmony_ci        if($^O eq 'msys') {
44713498266Sopenharmony_ci            chomp($path = `bash -c 'pwd -L'`);
44813498266Sopenharmony_ci        }
44913498266Sopenharmony_ci        else {
45013498266Sopenharmony_ci            chomp($path = `pwd -L`);
45113498266Sopenharmony_ci        }
45213498266Sopenharmony_ci        if($? != 0) {
45313498266Sopenharmony_ci            warn "Can't determine Unix-style current working directory.\n";
45413498266Sopenharmony_ci            return undef;
45513498266Sopenharmony_ci        }
45613498266Sopenharmony_ci
45713498266Sopenharmony_ci        # Add final slash if not at root dir.
45813498266Sopenharmony_ci        $path .= '/' if length($path) > 2;
45913498266Sopenharmony_ci        return $path;
46013498266Sopenharmony_ci    }
46113498266Sopenharmony_ci    elsif(should_use_cygpath()) {
46213498266Sopenharmony_ci        # 'cygpath' is available - use it.
46313498266Sopenharmony_ci
46413498266Sopenharmony_ci        my $has_final_slash = ($path =~ m{[\\/]$});
46513498266Sopenharmony_ci
46613498266Sopenharmony_ci        # Resolve relative directories, as they may be not resolved for
46713498266Sopenharmony_ci        # Unix-style paths.
46813498266Sopenharmony_ci        # Remove duplicated slashes, as they may be not processed.
46913498266Sopenharmony_ci        $path = normalize_path($path);
47013498266Sopenharmony_ci        return undef if !defined $path;
47113498266Sopenharmony_ci
47213498266Sopenharmony_ci        # Use 'cygpath', '-u' means Unix-stile path,
47313498266Sopenharmony_ci        # '-a' means absolute path
47413498266Sopenharmony_ci        chomp($path = `cygpath -u -a '$path'`);
47513498266Sopenharmony_ci        if($? != 0) {
47613498266Sopenharmony_ci            warn "Can't resolve path by usung \"cygpath\".\n";
47713498266Sopenharmony_ci            return undef;
47813498266Sopenharmony_ci        }
47913498266Sopenharmony_ci
48013498266Sopenharmony_ci        # 'cygpath' removes last slash if path is root dir on Win32 drive.
48113498266Sopenharmony_ci        # Restore it.
48213498266Sopenharmony_ci        $path .= '/' if($has_final_slash &&
48313498266Sopenharmony_ci                        substr($path, length($path) - 1, 1) ne '/');
48413498266Sopenharmony_ci
48513498266Sopenharmony_ci        return $path
48613498266Sopenharmony_ci    }
48713498266Sopenharmony_ci    elsif($path =~ m{^[a-zA-Z]:[/\\]}) {
48813498266Sopenharmony_ci        # Path is already in Win32 form. ('C:\path')
48913498266Sopenharmony_ci
49013498266Sopenharmony_ci        # Resolve relative dirs in Win32-style path otherwise paths
49113498266Sopenharmony_ci        # like 'D:/../c/' will be resolved incorrectly.
49213498266Sopenharmony_ci        # Replace any possible back slashes with forward slashes,
49313498266Sopenharmony_ci        # remove any duplicated slashes.
49413498266Sopenharmony_ci        $path = normalize_path($path);
49513498266Sopenharmony_ci        return undef if !defined $path;
49613498266Sopenharmony_ci
49713498266Sopenharmony_ci        return simple_transform_win32_to_unix($path);
49813498266Sopenharmony_ci    }
49913498266Sopenharmony_ci    elsif(substr($path, 0, 1) eq '\\') {
50013498266Sopenharmony_ci        # Path is directory or filename on Win32 current drive. ('\Windows')
50113498266Sopenharmony_ci
50213498266Sopenharmony_ci        my $w32drive = get_win32_current_drive();
50313498266Sopenharmony_ci        return undef if !defined $w32drive;
50413498266Sopenharmony_ci
50513498266Sopenharmony_ci        # Combine drive and path.
50613498266Sopenharmony_ci        # Resolve relative dirs in Win32-style path or paths like 'D:/../c/'
50713498266Sopenharmony_ci        # will be resolved incorrectly.
50813498266Sopenharmony_ci        # Replace any possible back slashes with forward slashes,
50913498266Sopenharmony_ci        # remove any duplicated slashes.
51013498266Sopenharmony_ci        $path = normalize_path($w32drive . $path);
51113498266Sopenharmony_ci        return undef if !defined $path;
51213498266Sopenharmony_ci
51313498266Sopenharmony_ci        return simple_transform_win32_to_unix($path);
51413498266Sopenharmony_ci    }
51513498266Sopenharmony_ci
51613498266Sopenharmony_ci    # Path is not in any Win32 form.
51713498266Sopenharmony_ci    if(substr($path, 0, 1) ne '/') {
51813498266Sopenharmony_ci        # Path in relative form. Resolve relative directories in Unix form
51913498266Sopenharmony_ci        # *BEFORE* converting to Win32 form otherwise paths like
52013498266Sopenharmony_ci        # '../../../cygdrive/c/windows' will not be resolved.
52113498266Sopenharmony_ci
52213498266Sopenharmony_ci        my $cur_dir;
52313498266Sopenharmony_ci        # MSys shell has built-in command.
52413498266Sopenharmony_ci        if($^O eq 'msys') {
52513498266Sopenharmony_ci            $cur_dir = `bash -c 'pwd -L'`;
52613498266Sopenharmony_ci        }
52713498266Sopenharmony_ci        else {
52813498266Sopenharmony_ci            $cur_dir = `pwd -L`;
52913498266Sopenharmony_ci        }
53013498266Sopenharmony_ci        if($? != 0) {
53113498266Sopenharmony_ci            warn "Can't determine current working directory.\n";
53213498266Sopenharmony_ci            return undef;
53313498266Sopenharmony_ci        }
53413498266Sopenharmony_ci        chomp($cur_dir);
53513498266Sopenharmony_ci
53613498266Sopenharmony_ci        $path = $cur_dir . '/' . $path;
53713498266Sopenharmony_ci    }
53813498266Sopenharmony_ci
53913498266Sopenharmony_ci    return normalize_path($path);
54013498266Sopenharmony_ci}
54113498266Sopenharmony_ci
54213498266Sopenharmony_ci#######################################################################
54313498266Sopenharmony_ci# Performs path "normalization": all slashes converted to forward
54413498266Sopenharmony_ci# slashes (except leading slash), all duplicated slashes are replaced
54513498266Sopenharmony_ci# with single slashes, all relative directories ('./' and '../') are
54613498266Sopenharmony_ci# resolved if possible.
54713498266Sopenharmony_ci# Path processed as string, directories are not checked for presence so
54813498266Sopenharmony_ci# path for not yet existing directory can be "normalized".
54913498266Sopenharmony_ci#
55013498266Sopenharmony_cisub normalize_path {
55113498266Sopenharmony_ci    my ($path) = @_;
55213498266Sopenharmony_ci
55313498266Sopenharmony_ci    # Don't process empty paths.
55413498266Sopenharmony_ci    return $path if $path eq '';
55513498266Sopenharmony_ci
55613498266Sopenharmony_ci    if($path !~ m{(?:^|\\|/)\.{1,2}(?:\\|/|$)}) {
55713498266Sopenharmony_ci        # Speed up processing of simple paths.
55813498266Sopenharmony_ci        my $first_char = substr($path, 0, 1);
55913498266Sopenharmony_ci        $path =~ s{[\\/]+}{/}g;
56013498266Sopenharmony_ci        # Restore starting backslash if any.
56113498266Sopenharmony_ci        substr($path, 0, 1, $first_char);
56213498266Sopenharmony_ci        return $path;
56313498266Sopenharmony_ci    }
56413498266Sopenharmony_ci
56513498266Sopenharmony_ci    my @arr;
56613498266Sopenharmony_ci    my $prefix;
56713498266Sopenharmony_ci    my $have_root = 0;
56813498266Sopenharmony_ci
56913498266Sopenharmony_ci    # Check whether path starts from Win32 drive. ('C:path' or 'C:\path')
57013498266Sopenharmony_ci    if($path =~ m{^([a-zA-Z]:(/|\\)?)(.*$)}) {
57113498266Sopenharmony_ci        $prefix = $1;
57213498266Sopenharmony_ci        $have_root = 1 if defined $2;
57313498266Sopenharmony_ci        # Process path separately from drive letter.
57413498266Sopenharmony_ci        @arr = split(m{\/|\\}, $3);
57513498266Sopenharmony_ci        # Replace backslash with forward slash if required.
57613498266Sopenharmony_ci        substr($prefix, 2, 1, '/') if $have_root;
57713498266Sopenharmony_ci    }
57813498266Sopenharmony_ci    else {
57913498266Sopenharmony_ci        if($path =~ m{^(\/|\\)}) {
58013498266Sopenharmony_ci            $have_root = 1;
58113498266Sopenharmony_ci            $prefix = $1;
58213498266Sopenharmony_ci        }
58313498266Sopenharmony_ci        else {
58413498266Sopenharmony_ci            $prefix = '';
58513498266Sopenharmony_ci        }
58613498266Sopenharmony_ci        @arr = split(m{\/|\\}, $path);
58713498266Sopenharmony_ci    }
58813498266Sopenharmony_ci
58913498266Sopenharmony_ci    my $p = 0;
59013498266Sopenharmony_ci    my @res;
59113498266Sopenharmony_ci
59213498266Sopenharmony_ci    for my $el (@arr) {
59313498266Sopenharmony_ci        if(length($el) == 0 || $el eq '.') {
59413498266Sopenharmony_ci            next;
59513498266Sopenharmony_ci        }
59613498266Sopenharmony_ci        elsif($el eq '..' && @res > 0 && $res[-1] ne '..') {
59713498266Sopenharmony_ci            pop @res;
59813498266Sopenharmony_ci            next;
59913498266Sopenharmony_ci        }
60013498266Sopenharmony_ci        push @res, $el;
60113498266Sopenharmony_ci    }
60213498266Sopenharmony_ci    if($have_root && @res > 0 && $res[0] eq '..') {
60313498266Sopenharmony_ci        warn "Error processing path \"$path\": " .
60413498266Sopenharmony_ci             "Parent directory of root directory does not exist!\n";
60513498266Sopenharmony_ci        return undef;
60613498266Sopenharmony_ci    }
60713498266Sopenharmony_ci
60813498266Sopenharmony_ci    my $ret = $prefix . join('/', @res);
60913498266Sopenharmony_ci    $ret .= '/' if($path =~ m{\\$|/$} && scalar @res > 0);
61013498266Sopenharmony_ci
61113498266Sopenharmony_ci    return $ret;
61213498266Sopenharmony_ci}
61313498266Sopenharmony_ci
61413498266Sopenharmony_ci# Internal function. Converts path by using Msys's built-in
61513498266Sopenharmony_ci# transformation.
61613498266Sopenharmony_cisub do_msys_transform {
61713498266Sopenharmony_ci    my ($path) = @_;
61813498266Sopenharmony_ci    return undef if $^O ne 'msys';
61913498266Sopenharmony_ci    return $path if $path eq '';
62013498266Sopenharmony_ci
62113498266Sopenharmony_ci    # Remove leading double forward slashes, as they turn off Msys
62213498266Sopenharmony_ci    # transforming.
62313498266Sopenharmony_ci    $path =~ s{^/[/\\]+}{/};
62413498266Sopenharmony_ci
62513498266Sopenharmony_ci    # Msys transforms automatically path to Windows native form in staring
62613498266Sopenharmony_ci    # program parameters if program is not Msys-based.
62713498266Sopenharmony_ci    # Note: already checked that $path is non-empty.
62813498266Sopenharmony_ci    $path = `cmd //c echo '$path'`;
62913498266Sopenharmony_ci    if($? != 0) {
63013498266Sopenharmony_ci        warn "Can't transform path into Win32 form by using Msys" .
63113498266Sopenharmony_ci             "internal transformation.\n";
63213498266Sopenharmony_ci        return undef;
63313498266Sopenharmony_ci    }
63413498266Sopenharmony_ci
63513498266Sopenharmony_ci    # Remove double quotes, they are added for paths with spaces,
63613498266Sopenharmony_ci    # remove both '\r' and '\n'.
63713498266Sopenharmony_ci    $path =~ s{^\"|\"$|\"\r|\n|\r}{}g;
63813498266Sopenharmony_ci
63913498266Sopenharmony_ci    return $path;
64013498266Sopenharmony_ci}
64113498266Sopenharmony_ci
64213498266Sopenharmony_ci# Internal function. Gets two parameters: first parameter must be single
64313498266Sopenharmony_ci# drive letter ('c'), second optional parameter is path relative to drive's
64413498266Sopenharmony_ci# current working directory. Returns Win32 absolute normalized path.
64513498266Sopenharmony_cisub get_abs_path_on_win32_drive {
64613498266Sopenharmony_ci    my ($drv, $rel_path) = @_;
64713498266Sopenharmony_ci    my $res;
64813498266Sopenharmony_ci
64913498266Sopenharmony_ci    # Get current directory on specified drive.
65013498266Sopenharmony_ci    # "/c;" is compatible with both Msys and Cygwin.
65113498266Sopenharmony_ci    my $cur_dir_on_drv = `cmd "/c;" echo %=$drv:%`;
65213498266Sopenharmony_ci    if($? != 0) {
65313498266Sopenharmony_ci        warn "Can't determine Win32 current directory on drive $drv:.\n";
65413498266Sopenharmony_ci        return undef;
65513498266Sopenharmony_ci    }
65613498266Sopenharmony_ci
65713498266Sopenharmony_ci    if($cur_dir_on_drv =~ m{^[%]}) {
65813498266Sopenharmony_ci        # Current directory on drive is not set, default is
65913498266Sopenharmony_ci        # root directory.
66013498266Sopenharmony_ci
66113498266Sopenharmony_ci        $res = ucfirst($drv) . ':/';
66213498266Sopenharmony_ci    }
66313498266Sopenharmony_ci    else {
66413498266Sopenharmony_ci        # Current directory on drive was set.
66513498266Sopenharmony_ci        # Remove both '\r' and '\n'.
66613498266Sopenharmony_ci        $cur_dir_on_drv =~ s{\n|\r}{}g;
66713498266Sopenharmony_ci
66813498266Sopenharmony_ci        # Append relative path part.
66913498266Sopenharmony_ci        $res = $cur_dir_on_drv . '/';
67013498266Sopenharmony_ci    }
67113498266Sopenharmony_ci    $res .= $rel_path if defined $rel_path;
67213498266Sopenharmony_ci
67313498266Sopenharmony_ci    # Replace any possible back slashes with forward slashes,
67413498266Sopenharmony_ci    # remove any duplicated slashes, resolve relative dirs.
67513498266Sopenharmony_ci    return normalize_path($res);
67613498266Sopenharmony_ci}
67713498266Sopenharmony_ci
67813498266Sopenharmony_ci# Internal function. Tries to find or guess Win32 version of given
67913498266Sopenharmony_ci# absolute Unix-style path. Other types of paths are not supported.
68013498266Sopenharmony_ci# Returned paths contain only single forward slashes (no back and
68113498266Sopenharmony_ci# duplicated slashes).
68213498266Sopenharmony_ci# Last resort. Used only when other transformations are not available.
68313498266Sopenharmony_cisub do_dumb_guessed_transform {
68413498266Sopenharmony_ci    my ($path) = @_;
68513498266Sopenharmony_ci
68613498266Sopenharmony_ci    # Replace any possible back slashes and duplicated forward slashes
68713498266Sopenharmony_ci    # with single forward slashes.
68813498266Sopenharmony_ci    $path =~ s{[/\\]+}{/}g;
68913498266Sopenharmony_ci
69013498266Sopenharmony_ci    # Empty path is not valid.
69113498266Sopenharmony_ci    return undef if (length($path) == 0);
69213498266Sopenharmony_ci
69313498266Sopenharmony_ci    # RE to find Win32 drive letter
69413498266Sopenharmony_ci    my $drv_ltr_re = drives_mounted_on_cygdrive() ?
69513498266Sopenharmony_ci                        qr{^/cygdrive/([a-zA-Z])($|/.*$)} :
69613498266Sopenharmony_ci                        qr{^/([a-zA-Z])($|/.*$)};
69713498266Sopenharmony_ci
69813498266Sopenharmony_ci    # Check path whether path is Win32 directly mapped drive and try to
69913498266Sopenharmony_ci    # transform it assuming that drive letter is matched to Win32 drive letter.
70013498266Sopenharmony_ci    if($path =~ m{$drv_ltr_re}) {
70113498266Sopenharmony_ci        return ucfirst($1) . ':/' if(length($2) == 0);
70213498266Sopenharmony_ci        return ucfirst($1) . ':' . $2;
70313498266Sopenharmony_ci    }
70413498266Sopenharmony_ci
70513498266Sopenharmony_ci    # This may be some custom mapped path. ('/mymount/path')
70613498266Sopenharmony_ci
70713498266Sopenharmony_ci    # Must check longest possible path component as subdir can be mapped to
70813498266Sopenharmony_ci    # different directory. For example '/usr/bin/' can be mapped to '/bin/' or
70913498266Sopenharmony_ci    # '/bin/' can be mapped to '/usr/bin/'.
71013498266Sopenharmony_ci    my $check_path = $path;
71113498266Sopenharmony_ci    my $path_tail = '';
71213498266Sopenharmony_ci    while(1) {
71313498266Sopenharmony_ci        if(-d $check_path) {
71413498266Sopenharmony_ci            my $res =
71513498266Sopenharmony_ci                `(cd "$check_path" && cmd /c "echo %__CD__%") 2>/dev/null`;
71613498266Sopenharmony_ci            if($? == 0 && substr($path, 0, 1) ne '%') {
71713498266Sopenharmony_ci                # Remove both '\r' and '\n'.
71813498266Sopenharmony_ci                $res =~ s{\n|\r}{}g;
71913498266Sopenharmony_ci
72013498266Sopenharmony_ci                # Replace all back slashes with forward slashes.
72113498266Sopenharmony_ci                $res =~ s{\\}{/}g;
72213498266Sopenharmony_ci
72313498266Sopenharmony_ci                if(length($path_tail) > 0) {
72413498266Sopenharmony_ci                    return $res . $path_tail;
72513498266Sopenharmony_ci                }
72613498266Sopenharmony_ci                else {
72713498266Sopenharmony_ci                    $res =~ s{/$}{} if $check_path !~ m{/$};
72813498266Sopenharmony_ci                    return $res;
72913498266Sopenharmony_ci                }
73013498266Sopenharmony_ci            }
73113498266Sopenharmony_ci        }
73213498266Sopenharmony_ci        if($check_path =~ m{(^.*/)([^/]+/*)}) {
73313498266Sopenharmony_ci            $check_path = $1;
73413498266Sopenharmony_ci            $path_tail = $2 . $path_tail;
73513498266Sopenharmony_ci        }
73613498266Sopenharmony_ci        else {
73713498266Sopenharmony_ci            # Shouldn't happens as root '/' directory should always
73813498266Sopenharmony_ci            # be resolvable.
73913498266Sopenharmony_ci            warn "Can't determine Win32 directory for path \"$path\".\n";
74013498266Sopenharmony_ci            return undef;
74113498266Sopenharmony_ci        }
74213498266Sopenharmony_ci    }
74313498266Sopenharmony_ci}
74413498266Sopenharmony_ci
74513498266Sopenharmony_ci
74613498266Sopenharmony_ci# Internal function. Converts given Unix-style absolute path to Win32 format.
74713498266Sopenharmony_cisub simple_transform_win32_to_unix {
74813498266Sopenharmony_ci    my ($path) = @_;
74913498266Sopenharmony_ci
75013498266Sopenharmony_ci    if(should_use_cygpath()) {
75113498266Sopenharmony_ci        # 'cygpath' gives precise result.
75213498266Sopenharmony_ci        my $res;
75313498266Sopenharmony_ci        chomp($res = `cygpath -a -u '$path'`);
75413498266Sopenharmony_ci        if($? != 0) {
75513498266Sopenharmony_ci            warn "Can't determine Unix-style directory for Win32 " .
75613498266Sopenharmony_ci                 "directory \"$path\".\n";
75713498266Sopenharmony_ci            return undef;
75813498266Sopenharmony_ci        }
75913498266Sopenharmony_ci
76013498266Sopenharmony_ci        # 'cygpath' removes last slash if path is root dir on Win32 drive.
76113498266Sopenharmony_ci        $res .= '/' if(substr($res, length($res) - 1, 1) ne '/' &&
76213498266Sopenharmony_ci                       $path =~ m{[/\\]$});
76313498266Sopenharmony_ci        return $res;
76413498266Sopenharmony_ci    }
76513498266Sopenharmony_ci
76613498266Sopenharmony_ci    # 'cygpath' is not available, use guessed transformation.
76713498266Sopenharmony_ci    if($path !~ s{^([a-zA-Z]):(?:/|\\)}{/\l$1/}) {
76813498266Sopenharmony_ci        warn "Can't determine Unix-style directory for Win32 " .
76913498266Sopenharmony_ci             "directory \"$path\".\n";
77013498266Sopenharmony_ci        return undef;
77113498266Sopenharmony_ci    }
77213498266Sopenharmony_ci
77313498266Sopenharmony_ci    $path = '/cygdrive' . $path if(drives_mounted_on_cygdrive());
77413498266Sopenharmony_ci    return $path;
77513498266Sopenharmony_ci}
77613498266Sopenharmony_ci#
77713498266Sopenharmony_ci#***************************************************************************
77813498266Sopenharmony_ci# Return file extension for executable files on this operating system
77913498266Sopenharmony_ci#
78013498266Sopenharmony_cisub exe_ext {
78113498266Sopenharmony_ci    my ($component, @arr) = @_;
78213498266Sopenharmony_ci    if ($ENV{'CURL_TEST_EXE_EXT'}) {
78313498266Sopenharmony_ci        return $ENV{'CURL_TEST_EXE_EXT'};
78413498266Sopenharmony_ci    }
78513498266Sopenharmony_ci    if ($ENV{'CURL_TEST_EXE_EXT_'.$component}) {
78613498266Sopenharmony_ci        return $ENV{'CURL_TEST_EXE_EXT_'.$component};
78713498266Sopenharmony_ci    }
78813498266Sopenharmony_ci    if ($^O eq 'MSWin32' || $^O eq 'cygwin' || $^O eq 'msys' ||
78913498266Sopenharmony_ci        $^O eq 'dos' || $^O eq 'os2') {
79013498266Sopenharmony_ci        return '.exe';
79113498266Sopenharmony_ci    }
79213498266Sopenharmony_ci    return '';
79313498266Sopenharmony_ci}
79413498266Sopenharmony_ci
79513498266Sopenharmony_ci1;    # End of module
796