16fb12b70Safresh1package File::Spec::Win32; 26fb12b70Safresh1 36fb12b70Safresh1use strict; 46fb12b70Safresh1 59f11ffb7Safresh1use Cwd (); 66fb12b70Safresh1require File::Spec::Unix; 76fb12b70Safresh1 8*3d61058aSafresh1our $VERSION = '3.91'; 9b8851fccSafresh1$VERSION =~ tr/_//d; 106fb12b70Safresh1 119f11ffb7Safresh1our @ISA = qw(File::Spec::Unix); 126fb12b70Safresh1 136fb12b70Safresh1# Some regexes we use for path splitting 146fb12b70Safresh1my $DRIVE_RX = '[a-zA-Z]:'; 156fb12b70Safresh1my $UNC_RX = '(?:\\\\\\\\|//)[^\\\\/]+[\\\\/][^\\\\/]+'; 166fb12b70Safresh1my $VOL_RX = "(?:$DRIVE_RX|$UNC_RX)"; 176fb12b70Safresh1 186fb12b70Safresh1 196fb12b70Safresh1=head1 NAME 206fb12b70Safresh1 216fb12b70Safresh1File::Spec::Win32 - methods for Win32 file specs 226fb12b70Safresh1 236fb12b70Safresh1=head1 SYNOPSIS 246fb12b70Safresh1 256fb12b70Safresh1 require File::Spec::Win32; # Done internally by File::Spec if needed 266fb12b70Safresh1 276fb12b70Safresh1=head1 DESCRIPTION 286fb12b70Safresh1 296fb12b70Safresh1See File::Spec::Unix for a documentation of the methods provided 306fb12b70Safresh1there. This package overrides the implementation of these methods, not 316fb12b70Safresh1the semantics. 326fb12b70Safresh1 336fb12b70Safresh1=over 4 346fb12b70Safresh1 356fb12b70Safresh1=item devnull 366fb12b70Safresh1 376fb12b70Safresh1Returns a string representation of the null device. 386fb12b70Safresh1 396fb12b70Safresh1=cut 406fb12b70Safresh1 416fb12b70Safresh1sub devnull { 426fb12b70Safresh1 return "nul"; 436fb12b70Safresh1} 446fb12b70Safresh1 456fb12b70Safresh1sub rootdir { '\\' } 466fb12b70Safresh1 476fb12b70Safresh1 486fb12b70Safresh1=item tmpdir 496fb12b70Safresh1 506fb12b70Safresh1Returns a string representation of the first existing directory 516fb12b70Safresh1from the following list: 526fb12b70Safresh1 536fb12b70Safresh1 $ENV{TMPDIR} 546fb12b70Safresh1 $ENV{TEMP} 556fb12b70Safresh1 $ENV{TMP} 566fb12b70Safresh1 SYS:/temp 576fb12b70Safresh1 C:\system\temp 586fb12b70Safresh1 C:/temp 596fb12b70Safresh1 /tmp 606fb12b70Safresh1 / 616fb12b70Safresh1 626fb12b70Safresh1The SYS:/temp is preferred in Novell NetWare and the C:\system\temp 636fb12b70Safresh1for Symbian (the File::Spec::Win32 is used also for those platforms). 646fb12b70Safresh1 656fb12b70Safresh1If running under taint mode, and if the environment 666fb12b70Safresh1variables are tainted, they are not used. 676fb12b70Safresh1 686fb12b70Safresh1=cut 696fb12b70Safresh1 706fb12b70Safresh1sub tmpdir { 716fb12b70Safresh1 my $tmpdir = $_[0]->_cached_tmpdir(qw(TMPDIR TEMP TMP)); 726fb12b70Safresh1 return $tmpdir if defined $tmpdir; 736fb12b70Safresh1 $tmpdir = $_[0]->_tmpdir( map( $ENV{$_}, qw(TMPDIR TEMP TMP) ), 746fb12b70Safresh1 'SYS:/temp', 756fb12b70Safresh1 'C:\system\temp', 766fb12b70Safresh1 'C:/temp', 776fb12b70Safresh1 '/tmp', 786fb12b70Safresh1 '/' ); 796fb12b70Safresh1 $_[0]->_cache_tmpdir($tmpdir, qw(TMPDIR TEMP TMP)); 806fb12b70Safresh1} 816fb12b70Safresh1 826fb12b70Safresh1=item case_tolerant 836fb12b70Safresh1 846fb12b70Safresh1MSWin32 case-tolerance depends on GetVolumeInformation() $ouFsFlags == FS_CASE_SENSITIVE, 856fb12b70Safresh1indicating the case significance when comparing file specifications. 866fb12b70Safresh1Since XP FS_CASE_SENSITIVE is effectively disabled for the NT subsubsystem. 8756d68f1eSafresh1See L<http://cygwin.com/ml/cygwin/2007-07/msg00891.html> 886fb12b70Safresh1Default: 1 896fb12b70Safresh1 906fb12b70Safresh1=cut 916fb12b70Safresh1 926fb12b70Safresh1sub case_tolerant { 930b7734b3Safresh1 eval { 940b7734b3Safresh1 local @INC = @INC; 950b7734b3Safresh1 pop @INC if $INC[-1] eq '.'; 960b7734b3Safresh1 require Win32API::File; 970b7734b3Safresh1 } or return 1; 986fb12b70Safresh1 my $drive = shift || "C:"; 996fb12b70Safresh1 my $osFsType = "\0"x256; 1006fb12b70Safresh1 my $osVolName = "\0"x256; 1016fb12b70Safresh1 my $ouFsFlags = 0; 1026fb12b70Safresh1 Win32API::File::GetVolumeInformation($drive, $osVolName, 256, [], [], $ouFsFlags, $osFsType, 256 ); 1036fb12b70Safresh1 if ($ouFsFlags & Win32API::File::FS_CASE_SENSITIVE()) { return 0; } 1046fb12b70Safresh1 else { return 1; } 1056fb12b70Safresh1} 1066fb12b70Safresh1 1076fb12b70Safresh1=item file_name_is_absolute 1086fb12b70Safresh1 1096fb12b70Safresh1As of right now, this returns 2 if the path is absolute with a 1106fb12b70Safresh1volume, 1 if it's absolute with no volume, 0 otherwise. 1116fb12b70Safresh1 1126fb12b70Safresh1=cut 1136fb12b70Safresh1 1146fb12b70Safresh1sub file_name_is_absolute { 1156fb12b70Safresh1 1166fb12b70Safresh1 my ($self,$file) = @_; 1176fb12b70Safresh1 1186fb12b70Safresh1 if ($file =~ m{^($VOL_RX)}o) { 1196fb12b70Safresh1 my $vol = $1; 1206fb12b70Safresh1 return ($vol =~ m{^$UNC_RX}o ? 2 1216fb12b70Safresh1 : $file =~ m{^$DRIVE_RX[\\/]}o ? 2 1226fb12b70Safresh1 : 0); 1236fb12b70Safresh1 } 1246fb12b70Safresh1 return $file =~ m{^[\\/]} ? 1 : 0; 1256fb12b70Safresh1} 1266fb12b70Safresh1 1276fb12b70Safresh1=item catfile 1286fb12b70Safresh1 1296fb12b70Safresh1Concatenate one or more directory names and a filename to form a 1306fb12b70Safresh1complete path ending with a filename 1316fb12b70Safresh1 1326fb12b70Safresh1=cut 1336fb12b70Safresh1 1346fb12b70Safresh1sub catfile { 1356fb12b70Safresh1 shift; 1366fb12b70Safresh1 1376fb12b70Safresh1 # Legacy / compatibility support 1386fb12b70Safresh1 # 1396fb12b70Safresh1 shift, return _canon_cat( "/", @_ ) 140b46d8ef2Safresh1 if !@_ || $_[0] eq ""; 1416fb12b70Safresh1 1426fb12b70Safresh1 # Compatibility with File::Spec <= 3.26: 1436fb12b70Safresh1 # catfile('A:', 'foo') should return 'A:\foo'. 1446fb12b70Safresh1 return _canon_cat( ($_[0].'\\'), @_[1..$#_] ) 1456fb12b70Safresh1 if $_[0] =~ m{^$DRIVE_RX\z}o; 1466fb12b70Safresh1 1476fb12b70Safresh1 return _canon_cat( @_ ); 1486fb12b70Safresh1} 1496fb12b70Safresh1 1506fb12b70Safresh1sub catdir { 1516fb12b70Safresh1 shift; 1526fb12b70Safresh1 1536fb12b70Safresh1 # Legacy / compatibility support 1546fb12b70Safresh1 # 1556fb12b70Safresh1 return "" 1566fb12b70Safresh1 unless @_; 1576fb12b70Safresh1 shift, return _canon_cat( "/", @_ ) 1586fb12b70Safresh1 if $_[0] eq ""; 1596fb12b70Safresh1 1606fb12b70Safresh1 # Compatibility with File::Spec <= 3.26: 1616fb12b70Safresh1 # catdir('A:', 'foo') should return 'A:\foo'. 1626fb12b70Safresh1 return _canon_cat( ($_[0].'\\'), @_[1..$#_] ) 1636fb12b70Safresh1 if $_[0] =~ m{^$DRIVE_RX\z}o; 1646fb12b70Safresh1 1656fb12b70Safresh1 return _canon_cat( @_ ); 1666fb12b70Safresh1} 1676fb12b70Safresh1 1686fb12b70Safresh1sub path { 1696fb12b70Safresh1 my @path = split(';', $ENV{PATH}); 1706fb12b70Safresh1 s/"//g for @path; 1716fb12b70Safresh1 @path = grep length, @path; 1726fb12b70Safresh1 unshift(@path, "."); 1736fb12b70Safresh1 return @path; 1746fb12b70Safresh1} 1756fb12b70Safresh1 1766fb12b70Safresh1=item canonpath 1776fb12b70Safresh1 1786fb12b70Safresh1No physical check on the filesystem, but a logical cleanup of a 1796fb12b70Safresh1path. On UNIX eliminated successive slashes and successive "/.". 1806fb12b70Safresh1On Win32 makes 1816fb12b70Safresh1 1826fb12b70Safresh1 dir1\dir2\dir3\..\..\dir4 -> \dir\dir4 and even 1836fb12b70Safresh1 dir1\dir2\dir3\...\dir4 -> \dir\dir4 1846fb12b70Safresh1 1856fb12b70Safresh1=cut 1866fb12b70Safresh1 1876fb12b70Safresh1sub canonpath { 1886fb12b70Safresh1 # Legacy / compatibility support 1896fb12b70Safresh1 # 1906fb12b70Safresh1 return $_[1] if !defined($_[1]) or $_[1] eq ''; 1916fb12b70Safresh1 return _canon_cat( $_[1] ); 1926fb12b70Safresh1} 1936fb12b70Safresh1 1946fb12b70Safresh1=item splitpath 1956fb12b70Safresh1 1966fb12b70Safresh1 ($volume,$directories,$file) = File::Spec->splitpath( $path ); 1976fb12b70Safresh1 ($volume,$directories,$file) = File::Spec->splitpath( $path, 1986fb12b70Safresh1 $no_file ); 1996fb12b70Safresh1 2006fb12b70Safresh1Splits a path into volume, directory, and filename portions. Assumes that 2016fb12b70Safresh1the last file is a path unless the path ends in '\\', '\\.', '\\..' 2026fb12b70Safresh1or $no_file is true. On Win32 this means that $no_file true makes this return 2036fb12b70Safresh1( $volume, $path, '' ). 2046fb12b70Safresh1 2056fb12b70Safresh1Separators accepted are \ and /. 2066fb12b70Safresh1 2076fb12b70Safresh1Volumes can be drive letters or UNC sharenames (\\server\share). 2086fb12b70Safresh1 2096fb12b70Safresh1The results can be passed to L</catpath> to get back a path equivalent to 2106fb12b70Safresh1(usually identical to) the original path. 2116fb12b70Safresh1 2126fb12b70Safresh1=cut 2136fb12b70Safresh1 2146fb12b70Safresh1sub splitpath { 2156fb12b70Safresh1 my ($self,$path, $nofile) = @_; 2166fb12b70Safresh1 my ($volume,$directory,$file) = ('','',''); 2176fb12b70Safresh1 if ( $nofile ) { 2186fb12b70Safresh1 $path =~ 2196fb12b70Safresh1 m{^ ( $VOL_RX ? ) (.*) }sox; 2206fb12b70Safresh1 $volume = $1; 2216fb12b70Safresh1 $directory = $2; 2226fb12b70Safresh1 } 2236fb12b70Safresh1 else { 2246fb12b70Safresh1 $path =~ 2256fb12b70Safresh1 m{^ ( $VOL_RX ? ) 2266fb12b70Safresh1 ( (?:.*[\\/](?:\.\.?\Z(?!\n))?)? ) 2276fb12b70Safresh1 (.*) 2286fb12b70Safresh1 }sox; 2296fb12b70Safresh1 $volume = $1; 2306fb12b70Safresh1 $directory = $2; 2316fb12b70Safresh1 $file = $3; 2326fb12b70Safresh1 } 2336fb12b70Safresh1 2346fb12b70Safresh1 return ($volume,$directory,$file); 2356fb12b70Safresh1} 2366fb12b70Safresh1 2376fb12b70Safresh1 2386fb12b70Safresh1=item splitdir 2396fb12b70Safresh1 2406fb12b70Safresh1The opposite of L<catdir()|File::Spec/catdir>. 2416fb12b70Safresh1 2426fb12b70Safresh1 @dirs = File::Spec->splitdir( $directories ); 2436fb12b70Safresh1 2446fb12b70Safresh1$directories must be only the directory portion of the path on systems 2456fb12b70Safresh1that have the concept of a volume or that have path syntax that differentiates 2466fb12b70Safresh1files from directories. 2476fb12b70Safresh1 2486fb12b70Safresh1Unlike just splitting the directories on the separator, leading empty and 2496fb12b70Safresh1trailing directory entries can be returned, because these are significant 2506fb12b70Safresh1on some OSs. So, 2516fb12b70Safresh1 252*3d61058aSafresh1 File::Spec->splitdir( "/a/b//c/" ); 2536fb12b70Safresh1 2546fb12b70Safresh1Yields: 2556fb12b70Safresh1 2566fb12b70Safresh1 ( '', 'a', 'b', '', 'c', '' ) 2576fb12b70Safresh1 2586fb12b70Safresh1=cut 2596fb12b70Safresh1 2606fb12b70Safresh1sub splitdir { 2616fb12b70Safresh1 my ($self,$directories) = @_ ; 2626fb12b70Safresh1 # 2636fb12b70Safresh1 # split() likes to forget about trailing null fields, so here we 2646fb12b70Safresh1 # check to be sure that there will not be any before handling the 2656fb12b70Safresh1 # simple case. 2666fb12b70Safresh1 # 2676fb12b70Safresh1 if ( $directories !~ m|[\\/]\Z(?!\n)| ) { 2686fb12b70Safresh1 return split( m|[\\/]|, $directories ); 2696fb12b70Safresh1 } 2706fb12b70Safresh1 else { 2716fb12b70Safresh1 # 2726fb12b70Safresh1 # since there was a trailing separator, add a file name to the end, 2736fb12b70Safresh1 # then do the split, then replace it with ''. 2746fb12b70Safresh1 # 2756fb12b70Safresh1 my( @directories )= split( m|[\\/]|, "${directories}dummy" ) ; 2766fb12b70Safresh1 $directories[ $#directories ]= '' ; 2776fb12b70Safresh1 return @directories ; 2786fb12b70Safresh1 } 2796fb12b70Safresh1} 2806fb12b70Safresh1 2816fb12b70Safresh1 2826fb12b70Safresh1=item catpath 2836fb12b70Safresh1 2846fb12b70Safresh1Takes volume, directory and file portions and returns an entire path. Under 2856fb12b70Safresh1Unix, $volume is ignored, and this is just like catfile(). On other OSs, 2866fb12b70Safresh1the $volume become significant. 2876fb12b70Safresh1 2886fb12b70Safresh1=cut 2896fb12b70Safresh1 2906fb12b70Safresh1sub catpath { 2916fb12b70Safresh1 my ($self,$volume,$directory,$file) = @_; 2926fb12b70Safresh1 2936fb12b70Safresh1 # If it's UNC, make sure the glue separator is there, reusing 2946fb12b70Safresh1 # whatever separator is first in the $volume 2956fb12b70Safresh1 my $v; 2966fb12b70Safresh1 $volume .= $v 2976fb12b70Safresh1 if ( (($v) = $volume =~ m@^([\\/])[\\/][^\\/]+[\\/][^\\/]+\Z(?!\n)@s) && 2986fb12b70Safresh1 $directory =~ m@^[^\\/]@s 2996fb12b70Safresh1 ) ; 3006fb12b70Safresh1 3016fb12b70Safresh1 $volume .= $directory ; 3026fb12b70Safresh1 3036fb12b70Safresh1 # If the volume is not just A:, make sure the glue separator is 3046fb12b70Safresh1 # there, reusing whatever separator is first in the $volume if possible. 3056fb12b70Safresh1 if ( $volume !~ m@^[a-zA-Z]:\Z(?!\n)@s && 3066fb12b70Safresh1 $volume =~ m@[^\\/]\Z(?!\n)@ && 3076fb12b70Safresh1 $file =~ m@[^\\/]@ 3086fb12b70Safresh1 ) { 3096fb12b70Safresh1 $volume =~ m@([\\/])@ ; 3106fb12b70Safresh1 my $sep = $1 ? $1 : '\\' ; 3116fb12b70Safresh1 $volume .= $sep ; 3126fb12b70Safresh1 } 3136fb12b70Safresh1 3146fb12b70Safresh1 $volume .= $file ; 3156fb12b70Safresh1 3166fb12b70Safresh1 return $volume ; 3176fb12b70Safresh1} 3186fb12b70Safresh1 3196fb12b70Safresh1sub _same { 3206fb12b70Safresh1 lc($_[1]) eq lc($_[2]); 3216fb12b70Safresh1} 3226fb12b70Safresh1 3236fb12b70Safresh1sub rel2abs { 3246fb12b70Safresh1 my ($self,$path,$base ) = @_; 3256fb12b70Safresh1 3266fb12b70Safresh1 my $is_abs = $self->file_name_is_absolute($path); 3276fb12b70Safresh1 3286fb12b70Safresh1 # Check for volume (should probably document the '2' thing...) 3296fb12b70Safresh1 return $self->canonpath( $path ) if $is_abs == 2; 3306fb12b70Safresh1 3316fb12b70Safresh1 if ($is_abs) { 3326fb12b70Safresh1 # It's missing a volume, add one 3339f11ffb7Safresh1 my $vol = ($self->splitpath( Cwd::getcwd() ))[0]; 3346fb12b70Safresh1 return $self->canonpath( $vol . $path ); 3356fb12b70Safresh1 } 3366fb12b70Safresh1 3376fb12b70Safresh1 if ( !defined( $base ) || $base eq '' ) { 3386fb12b70Safresh1 $base = Cwd::getdcwd( ($self->splitpath( $path ))[0] ) if defined &Cwd::getdcwd ; 3399f11ffb7Safresh1 $base = Cwd::getcwd() unless defined $base ; 3406fb12b70Safresh1 } 3416fb12b70Safresh1 elsif ( ! $self->file_name_is_absolute( $base ) ) { 3426fb12b70Safresh1 $base = $self->rel2abs( $base ) ; 3436fb12b70Safresh1 } 3446fb12b70Safresh1 else { 3456fb12b70Safresh1 $base = $self->canonpath( $base ) ; 3466fb12b70Safresh1 } 3476fb12b70Safresh1 3486fb12b70Safresh1 my ( $path_directories, $path_file ) = 3496fb12b70Safresh1 ($self->splitpath( $path, 1 ))[1,2] ; 3506fb12b70Safresh1 3516fb12b70Safresh1 my ( $base_volume, $base_directories ) = 3526fb12b70Safresh1 $self->splitpath( $base, 1 ) ; 3536fb12b70Safresh1 3546fb12b70Safresh1 $path = $self->catpath( 3556fb12b70Safresh1 $base_volume, 3566fb12b70Safresh1 $self->catdir( $base_directories, $path_directories ), 3576fb12b70Safresh1 $path_file 3586fb12b70Safresh1 ) ; 3596fb12b70Safresh1 3606fb12b70Safresh1 return $self->canonpath( $path ) ; 3616fb12b70Safresh1} 3626fb12b70Safresh1 3636fb12b70Safresh1=back 3646fb12b70Safresh1 3656fb12b70Safresh1=head2 Note For File::Spec::Win32 Maintainers 3666fb12b70Safresh1 3676fb12b70Safresh1Novell NetWare inherits its File::Spec behaviour from File::Spec::Win32. 3686fb12b70Safresh1 3696fb12b70Safresh1=head1 COPYRIGHT 3706fb12b70Safresh1 3716fb12b70Safresh1Copyright (c) 2004,2007 by the Perl 5 Porters. All rights reserved. 3726fb12b70Safresh1 3736fb12b70Safresh1This program is free software; you can redistribute it and/or modify 3746fb12b70Safresh1it under the same terms as Perl itself. 3756fb12b70Safresh1 3766fb12b70Safresh1=head1 SEE ALSO 3776fb12b70Safresh1 3786fb12b70Safresh1See L<File::Spec> and L<File::Spec::Unix>. This package overrides the 3796fb12b70Safresh1implementation of these methods, not the semantics. 3806fb12b70Safresh1 3816fb12b70Safresh1=cut 3826fb12b70Safresh1 3836fb12b70Safresh1 3846fb12b70Safresh1sub _canon_cat # @path -> path 3856fb12b70Safresh1{ 3866fb12b70Safresh1 my ($first, @rest) = @_; 3876fb12b70Safresh1 3886fb12b70Safresh1 my $volume = $first =~ s{ \A ([A-Za-z]:) ([\\/]?) }{}x # drive letter 3896fb12b70Safresh1 ? ucfirst( $1 ).( $2 ? "\\" : "" ) 3906fb12b70Safresh1 : $first =~ s{ \A (?:\\\\|//) ([^\\/]+) 3916fb12b70Safresh1 (?: [\\/] ([^\\/]+) )? 3926fb12b70Safresh1 [\\/]? }{}xs # UNC volume 3936fb12b70Safresh1 ? "\\\\$1".( defined $2 ? "\\$2" : "" )."\\" 3946fb12b70Safresh1 : $first =~ s{ \A [\\/] }{}x # root dir 3956fb12b70Safresh1 ? "\\" 3966fb12b70Safresh1 : ""; 3976fb12b70Safresh1 my $path = join "\\", $first, @rest; 3986fb12b70Safresh1 3996fb12b70Safresh1 $path =~ tr#\\/#\\\\#s; # xx/yy --> xx\yy & xx\\yy --> xx\yy 4006fb12b70Safresh1 4016fb12b70Safresh1 # xx/././yy --> xx/yy 4026fb12b70Safresh1 $path =~ s{(?: 4036fb12b70Safresh1 (?:\A|\\) # at begin or after a slash 4046fb12b70Safresh1 \. 4056fb12b70Safresh1 (?:\\\.)* # and more 4066fb12b70Safresh1 (?:\\|\z) # at end or followed by slash 4076fb12b70Safresh1 )+ # performance boost -- I do not know why 4086fb12b70Safresh1 }{\\}gx; 4096fb12b70Safresh1 4106fb12b70Safresh1 # xx\yy\..\zz --> xx\zz 4116fb12b70Safresh1 while ( $path =~ s{(?: 4126fb12b70Safresh1 (?:\A|\\) # at begin or after a slash 4136fb12b70Safresh1 [^\\]+ # rip this 'yy' off 4146fb12b70Safresh1 \\\.\. 4156fb12b70Safresh1 (?<!\A\.\.\\\.\.) # do *not* replace ^..\.. 4166fb12b70Safresh1 (?<!\\\.\.\\\.\.) # do *not* replace \..\.. 4176fb12b70Safresh1 (?:\\|\z) # at end or followed by slash 4186fb12b70Safresh1 )+ # performance boost -- I do not know why 4196fb12b70Safresh1 }{\\}sx ) {} 4206fb12b70Safresh1 4216fb12b70Safresh1 $path =~ s#\A\\##; # \xx --> xx NOTE: this is *not* root 4226fb12b70Safresh1 $path =~ s#\\\z##; # xx\ --> xx 4236fb12b70Safresh1 4246fb12b70Safresh1 if ( $volume =~ m#\\\z# ) 4256fb12b70Safresh1 { # <vol>\.. --> <vol>\ 4266fb12b70Safresh1 $path =~ s{ \A # at begin 4276fb12b70Safresh1 \.\. 4286fb12b70Safresh1 (?:\\\.\.)* # and more 4296fb12b70Safresh1 (?:\\|\z) # at end or followed by slash 4306fb12b70Safresh1 }{}x; 4316fb12b70Safresh1 4326fb12b70Safresh1 return $1 # \\HOST\SHARE\ --> \\HOST\SHARE 4336fb12b70Safresh1 if $path eq "" 4346fb12b70Safresh1 and $volume =~ m#\A(\\\\.*)\\\z#s; 4356fb12b70Safresh1 } 4366fb12b70Safresh1 return $path ne "" || $volume ? $volume.$path : "."; 4376fb12b70Safresh1} 4386fb12b70Safresh1 4396fb12b70Safresh11; 440