Change 33572 by [EMAIL PROTECTED] on 2008/03/26 12:45:28
Integrate:
[ 33332]
Subject: [PATCH] consting for .c files in tests
From: "Robin Barker" <[EMAIL PROTECTED]>
Date: Mon, 18 Feb 2008 13:43:56 -0000
Message-ID: <[EMAIL PROTECTED]>
[ 33386]
Subject: Fwd: CPAN Upload: Y/YV/YVES/ExtUtils-Install-1.45.tar.gz
From: demerphq <[EMAIL PROTECTED]>
Date: Wed, 27 Feb 2008 14:06:29 +0100
Message-ID: <[EMAIL PROTECTED]>
Upgrade to ExtUtils-Install-1.45 to fix [cpan #32813]
[ 33404]
Synchronize blead with changes from ExtUtils::Install 1.46
Apply patches from Michael Schwern (rt #33688, rt #31429, rt #31248)
and from Slaven Rezic (rt #33290). Also implemented the suggestion from
Schwern about not dieing when failing to remove a shadow file that is
later on in INC than the installed version. (rt #2928)
[ 33410]
Update ExtUtils::Install to release 1.47
[ 33460]
Upgrade to ExtUtils-Install-1.50
[ 33566]
Subject: RE: [PATCH revised] Fix ExtUtils::Install under Cygwin
From: "Steve Hay" <[EMAIL PROTECTED]>
Message-ID: <[EMAIL PROTECTED]>
Date: Mon, 17 Mar 2008 14:36:54 -0000
"OK, so how about the attached. This fixes up -w for all compilers so
that it is symmetrical with chmod(), and adds a note to perltodo on
fixing POSIX::access() and chdir()."
The whole long thread started here:
http://www.xray.mpe.mpg.de/mailing-lists/perl5-porters/2008-03/msg00056.html
[ 33567]
Patches for VMS by Craig Berry from
http://rt.cpan.org/Public/Bug/Display.html?id=34095
(1.50 has 3 failures on VMS)
Affected files ...
... //depot/maint-5.10/perl/MANIFEST#15 integrate
... //depot/maint-5.10/perl/lib/ExtUtils/Install.pm#2 integrate
... //depot/maint-5.10/perl/lib/ExtUtils/t/Embed.t#3 integrate
... //depot/maint-5.10/perl/lib/ExtUtils/t/Install.t#2 integrate
... //depot/maint-5.10/perl/lib/ExtUtils/t/Installapi2.t#1 branch
... //depot/maint-5.10/perl/lib/ExtUtils/t/can_write_dir.t#1 branch
... //depot/maint-5.10/perl/pod/perlport.pod#3 integrate
... //depot/maint-5.10/perl/pod/perltodo.pod#4 integrate
... //depot/maint-5.10/perl/win32/win32.c#3 integrate
Differences ...
==== //depot/maint-5.10/perl/MANIFEST#15 (text) ====
Index: perl/MANIFEST
--- perl/MANIFEST#14~33529~ 2008-03-14 04:50:59.000000000 -0700
+++ perl/MANIFEST 2008-03-26 05:45:28.000000000 -0700
@@ -1797,6 +1797,7 @@
lib/ExtUtils/t/basic.t See if MakeMaker can build a module
lib/ExtUtils/t/build_man.t Set if MakeMaker builds manpages
lib/ExtUtils/t/bytes.t Test ExtUtils::MakeMaker::bytes
+lib/ExtUtils/t/can_write_dir.t Does the _can_write_dir function of
ExtUtils::Install work properly?
lib/ExtUtils/t/cd.t Test to see cd works
lib/ExtUtils/t/config.t Test ExtUtils::MakeMaker::Config
lib/ExtUtils/t/Constant.t See if ExtUtils::Constant works
@@ -1810,6 +1811,7 @@
lib/ExtUtils/t/INSTALL_BASE.t Test INSTALL_BASE in MakeMaker
lib/ExtUtils/t/Installed.t See if ExtUtils::Installed works
lib/ExtUtils/t/Install.t See if ExtUtils::Install works
+lib/ExtUtils/t/Installapi2.t See if new api for ExtUtils::Install::install()
works
lib/ExtUtils/t/INST_PREFIX.t See if MakeMaker can apply PREFIXs
lib/ExtUtils/t/INST.t Check MakeMaker INST_* macros
lib/ExtUtils/t/Liblist.t See if ExtUtils::Liblist works
==== //depot/maint-5.10/perl/lib/ExtUtils/Install.pm#2 (text) ====
Index: perl/lib/ExtUtils/Install.pm
--- perl/lib/ExtUtils/Install.pm#1~32694~ 2007-12-22 01:23:09.000000000
-0800
+++ perl/lib/ExtUtils/Install.pm 2008-03-26 05:45:28.000000000 -0700
@@ -1,10 +1,7 @@
package ExtUtils::Install;
-use 5.00503;
use strict;
use vars qw(@ISA @EXPORT $VERSION $MUST_REBOOT %Config);
-$VERSION = '1.44';
-$VERSION = eval $VERSION;
use AutoSplit;
use Carp ();
@@ -23,6 +20,8 @@
@ISA = ('Exporter');
@EXPORT = ('install','uninstall','pm_to_blib', 'install_default');
+=pod
+
=head1 NAME
ExtUtils::Install - install files from here to there
@@ -36,6 +35,17 @@
uninstall($packlist);
pm_to_blib({ 'lib/Foo/Bar.pm' => 'blib/lib/Foo/Bar.pm' });
+
+=head1 VERSION
+
+1.51
+
+=cut
+
+$VERSION = '1.50_01';
+$VERSION = eval $VERSION;
+
+=pod
=head1 DESCRIPTION
@@ -238,8 +248,9 @@
my ( $file, $tryhard, $installing )= @_;
_chmod( 0666, $file );
- unlink $file
- and return $file;
+ my $unlink_count = 0;
+ while (unlink $file) { $unlink_count++; }
+ return $file if $unlink_count > 0;
my $error="$!";
_choke("Cannot unlink '$file': $!")
@@ -272,58 +283,10 @@
}
+=pod
=head2 Functions
-=over 4
-
-=item B<install>
-
- install(\%from_to);
- install(\%from_to, $verbose, $dont_execute, $uninstall_shadows, $skip);
-
-Copies each directory tree of %from_to to its corresponding value
-preserving timestamps and permissions.
-
-There are two keys with a special meaning in the hash: "read" and
-"write". These contain packlist files. After the copying is done,
-install() will write the list of target files to $from_to{write}. If
-$from_to{read} is given the contents of this file will be merged into
-the written file. The read and the written file may be identical, but
-on AFS it is quite likely that people are installing to a different
-directory than the one where the files later appear.
-
-If $verbose is true, will print out each file removed. Default is
-false. This is "make install VERBINST=1". $verbose values going
-up to 5 show increasingly more diagnostics output.
-
-If $dont_execute is true it will only print what it was going to do
-without actually doing it. Default is false.
-
-If $uninstall_shadows is true any differing versions throughout @INC
-will be uninstalled. This is "make install UNINST=1"
-
-As of 1.37_02 install() supports the use of a list of patterns to filter
-out files that shouldn't be installed. If $skip is omitted or undefined
-then install will try to read the list from INSTALL.SKIP in the CWD.
-This file is a list of regular expressions and is just like the
-MANIFEST.SKIP file used by L<ExtUtils::Manifest>.
-
-A default site INSTALL.SKIP may be provided by setting then environment
-variable EU_INSTALL_SITE_SKIPFILE, this will only be used when there
-isn't a distribution specific INSTALL.SKIP. If the environment variable
-EU_INSTALL_IGNORE_SKIP is true then no install file filtering will be
-performed.
-
-If $skip is undefined then the skip file will be autodetected and used if it
-is found. If $skip is a reference to an array then it is assumed
-the array contains the list of patterns, if $skip is a true non reference it is
-assumed to be the filename holding the list of patterns, any other value of
-$skip is taken to mean that no install filtering should occur.
-
-
-=cut
-
=begin _private
=item _get_install_skip
@@ -383,19 +346,21 @@
return $skip
}
+=pod
+
=item _have_write_access
Abstract a -w check that tries to use POSIX::access() if possible.
=cut
-
{
my $has_posix;
sub _have_write_access {
my $dir=shift;
- if (!defined $has_posix) {
- $has_posix=eval "local $^W; require POSIX; 1" || 0;
+ unless (defined $has_posix) {
+ $has_posix= (!$Is_cygwin && !$Is_Win32
+ && eval 'local $^W; require POSIX; 1') || 0;
}
if ($has_posix) {
return POSIX::access($dir, POSIX::W_OK());
@@ -405,6 +370,7 @@
}
}
+=pod
=item _can_write_dir(C<$dir>)
@@ -431,12 +397,22 @@
return
unless defined $dir and length $dir;
- my ($vol, $dirs, $file) =
File::Spec->splitpath(File::Spec->rel2abs($dir),1);
+ my ($vol, $dirs, $file) = File::Spec->splitpath($dir,1);
my @dirs = File::Spec->splitdir($dirs);
+ unshift @dirs, File::Spec->curdir
+ unless File::Spec->file_name_is_absolute($dir);
+
my $path='';
my @make;
while (@dirs) {
- $dir = File::Spec->catdir($vol,@dirs);
+ if ($Is_VMS) {
+ $dir = File::Spec->catdir($vol,@dirs);
+ }
+ else {
+ $dir = File::Spec->catdir(@dirs);
+ $dir = File::Spec->catpath($vol,$dir,'')
+ if defined $vol and length $vol;
+ }
next if ( $dir eq $path );
if ( ! -e $dir ) {
unshift @make,$dir;
@@ -453,29 +429,31 @@
return 0;
}
-=item _mkpath($dir,$show,$mode,$verbose,$fake)
+=pod
+
+=item _mkpath($dir,$show,$mode,$verbose,$dry_run)
Wrapper around File::Path::mkpath() to handle errors.
If $verbose is true and >1 then additional diagnostics will be produced, also
this will force $show to true.
-If $fake is true then the directory will not be created but a check will be
+If $dry_run is true then the directory will not be created but a check will be
made to see whether it would be possible to write to the directory, or that
it would be possible to create the directory.
-If $fake is not true dies if the directory can not be created or is not
+If $dry_run is not true dies if the directory can not be created or is not
writable.
=cut
sub _mkpath {
- my ($dir,$show,$mode,$verbose,$fake)[EMAIL PROTECTED];
+ my ($dir,$show,$mode,$verbose,$dry_run)[EMAIL PROTECTED];
if ( $verbose && $verbose > 1 && ! -d $dir) {
$show= 1;
printf "mkpath(%s,%d,%#o)\n", $dir, $show, $mode;
}
- if (!$fake) {
+ if (!$dry_run) {
if ( ! eval { File::Path::mkpath($dir,$show,$mode); 1 } ) {
_choke("Can't create '$dir'","$@");
}
@@ -488,23 +466,26 @@
$root ? "Do not have write permissions on '$root'"
: "Unknown Error"
);
- if ($fake) {
+ if ($dry_run) {
_warnonce @msg;
} else {
_choke @msg;
}
- } elsif ($show and $fake) {
+ } elsif ($show and $dry_run) {
print "$_\n" for @make;
}
+
}
-=item _copy($from,$to,$verbose,$fake)
+=pod
+
+=item _copy($from,$to,$verbose,$dry_run)
Wrapper around File::Copy::copy to handle errors.
If $verbose is true and >1 then additional dignostics will be emitted.
-If $fake is true then the copy will not actually occur.
+If $dry_run is true then the copy will not actually occur.
Dies if the copy fails.
@@ -512,16 +493,18 @@
sub _copy {
- my ( $from, $to, $verbose, $nonono)[EMAIL PROTECTED];
+ my ( $from, $to, $verbose, $dry_run)[EMAIL PROTECTED];
if ($verbose && $verbose>1) {
printf "copy(%s,%s)\n", $from, $to;
}
- if (!$nonono) {
+ if (!$dry_run) {
File::Copy::copy($from,$to)
or Carp::croak( _estr "ERROR: Cannot copy '$from' to '$to': $!" );
}
}
+=pod
+
=item _chdir($from)
Wrapper around chdir to catch errors.
@@ -543,16 +526,149 @@
return $ret;
}
+=pod
+
=end _private
+=over 4
+
+=item B<install>
+
+ # deprecated forms
+ install(\%from_to);
+ install(\%from_to, $verbose, $dry_run, $uninstall_shadows,
+ $skip, $always_copy, \%result);
+
+ # recommended form as of 1.47
+ install([
+ from_to => \%from_to,
+ verbose => 1,
+ dry_run => 0,
+ uninstall_shadows => 1,
+ skip => undef,
+ always_copy => 1,
+ result => \%install_results,
+ ]);
+
+
+Copies each directory tree of %from_to to its corresponding value
+preserving timestamps and permissions.
+
+There are two keys with a special meaning in the hash: "read" and
+"write". These contain packlist files. After the copying is done,
+install() will write the list of target files to $from_to{write}. If
+$from_to{read} is given the contents of this file will be merged into
+the written file. The read and the written file may be identical, but
+on AFS it is quite likely that people are installing to a different
+directory than the one where the files later appear.
+
+If $verbose is true, will print out each file removed. Default is
+false. This is "make install VERBINST=1". $verbose values going
+up to 5 show increasingly more diagnostics output.
+
+If $dry_run is true it will only print what it was going to do
+without actually doing it. Default is false.
+
+If $uninstall_shadows is true any differing versions throughout @INC
+will be uninstalled. This is "make install UNINST=1"
+
+As of 1.37_02 install() supports the use of a list of patterns to filter out
+files that shouldn't be installed. If $skip is omitted or undefined then
+install will try to read the list from INSTALL.SKIP in the CWD. This file is
+a list of regular expressions and is just like the MANIFEST.SKIP file used
+by L<ExtUtils::Manifest>.
+
+A default site INSTALL.SKIP may be provided by setting then environment
+variable EU_INSTALL_SITE_SKIPFILE, this will only be used when there isn't a
+distribution specific INSTALL.SKIP. If the environment variable
+EU_INSTALL_IGNORE_SKIP is true then no install file filtering will be
+performed.
+
+If $skip is undefined then the skip file will be autodetected and used if it
+is found. If $skip is a reference to an array then it is assumed the array
+contains the list of patterns, if $skip is a true non reference it is
+assumed to be the filename holding the list of patterns, any other value of
+$skip is taken to mean that no install filtering should occur.
+
+B<Changes As of Version 1.47>
+
+As of version 1.47 the following additions were made to the install interface.
+Note that the new argument style and use of the %result hash is recommended.
+
+The $always_copy parameter which when true causes files to be updated
+regardles as to whether they have changed, if it is defined but false then
+copies are made only if the files have changed, if it is undefined then the
+value of the environment variable EU_INSTALL_ALWAYS_COPY is used as default.
+
+The %result hash will be populated with the various keys/subhashes reflecting
+the install. Currently these keys and their structure are:
+
+ install => { $target => $source },
+ install_fail => { $target => $source },
+ install_unchanged => { $target => $source },
+
+ install_filtered => { $source => $pattern },
+
+ uninstall => { $uninstalled => $source },
+ uninstall_fail => { $uninstalled => $source },
+
+where C<$source> is the filespec of the file being installed. C<$target> is
where
+it is being installed to, and C<$uninstalled> is any shadow file that is in
C<@INC>
+or C<$ENV{PERL5LIB}> or other standard locations, and C<$pattern> is the
pattern that
+caused a source file to be skipped. In future more keys will be added, such as
to
+show created directories, however this requires changes in other modules and
must
+therefore wait.
+
+These keys will be populated before any exceptions are thrown should there be
an
+error.
+
+Note that all updates of the %result are additive, the hash will not be
+cleared before use, thus allowing status results of many installs to be easily
+aggregated.
+
+B<NEW ARGUMENT STYLE>
+
+If there is only one argument and it is a reference to an array then
+the array is assumed to contain a list of key-value pairs specifying
+the options. In this case the option "from_to" is mandatory. This style
+means that you dont have to supply a cryptic list of arguments and can
+use a self documenting argument list that is easier to understand.
+
+This is now the recommended interface to install().
+
+B<RETURN>
+
+If all actions were successful install will return a hashref of the results
+as described above for the $result parameter. If any action is a failure
+then install will die, therefore it is recommended to pass in the $result
+parameter instead of using the return value. If the result parameter is
+provided then the returned hashref will be the passed in hashref.
+
=cut
sub install { #XXX OS-SPECIFIC
- my($from_to,$verbose,$nonono,$inc_uninstall,$skip) = @_;
+
my($from_to,$verbose,$dry_run,$uninstall_shadows,$skip,$always_copy,$result) =
@_;
+ if (@_==1 and eval { [EMAIL PROTECTED] }) {
+ my %opts = @$from_to;
+ $from_to = $opts{from_to}
+ or Carp::confess("from_to is a mandatory
parameter");
+ $verbose = $opts{verbose};
+ $dry_run = $opts{dry_run};
+ $uninstall_shadows = $opts{uninstall_shadows};
+ $skip = $opts{skip};
+ $always_copy = $opts{always_copy};
+ $result = $opts{result};
+ }
+
+ $result ||= {};
$verbose ||= 0;
- $nonono ||= 0;
+ $dry_run ||= 0;
$skip= _get_install_skip($skip,$verbose);
+ $always_copy = $ENV{EU_INSTALL_ALWAYS_COPY}
+ || $ENV{EU_ALWAYS_COPY}
+ || 0
+ unless defined $always_copy;
my(%from_to) = %$from_to;
my(%pack, $dir, %warned);
@@ -614,6 +730,7 @@
if ( $sourcefile=~/$pat/ ) {
print "Skipping $targetfile (filtered)\n"
if $verbose>1;
+ $result->{install_filtered}{$sourcefile} = $pat;
return;
}
}
@@ -621,11 +738,12 @@
# and because the target is relative
my $save_cwd = _chdir($cwd);
my $diff = 0;
- if ( -f $targetfile && -s _ == $size) {
- # We have a good chance, we can skip this one
- $diff = compare($sourcefile, $targetfile);
- } else {
+ # XXX: I wonder how useful this logic is actually -- demerphq
+ if ( $always_copy or !-f $targetfile or -s $targetfile != $size) {
$diff++;
+ } else {
+ # we might not need to copy this file
+ $diff = compare($sourcefile, $targetfile);
}
$check_dirs{$targetdir}++
unless -w $targetfile;
@@ -642,9 +760,8 @@
}, $current_directory );
_chdir($cwd);
}
-
foreach my $targetdir (sort keys %check_dirs) {
- _mkpath( $targetdir, 0, 0755, $verbose, $nonono );
+ _mkpath( $targetdir, 0, 0755, $verbose, $dry_run );
}
foreach my $found (@found_files) {
my ($diff, $ffd, $origfile, $mode, $size, $atime, $mtime,
@@ -652,32 +769,44 @@
my $realtarget= $targetfile;
if ($diff) {
- if (-f $targetfile) {
- print "_unlink_or_rename($targetfile)\n" if $verbose>1;
- $targetfile= _unlink_or_rename( $targetfile, 'tryhard',
'install' )
- unless $nonono;
- } elsif ( ! -d $targetdir ) {
- _mkpath( $targetdir, 0, 0755, $verbose, $nonono );
- }
- print "Installing $targetfile\n";
- _copy( $sourcefile, $targetfile, $verbose, $nonono, );
- #XXX OS-SPECIFIC
- print "utime($atime,$mtime,$targetfile)\n" if $verbose>1;
- utime($atime,$mtime + $Is_VMS,$targetfile) unless $nonono>1;
-
-
- $mode = 0444 | ( $mode & 0111 ? 0111 : 0 );
- $mode = $mode | 0222
- if $realtarget ne $targetfile;
- _chmod( $mode, $targetfile, $verbose );
+ eval {
+ if (-f $targetfile) {
+ print "_unlink_or_rename($targetfile)\n" if $verbose>1;
+ $targetfile= _unlink_or_rename( $targetfile, 'tryhard',
'install' )
+ unless $dry_run;
+ } elsif ( ! -d $targetdir ) {
+ _mkpath( $targetdir, 0, 0755, $verbose, $dry_run );
+ }
+ print "Installing $targetfile\n";
+
+ _copy( $sourcefile, $targetfile, $verbose, $dry_run, );
+
+
+ #XXX OS-SPECIFIC
+ print "utime($atime,$mtime,$targetfile)\n" if $verbose>1;
+ utime($atime,$mtime + $Is_VMS,$targetfile) unless $dry_run>1;
+
+
+ $mode = 0444 | ( $mode & 0111 ? 0111 : 0 );
+ $mode = $mode | 0222
+ if $realtarget ne $targetfile;
+ _chmod( $mode, $targetfile, $verbose );
+ $result->{install}{$targetfile} = $sourcefile;
+ 1
+ } or do {
+ $result->{install_fail}{$targetfile} = $sourcefile;
+ die $@;
+ };
} else {
+ $result->{install_unchanged}{$targetfile} = $sourcefile;
print "Skipping $targetfile (unchanged)\n" if $verbose;
}
- if ( $inc_uninstall ) {
+ if ( $uninstall_shadows ) {
inc_uninstall($sourcefile,$ffd, $verbose,
- $nonono,
- $realtarget ne $targetfile ? $realtarget : "");
+ $dry_run,
+ $realtarget ne $targetfile ? $realtarget : "",
+ $result);
}
# Record the full pathname.
@@ -686,12 +815,13 @@
if ($pack{'write'}) {
$dir = install_rooted_dir(dirname($pack{'write'}));
- _mkpath( $dir, 0, 0755, $verbose, $nonono );
+ _mkpath( $dir, 0, 0755, $verbose, $dry_run );
print "Writing $pack{'write'}\n";
- $packlist->write(install_rooted_file($pack{'write'})) unless $nonono;
+ $packlist->write(install_rooted_file($pack{'write'})) unless $dry_run;
}
_do_cleanup($verbose);
+ return $result;
}
=begin _private
@@ -767,7 +897,7 @@
sub forceunlink {
my ( $file, $tryhard )= @_; #XXX OS-SPECIFIC
- _unlink_or_rename( $file, $tryhard );
+ _unlink_or_rename( $file, $tryhard, not("installing") );
}
=begin _undocumented
@@ -794,6 +924,7 @@
return $files;
}
+=pod
=item B<install_default> I<DISCOURAGED>
@@ -857,9 +988,9 @@
=cut
sub uninstall {
- my($fil,$verbose,$nonono) = @_;
+ my($fil,$verbose,$dry_run) = @_;
$verbose ||= 0;
- $nonono ||= 0;
+ $dry_run ||= 0;
die _estr "ERROR: no packlist file found: '$fil'"
unless -f $fil;
@@ -869,40 +1000,53 @@
foreach (sort(keys(%$packlist))) {
chomp;
print "unlink $_\n" if $verbose;
- forceunlink($_,'tryhard') unless $nonono;
+ forceunlink($_,'tryhard') unless $dry_run;
}
print "unlink $fil\n" if $verbose;
- forceunlink($fil, 'tryhard') unless $nonono;
+ forceunlink($fil, 'tryhard') unless $dry_run;
_do_cleanup($verbose);
}
=begin _undocumented
-=item inc_uninstall($filepath,$libdir,$verbose,$nonono,$ignore)
+=item inc_uninstall($filepath,$libdir,$verbose,$dry_run,$ignore,$results)
Remove shadowed files. If $ignore is true then it is assumed to hold
a filename to ignore. This is used to prevent spurious warnings from
occuring when doing an install at reboot.
+We now only die when failing to remove a file that has precedence over
+our own, when our install has precedence we only warn.
+
+$results is assumed to contain a hashref which will have the keys
+'uninstall' and 'uninstall_fail' populated with keys for the files
+removed and values of the source files they would shadow.
+
=end _undocumented
=cut
sub inc_uninstall {
- my($filepath,$libdir,$verbose,$nonono,$ignore) = @_;
+ my($filepath,$libdir,$verbose,$dry_run,$ignore,$results) = @_;
my($dir);
$ignore||="";
my $file = (File::Spec->splitpath($filepath))[2];
my %seen_dir = ();
-
+
my @PERL_ENV_LIB = split $Config{path_sep}, defined $ENV{'PERL5LIB'}
? $ENV{'PERL5LIB'} : $ENV{'PERLLIB'} || '';
-
- foreach $dir (@INC, @PERL_ENV_LIB, @Config{qw(archlibexp
- privlibexp
- sitearchexp
- sitelibexp)}) {
- my $canonpath = File::Spec->canonpath($dir);
+
+ my @dirs=( @PERL_ENV_LIB,
+ @INC,
+ @Config{qw(archlibexp
+ privlibexp
+ sitearchexp
+ sitelibexp)});
+
+ #warn join "\n","---",@dirs,"---";
+ my $seen_ours;
+ foreach $dir ( @dirs ) {
+ my $canonpath = $Is_VMS ? $dir : File::Spec->canonpath($dir);
next if $canonpath eq $Curdir;
next if $seen_dir{$canonpath}++;
my $targetfile = File::Spec->catfile($canonpath,$libdir,$file);
@@ -920,8 +1064,12 @@
}
print "#$file and $targetfile differ\n" if $diff && $verbose > 1;
- next if !$diff or $targetfile eq $ignore;
- if ($nonono) {
+ if (!$diff or $targetfile eq $ignore) {
+ $seen_ours = 1;
+ next;
+ }
+ if ($dry_run) {
+ $results->{uninstall}{$targetfile} = $filepath;
if ($verbose) {
$Inc_uninstall_warn_handler ||= ExtUtils::Install::Warn->new();
$libdir =~ s|^\./||s ; # That's just cosmetics, no need to
port. It looks prettier.
@@ -933,7 +1081,21 @@
# if not verbose, we just say nothing
} else {
print "Unlinking $targetfile (shadowing?)\n" if $verbose;
- forceunlink($targetfile,'tryhard');
+ eval {
+ die "Fake die for testing"
+ if $ExtUtils::Install::Testing and
+
ucase(File::Spec->canonpath($ExtUtils::Install::Testing)) eq ucase($targetfile);
+ forceunlink($targetfile,'tryhard');
+ $results->{uninstall}{$targetfile} = $filepath;
+ 1;
+ } or do {
+ $results->{fail_uninstall}{$targetfile} = $filepath;
+ if ($seen_ours) {
+ warn "Failed to remove probably harmless shadow file
'$targetfile'\n";
+ } else {
+ die "[EMAIL PROTECTED]";
+ }
+ };
}
}
}
@@ -962,6 +1124,7 @@
close CMD or die "Filter command '$cmd' failed for $src";
}
+=pod
=item B<pm_to_blib>
@@ -1068,7 +1231,8 @@
}
$plural = $i>1 ? "all those files" : "this file";
my $inst = (_invokant() eq 'ExtUtils::MakeMaker')
- ? ( $Config::Config{make} || 'make' ).' install UNINST=1'
+ ? ( $Config::Config{make} || 'make' ).' install'
+ . ( $Is_VMS ? '/MACRO="UNINST"=1' : ' UNINST=1' )
: './Build install uninst=1';
print "## Running '$inst' will unlink $plural for you.\n";
}
@@ -1103,6 +1267,7 @@
return $builder;
}
+=pod
=back
@@ -1123,13 +1288,23 @@
If there is no INSTALL.SKIP file in the make directory then this value
can be used to provide a default.
+=item B<EU_INSTALL_ALWAYS_COPY>
+
+If this environment variable is true then normal install processes will
+always overwrite older identical files during the install process.
+
+Note that the alias EU_ALWAYS_COPY will be supported if EU_INSTALL_ALWAYS_COPY
+is not defined until at least the 1.50 release. Please ensure you use the
+correct EU_INSTALL_ALWAYS_COPY.
+
=back
=head1 AUTHOR
Original author lost in the mists of time. Probably the same as Makemaker.
-Production release currently maintained by demerphq C<yves at cpan.org>
+Production release currently maintained by demerphq C<yves at cpan.org>,
+extensive changes by Michael G. Schwern.
Send bug reports via http://rt.cpan.org/. Please send your
generated Makefile along with your report.
==== //depot/maint-5.10/perl/lib/ExtUtils/t/Embed.t#3 (text) ====
Index: perl/lib/ExtUtils/t/Embed.t
--- perl/lib/ExtUtils/t/Embed.t#2~33483~ 2008-03-11 14:22:23.000000000
-0700
+++ perl/lib/ExtUtils/t/Embed.t 2008-03-26 05:45:28.000000000 -0700
@@ -163,7 +163,7 @@
#define my_puts(a) if(puts(a) < 0) exit(666)
-static char *cmds[] = { "perl","-e", "$|=1; print qq[ok 5\\n]", NULL };
+static const char * cmds [] = { "perl", "-e", "$|=1; print qq[ok 5\\n]", NULL
};
#ifdef PERL_GLOBAL_STRUCT_PRIVATE
static struct perl_vars *my_plvarsp;
@@ -171,12 +171,11 @@
#endif
#ifdef NO_ENV_ARRAY_IN_MAIN
-extern char **environ;
-int main(int argc, char **argv)
+int main(int argc, char **argv) {
+ char **env;
#else
-int main(int argc, char **argv, char **env)
+int main(int argc, char **argv, char **env) {
#endif
-{
PerlInterpreter *my_perl;
#ifdef PERL_GLOBAL_STRUCT
dVAR;
@@ -188,11 +187,7 @@
(void)argc; /* PERL_SYS_INIT3 may #define away their use */
(void)argv;
-#ifdef NO_ENV_ARRAY_IN_MAIN
- PERL_SYS_INIT3(&argc,&argv,&environ);
-#else
- PERL_SYS_INIT3(&argc,&argv,&env);
-#endif
+ PERL_SYS_INIT3(&argc, &argv, &env);
my_perl = perl_alloc();
@@ -202,11 +197,7 @@
my_puts("ok 3");
-#ifdef NO_ENV_ARRAY_IN_MAIN
- perl_parse(my_perl, NULL, (sizeof(cmds)/sizeof(char *))-1, cmds, environ);
-#else
- perl_parse(my_perl, NULL, (sizeof(cmds)/sizeof(char *))-1, cmds, env);
-#endif
+ perl_parse(my_perl, NULL, (sizeof(cmds)/sizeof(char *))-1, (char **)cmds,
env);
my_puts("ok 4");
==== //depot/maint-5.10/perl/lib/ExtUtils/t/Install.t#2 (text) ====
Index: perl/lib/ExtUtils/t/Install.t
--- perl/lib/ExtUtils/t/Install.t#1~32694~ 2007-12-22 01:23:09.000000000
-0800
+++ perl/lib/ExtUtils/t/Install.t 2008-03-26 05:45:28.000000000 -0700
@@ -17,11 +17,14 @@
use File::Path;
use File::Spec;
-use Test::More tests => 38;
+use Test::More tests => 52;
use MakeMaker::Test::Setup::BFD;
BEGIN { use_ok('ExtUtils::Install') }
+# ensure the env doesnt pollute our tests
+local $ENV{EU_INSTALL_ALWAYS_COPY};
+local $ENV{EU_ALWAYS_COPY};
# Check exports.
foreach my $func (qw(install uninstall pm_to_blib install_default)) {
@@ -122,6 +125,56 @@
' UNINST=0 left different' );
}
+# Test UNINST=1 only warning when failing to remove an irrelevent shadow file
+{
+ my $tfile='install-test/lib/perl/Big/Dummy.pm';
+ local $ExtUtils::Install::Testing = $tfile;
+ local @INC = ('install-test/other_lib/perl','install-test/lib/perl');
+ local $ENV{PERL5LIB} = '';
+ ok( -r $tfile, 'different install exists' );
+ my @warn;
+ local $SIG{__WARN__}=sub { push @warn, @_; return };
+ my $ok=eval {
+ install( { 'blib/lib' => 'install-test/other_lib/perl',
+ read => 'install-test/packlist',
+ write => 'install-test/packlist'
+ },
+ 0, 0, 1);
+ 1
+ };
+ ok($ok,' we didnt die');
+ ok([EMAIL PROTECTED]," we did warn");
+ ok( -d 'install-test/other_lib/perl', 'install made other dir' );
+ ok( -r 'install-test/other_lib/perl/Big/Dummy.pm', ' .pm file installed' );
+ ok( -r 'install-test/packlist', ' packlist exists' );
+ ok( -r $tfile, ' UNINST=1 failed to remove different' );
+
+}
+
+# Test UNINST=1 dieing when failing to remove an relevent shadow file
+{
+ my $tfile='install-test/lib/perl/Big/Dummy.pm';
+ local $ExtUtils::Install::Testing = $tfile;
+ local @INC = ('install-test/lib/perl','install-test/other_lib/perl');
+ local $ENV{PERL5LIB} = '';
+ ok( -r $tfile, 'different install exists' );
+ my @warn;
+ local $SIG{__WARN__}=sub { push @warn,@_; return };
+ my $ok=eval {
+ install( { 'blib/lib' => 'install-test/other_lib/perl',
+ read => 'install-test/packlist',
+ write => 'install-test/packlist'
+ },
+ 0, 0, 1);
+ 1
+ };
+ ok(!$ok,' we did die');
+ ok([EMAIL PROTECTED]," we didnt warn");
+ ok( -d 'install-test/other_lib/perl', 'install made other dir' );
+ ok( -r 'install-test/other_lib/perl/Big/Dummy.pm', ' .pm file installed' );
+ ok( -r 'install-test/packlist', ' packlist exists' );
+ ok( -r $tfile,' UNINST=1 failed to remove different' );
+}
# Test UNINST=1 removing other versions in other dirs.
{
@@ -138,3 +191,4 @@
ok( !-r 'install-test/lib/perl/Big/Dummy.pm',
' UNINST=1 removed different' );
}
+
==== //depot/maint-5.10/perl/lib/ExtUtils/t/Installapi2.t#1 (text) ====
Index: perl/lib/ExtUtils/t/Installapi2.t
--- /dev/null 2008-03-18 12:45:05.529577733 -0700
+++ perl/lib/ExtUtils/t/Installapi2.t 2008-03-26 05:45:28.000000000 -0700
@@ -0,0 +1,238 @@
+#!/usr/bin/perl -w
+
+# Test ExtUtils::Install.
+
+BEGIN {
+ if( $ENV{PERL_CORE} ) {
+ @INC = ('../../lib', '../lib', 'lib');
+ }
+ else {
+ unshift @INC, 't/lib';
+ }
+}
+chdir 't';
+
+use strict;
+use TieOut;
+use File::Path;
+use File::Spec;
+
+use Test::More tests => 70;
+
+use MakeMaker::Test::Setup::BFD;
+
+BEGIN { use_ok('ExtUtils::Install') }
+
+# Check exports.
+foreach my $func (qw(install uninstall pm_to_blib install_default)) {
+ can_ok(__PACKAGE__, $func);
+}
+
+
+ok( setup_recurs(), 'setup' );
+END {
+ ok( chdir File::Spec->updir );
+ ok( teardown_recurs(), 'teardown' );
+}
+# ensure the env doesnt pollute our tests
+local $ENV{EU_INSTALL_ALWAYS_COPY};
+local $ENV{EU_ALWAYS_COPY};
+
+chdir 'Big-Dummy';
+
+my $stdout = tie *STDOUT, 'TieOut';
+pm_to_blib( { 'lib/Big/Dummy.pm' => 'blib/lib/Big/Dummy.pm' },
+ 'blib/lib/auto'
+ );
+END { rmtree 'blib' }
+
+ok( -d 'blib/lib', 'pm_to_blib created blib dir' );
+ok( -r 'blib/lib/Big/Dummy.pm', ' copied .pm file' );
+ok( -r 'blib/lib/auto', ' created autosplit dir' );
+is( $stdout->read, "cp lib/Big/Dummy.pm blib/lib/Big/Dummy.pm\n" );
+
+pm_to_blib( { 'lib/Big/Dummy.pm' => 'blib/lib/Big/Dummy.pm' },
+ 'blib/lib/auto'
+ );
+ok( -d 'blib/lib', 'second run, blib dir still there' );
+ok( -r 'blib/lib/Big/Dummy.pm', ' .pm file still there' );
+ok( -r 'blib/lib/auto', ' autosplit still there' );
+is( $stdout->read, "Skip blib/lib/Big/Dummy.pm (unchanged)\n" );
+
+install( [
+ from_to=>{ 'blib/lib' => 'install-test/lib/perl',
+ read => 'install-test/packlist',
+ write => 'install-test/packlist'
+ },
+ dry_run=>1]);
+ok( ! -d 'install-test/lib/perl', 'install made dir (dry run)');
+ok( ! -r 'install-test/lib/perl/Big/Dummy.pm',
+ ' .pm file installed (dry run)');
+ok( ! -r 'install-test/packlist', ' packlist exists (dry run)');
+
+install([ from_to=> { 'blib/lib' => 'install-test/lib/perl',
+ read => 'install-test/packlist',
+ write => 'install-test/packlist'
+ } ]);
+ok( -d 'install-test/lib/perl', 'install made dir' );
+ok( -r 'install-test/lib/perl/Big/Dummy.pm', ' .pm file installed' );
+ok(!-r 'install-test/lib/perl/Big/Dummy.SKIP', ' ignored .SKIP file' );
+ok( -r 'install-test/packlist', ' packlist exists' );
+
+open(PACKLIST, 'install-test/packlist' );
+my %packlist = map { chomp; ($_ => 1) } <PACKLIST>;
+close PACKLIST;
+
+# On case-insensitive filesystems (ie. VMS), the keys of the packlist might
+# be lowercase. :(
+my $native_dummy = File::Spec->catfile(qw(install-test lib perl Big Dummy.pm));
+is( keys %packlist, 1 );
+is( lc((keys %packlist)[0]), lc $native_dummy, 'packlist written' );
+
+
+# Test UNINST=1 preserving same versions in other dirs.
+install([from_to=> { 'blib/lib' => 'install-test/other_lib/perl',
+ read => 'install-test/packlist',
+ write => 'install-test/packlist'
+ },uninstall_shadows=>1]);
+ok( -d 'install-test/other_lib/perl', 'install made other dir' );
+ok( -r 'install-test/other_lib/perl/Big/Dummy.pm', ' .pm file installed' );
+ok( -r 'install-test/packlist', ' packlist exists' );
+ok( -r 'install-test/lib/perl/Big/Dummy.pm', ' UNINST=1 preserved same' );
+
+
+chmod 0644, 'blib/lib/Big/Dummy.pm' or die $!;
+open(DUMMY, ">>blib/lib/Big/Dummy.pm") or die $!;
+print DUMMY "Extra stuff\n";
+close DUMMY;
+
+
+# Test UNINST=0 does not remove other versions in other dirs.
+{
+ ok( -r 'install-test/lib/perl/Big/Dummy.pm', 'different install exists' );
+
+ local @INC = ('install-test/lib/perl');
+ local $ENV{PERL5LIB} = '';
+ install([from_to=> { 'blib/lib' => 'install-test/other_lib/perl',
+ read => 'install-test/packlist',
+ write => 'install-test/packlist'
+ }]);
+ ok( -d 'install-test/other_lib/perl', 'install made other dir' );
+ ok( -r 'install-test/other_lib/perl/Big/Dummy.pm', ' .pm file installed' );
+ ok( -r 'install-test/packlist', ' packlist exists' );
+ ok( -r 'install-test/lib/perl/Big/Dummy.pm',
+ ' UNINST=0 left different' );
+}
+
+# Test UNINST=1 only warning when failing to remove an irrelevent shadow file
+{
+ my $tfile='install-test/lib/perl/Big/Dummy.pm';
+ local $ExtUtils::Install::Testing = $tfile;
+ local @INC = ('install-test/other_lib/perl','install-test/lib/perl');
+ local $ENV{PERL5LIB} = '';
+ ok( -r $tfile, 'different install exists' );
+ my @warn;
+ local $SIG{__WARN__}=sub { push @warn, @_; return };
+ my $ok=eval {
+ install([from_to=> { 'blib/lib' => 'install-test/other_lib/perl',
+ read => 'install-test/packlist',
+ write => 'install-test/packlist'
+ },
+ uninstall_shadows=>1]);
+ 1
+ };
+ ok($ok,' we didnt die');
+ ok([EMAIL PROTECTED]," we did warn");
+ ok( -d 'install-test/other_lib/perl', 'install made other dir' );
+ ok( -r 'install-test/other_lib/perl/Big/Dummy.pm', ' .pm file installed' );
+ ok( -r 'install-test/packlist', ' packlist exists' );
+ ok( -r $tfile, ' UNINST=1 failed to remove different' );
+
+}
+
+# Test UNINST=1 dieing when failing to remove an relevent shadow file
+{
+ my $tfile='install-test/lib/perl/Big/Dummy.pm';
+ local $ExtUtils::Install::Testing = $tfile;
+ local @INC = ('install-test/lib/perl','install-test/other_lib/perl');
+ local $ENV{PERL5LIB} = '';
+ ok( -r $tfile, 'different install exists' );
+ my @warn;
+ local $SIG{__WARN__}=sub { push @warn,@_; return };
+ my $ok=eval {
+ install([from_to=> { 'blib/lib' => 'install-test/other_lib/perl',
+ read => 'install-test/packlist',
+ write => 'install-test/packlist'
+ },uninstall_shadows=>1]);
+ 1
+ };
+ ok(!$ok,' we did die');
+ ok([EMAIL PROTECTED]," we didnt warn");
+ ok( -d 'install-test/other_lib/perl', 'install made other dir' );
+ ok( -r 'install-test/other_lib/perl/Big/Dummy.pm', ' .pm file installed' );
+ ok( -r 'install-test/packlist', ' packlist exists' );
+ ok( -r $tfile,' UNINST=1 failed to remove different' );
+}
+
+# Test UNINST=1 removing other versions in other dirs.
+{
+ local @INC = ('install-test/lib/perl');
+ local $ENV{PERL5LIB} = '';
+ ok( -r 'install-test/lib/perl/Big/Dummy.pm','different install exists' );
+ install([from_to=>{ 'blib/lib' => 'install-test/other_lib/perl',
+ read => 'install-test/packlist',
+ write => 'install-test/packlist'
+ },uninstall_shadows=>1]);
+ ok( -d 'install-test/other_lib/perl', 'install made other dir' );
+ ok( -r 'install-test/other_lib/perl/Big/Dummy.pm', ' .pm file installed' );
+ ok( -r 'install-test/packlist', ' packlist exists' );
+ ok( !-r 'install-test/lib/perl/Big/Dummy.pm',
+ ' UNINST=1 removed different' );
+}
+
+# Test EU_ALWAYS_COPY triggers copy.
+{
+ local @INC = ('install-test/lib/perl');
+ local $ENV{PERL5LIB} = '';
+ local $ENV{EU_INSTALL_ALWAYS_COPY}=1;
+ my $tfile='install-test/other_lib/perl/Big/Dummy.pm';
+ my $sfile='blib/lib/Big/Dummy.pm';
+ ok(-r $tfile,"install file already exists");
+ ok(-r $sfile,"source file already exists");
+ utime time-600, time-600, $sfile or die "utime '$sfile' failed:$!";
+ ok( (stat $tfile)[9]!=(stat $sfile)[9],' Times are different');
+ install([from_to=>{ 'blib/lib' => 'install-test/other_lib/perl',
+ read => 'install-test/packlist',
+ write => 'install-test/packlist'
+ },result=>\my %result]);
+ ok( -d 'install-test/other_lib/perl', 'install made other dir' );
+ ok( -r 'install-test/other_lib/perl/Big/Dummy.pm', ' .pm file installed' );
+ ok( -r 'install-test/packlist', ' packlist exists' );
+SKIP: {
+ skip "Times not preserved during copy by default", 1 if $^O eq 'VMS';
+ ok( (stat $tfile)[9]==(stat $sfile)[9],' Times are same');
+}
+ ok( !$result{install_unchanged},' $result{install_unchanged} should be
empty');
+}
+# Test nothing is copied.
+{
+ local @INC = ('install-test/lib/perl');
+ local $ENV{PERL5LIB} = '';
+ local $ENV{EU_INSTALL_ALWAYS_COPY}=0;
+ my $tfile='install-test/other_lib/perl/Big/Dummy.pm';
+ my $sfile='blib/lib/Big/Dummy.pm';
+ ok(-r $tfile,"install file already exists");
+ ok(-r $sfile,"source file already exists");
+ utime time-1200, time-1200, $sfile or die "utime '$sfile' failed:$!";
+ ok( (stat $tfile)[9]!=(stat $sfile)[9],' Times are different');
+ install([from_to=>{ 'blib/lib' => 'install-test/other_lib/perl',
+ read => 'install-test/packlist',
+ write => 'install-test/packlist'
+ },result=>\my %result]);
+ ok( -d 'install-test/other_lib/perl', 'install made other dir' );
+ ok( -r 'install-test/other_lib/perl/Big/Dummy.pm', ' .pm file installed' );
+ ok( -r 'install-test/packlist', ' packlist exists' );
+ ok( (stat $tfile)[9]!=(stat$sfile)[9],' Times are different');
+ ok( !$result{install},' nothing should have been installed');
+ ok( $result{install_unchanged},' install_unchanged should be populated');
+}
==== //depot/maint-5.10/perl/lib/ExtUtils/t/can_write_dir.t#1 (xtext) ====
Index: perl/lib/ExtUtils/t/can_write_dir.t
--- /dev/null 2008-03-18 12:45:05.529577733 -0700
+++ perl/lib/ExtUtils/t/can_write_dir.t 2008-03-26 05:45:28.000000000 -0700
@@ -0,0 +1,61 @@
+#!/usr/bin/perl -w
+
+# Test the private _can_write_dir() function.
+
+use strict;
+use ExtUtils::Install;
+use File::Spec;
+{ package FS; our @ISA = qw(File::Spec); }
+
+# Alias it for easier access
+*can_write_dir = \&ExtUtils::Install::_can_write_dir;
+
+use Test::More 'no_plan';
+
+
+my $dne = FS->catdir(qw(does not exist));
+ok ! -e $dne;
+is_deeply [can_write_dir($dne)],
+ [1,
+ FS->curdir,
+ FS->catdir('does'),
+ FS->catdir('does', 'not'),
+ FS->catdir('does', 'not', 'exist')
+ ];
+
+
+my $abs_dne = FS->rel2abs($dne);
+ok ! -e $abs_dne;
+is_deeply [can_write_dir($abs_dne)],
+ [1,
+ FS->rel2abs(FS->curdir),
+ FS->rel2abs(FS->catdir('does')),
+ FS->rel2abs(FS->catdir('does', 'not')),
+ FS->rel2abs(FS->catdir('does', 'not', 'exist')),
+ ];
+
+SKIP: {
+ my $exists = FS->catdir(qw(exists));
+ my $subdir = FS->catdir(qw(exists subdir));
+
+
+ ok mkdir $exists;
+ END { rmdir $exists }
+
+ ok chmod 0555, $exists, 'make read only';
+
+ skip "Current user or OS cannot create directories that they cannot read",
6
+ if -w $exists; # these tests require a directory we cant read
+
+ is_deeply [can_write_dir($exists)], [0, $exists];
+ is_deeply [can_write_dir($subdir)], [0, $exists, $subdir];
+
+ ok chmod 0777, $exists, 'make writable';
+ ok -w $exists;
+ is_deeply [can_write_dir($exists)], [1, $exists];
+ is_deeply [can_write_dir($subdir)],
+ [1,
+ $exists,
+ $subdir
+ ];
+}
\ No newline at end of file
==== //depot/maint-5.10/perl/pod/perlport.pod#3 (text) ====
Index: perl/pod/perlport.pod
--- perl/pod/perlport.pod#2~33123~ 2008-01-30 03:45:08.000000000 -0800
+++ perl/pod/perlport.pod 2008-03-26 05:45:28.000000000 -0700
@@ -1580,6 +1580,11 @@
and applications are executable, and there are no uid/gid
considerations. C<-o> is not supported. (S<Mac OS>)
+C<-w> only inspects the read-only file attribute (FILE_ATTRIBUTE_READONLY),
+which determines whether the directory can be deleted, not whether it can
+be written to. Directories always have read and write access unless denied
+by discretionary access control lists (DACLs). (S<Win32>)
+
C<-r>, C<-w>, C<-x>, and C<-o> tell whether the file is accessible,
which may not reflect UIC-based file protections. (VMS)
==== //depot/maint-5.10/perl/pod/perltodo.pod#4 (text) ====
Index: perl/pod/perltodo.pod
--- perl/pod/perltodo.pod#3~33123~ 2008-01-30 03:45:08.000000000 -0800
+++ perl/pod/perltodo.pod 2008-03-26 05:45:28.000000000 -0700
@@ -484,6 +484,31 @@
might be nice to do as Microsoft suggest here too, although, unlike the secure
functions issue, there is presumably little or no benefit in this case.
+=head2 Fix POSIX::access() and chdir() on Win32
+
+These functions currently take no account of DACLs and therefore do not behave
+correctly in situations where access is restricted by DACLs (as opposed to the
+read-only attribute).
+
+Furthermore, POSIX::access() behaves differently for directories having the
+read-only attribute set depending on what CRT library is being used. For
+example, the _access() function in the VC6 and VC7 CRTs (wrongly) claim that
+such directories are not writable, whereas in fact all directories are writable
+unless access is denied by DACLs. (In the case of directories, the read-only
+attribute actually only means that the directory cannot be deleted.) This CRT
+bug is fixed in the VC8 and VC9 CRTs (but, of course, the directory may still
+not actually be writable if access is indeed denied by DACLs).
+
+For the chdir() issue, see ActiveState bug #74552:
+http://bugs.activestate.com/show_bug.cgi?id=74552
+
+Therefore, DACLs should be checked both for consistency across CRTs and for
+the correct answer.
+
+(Note that perl's -w operator should not be modified to check DACLs. It has
+been written so that it reflects the state of the read-only attribute, even
+for directories (whatever CRT is being used), for symmetry with chmod().)
+
=head2 strcat(), strcpy(), strncat(), strncpy(), sprintf(), vsprintf()
Maybe create a utility that checks after each libperl.a creation that
==== //depot/maint-5.10/perl/win32/win32.c#3 (text) ====
Index: perl/win32/win32.c
--- perl/win32/win32.c#2~33121~ 2008-01-30 03:03:49.000000000 -0800
+++ perl/win32/win32.c 2008-03-26 05:45:28.000000000 -0700
@@ -1500,9 +1500,22 @@
errno = ENOTDIR;
return -1;
}
+ if (S_ISDIR(sbuf->st_mode)) {
+ /* Ensure the "write" bit is switched off in the mode for
+ * directories with the read-only attribute set. Borland (at least)
+ * switches it on for directories, which is technically correct
+ * (directories are indeed always writable unless denied by DACLs),
+ * but we want stat() and -w to reflect the state of the read-only
+ * attribute for symmetry with chmod(). */
+ DWORD r = GetFileAttributesA(path);
+ if (r != 0xffffffff && (r & FILE_ATTRIBUTE_READONLY)) {
+ sbuf->st_mode &= ~S_IWRITE;
+ }
+ }
#ifdef __BORLANDC__
- if (S_ISDIR(sbuf->st_mode))
- sbuf->st_mode |= S_IWRITE | S_IEXEC;
+ if (S_ISDIR(sbuf->st_mode)) {
+ sbuf->st_mode |= S_IEXEC;
+ }
else if (S_ISREG(sbuf->st_mode)) {
int perms;
if (l >= 4 && path[l-4] == '.') {
End of Patch.