xref: /curl/tests/pathhelp.pm (revision 0acf0bce)
1###########################################################################
2#                                  _   _ ____  _
3#  Project                     ___| | | |  _ \| |
4#                             / __| | | | |_) | |
5#                            | (__| |_| |  _ <| |___
6#                             \___|\___/|_| \_\_____|
7#
8# Copyright (C) Evgeny Grin (Karlson2k), <k2k@narod.ru>.
9#
10# This software is licensed as described in the file COPYING, which
11# you should have received as part of this distribution. The terms
12# are also available at https://curl.se/docs/copyright.html.
13#
14# You may opt to use, copy, modify, merge, publish, distribute and/or sell
15# copies of the Software, and permit persons to whom the Software is
16# furnished to do so, under the terms of the COPYING file.
17#
18# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19# KIND, either express or implied.
20#
21# SPDX-License-Identifier: curl
22#
23###########################################################################
24
25# This Perl package helps with path transforming when running curl tests on
26# native Windows and MSYS/Cygwin.
27# Following input formats are supported (via built-in Perl functions):
28#  (1) /some/path   - absolute path in POSIX-style
29#  (2) D:/some/path - absolute path in Windows-style
30#  (3) some/path    - relative path
31#  (4) D:some/path  - path relative to current directory on Windows drive
32#                     (paths like 'D:' are treated as 'D:./') (*)
33#  (5) \some/path   - path from root directory on current Windows drive (*)
34# All forward '/' and back '\' slashes are treated identically except leading
35# slash in forms (1) and (5).
36# Forward slashes are simpler processed in Perl, do not require extra escaping
37# for shell (unlike back slashes) and accepted by Windows native programs, so
38# all functions return paths with only forward slashes.
39# All returned paths don't contain any duplicated slashes, only single slashes
40# are used as directory separators on output.
41# On non-Windows platforms functions acts as transparent wrappers for similar
42# Perl's functions or return unmodified string (depending on functionality),
43# so all functions can be unconditionally used on all platforms.
44#
45# (*) CAUTION! Forms (4) and (5) are not recommended to use as they can be
46#     interpreted incorrectly in Perl and MSYS/Cygwin environment have low
47#     control on Windows current drive and Windows current path on specific
48#     drive.
49
50package pathhelp;
51
52use strict;
53use warnings;
54use Cwd 'abs_path';
55
56BEGIN {
57    use base qw(Exporter);
58
59    our @EXPORT_OK = qw(
60        os_is_win
61        exe_ext
62        sys_native_abs_path
63        sys_native_current_path
64        build_sys_abs_path
65    );
66}
67
68
69#######################################################################
70# Block for cached static variables
71#
72{
73    # Cached static variable, Perl 5.0-compatible.
74    my $is_win = $^O eq 'MSWin32'
75              || $^O eq 'cygwin'
76              || $^O eq 'msys';
77
78    # Returns boolean true if OS is any form of Windows.
79    sub os_is_win {
80        return $is_win;
81    }
82
83    # Cached static variable, Perl 5.0-compatible.
84    my $cygdrive_present;
85
86    # Returns boolean true if Windows drives mounted with '/cygdrive/' prefix.
87    sub drives_mounted_on_cygdrive {
88        return $cygdrive_present if defined $cygdrive_present;
89        $cygdrive_present = ((-e '/cygdrive/') && (-d '/cygdrive/')) ? 1 : 0;
90        return $cygdrive_present;
91    }
92}
93
94#######################################################################
95# Returns current working directory in Windows format on Windows.
96#
97sub sys_native_current_path {
98    return Cwd::getcwd() if !os_is_win();
99
100    my $cur_dir;
101    if($^O eq 'MSWin32') {
102        $cur_dir = Cwd::getcwd();
103    }
104    else {
105        $cur_dir = Cygwin::posix_to_win_path(Cwd::getcwd());
106    }
107    $cur_dir =~ s{[/\\]+}{/}g;
108    return $cur_dir;
109}
110
111#######################################################################
112# Converts given path to system native absolute path, i.e. to Windows
113# absolute format on Windows platform. Both relative and absolute
114# formats are supported for input.
115#
116sub sys_native_abs_path {
117    my ($path) = @_;
118
119    # Return untouched on non-Windows platforms.
120    return Cwd::abs_path($path) if !os_is_win();
121
122    # Do not process empty path.
123    return $path if ($path eq '');
124
125    my $res;
126    if($^O eq 'msys' || $^O eq 'cygwin') {
127        $res = Cygwin::posix_to_win_path(Cwd::abs_path($path));
128    }
129    elsif($path =~ m{^/(cygdrive/)?([a-z])/(.*)}) {
130        $res = uc($2) . ":/" . $3;
131    }
132    else {
133        $res = Cwd::abs_path($path);
134    }
135
136    $res =~ s{[/\\]+}{/}g;
137    return $res;
138}
139
140#######################################################################
141# Converts given path to build system format absolute path, i.e. to
142# MSYS/Cygwin POSIX-style absolute format on Windows platform. Both
143# relative and absolute formats are supported for input.
144#
145sub build_sys_abs_path {
146    my ($path) = @_;
147
148    # Return untouched on non-Windows platforms.
149    return Cwd::abs_path($path) if !os_is_win();
150
151    my $res;
152    if($^O eq 'msys' || $^O eq 'cygwin') {
153        $res = Cygwin::win_to_posix_path($path, 1);
154    }
155    else {
156        $res = Cwd::abs_path($path);
157
158        if($res =~ m{^([A-Za-z]):(.*)}) {
159            $res = "/" . lc($1) . $2;
160            $res = '/cygdrive' . $res if(drives_mounted_on_cygdrive());
161        }
162    }
163
164    return $res;
165}
166
167#***************************************************************************
168# Return file extension for executable files on this operating system
169#
170sub exe_ext {
171    my ($component, @arr) = @_;
172    if ($ENV{'CURL_TEST_EXE_EXT'}) {
173        return $ENV{'CURL_TEST_EXE_EXT'};
174    }
175    if ($ENV{'CURL_TEST_EXE_EXT_'.$component}) {
176        return $ENV{'CURL_TEST_EXE_EXT_'.$component};
177    }
178    if ($^O eq 'MSWin32' || $^O eq 'cygwin' || $^O eq 'msys' ||
179        $^O eq 'dos' || $^O eq 'os2') {
180        return '.exe';
181    }
182    return '';
183}
184
1851;    # End of module
186