Skip Menu |

This queue is for tickets about the ExtUtils-Command CPAN distribution.

Report information
The Basics
Id: 34718
Status: resolved
Priority: 0/
Queue: ExtUtils-Command

People
Owner: Nobody in particular
Requestors: adamk [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: Critical
Broken in: 1.14
Fixed in: (no value)



Subject: cp fails to update timestamp on Win32
cp currently misbehaves on Win32 on NTFS under some circumstances, because the newly copied file retains the timestamp of the old file. This creates critical failures in downstream functionality, in particular it completely destroys the functionality of makefiles, because copied files are expected to have updated timestamps. The cp implementation should validate that the timestamp is updated, and if not it should touch the file to ensure that the timestamp is updated.
Subject: Re: [rt.cpan.org #34718] AutoReply: cp fails to update timestamp on Win32
Date: Tue, 8 Apr 2008 07:17:45 +0200
To: bug-ExtUtils-Command [...] rt.cpan.org
From: "Adam Kennedy" <adamkennedybackup [...] gmail.com>
Followup. I can validate that something as simple as if ( $^O eq 'MSWin32' ) { my $t = time; utime($t, $t, $dst); } ... at the end inside the main foreach in cp is enough to get it working for Strawberry Perl. I've patched the version I bundle with this change. Adam K On 06/04/2008, Bugs in ExtUtils-Command via RT <bug-ExtUtils-Command@rt.cpan.org> wrote: Show quoted text
> > Greetings, > > This message has been automatically generated in response to the > creation of a trouble ticket regarding: > "cp fails to update timestamp on Win32", > a summary of which appears below. > > There is no need to reply to this message right now. Your ticket has been > assigned an ID of [rt.cpan.org #34718]. Your ticket is accessible > on the web at: > > http://rt.cpan.org/Ticket/Display.html?id=34718 > > Please include the string: > > [rt.cpan.org #34718] > > in the subject line of all future correspondence about this issue. To do so, > you may reply to this message. > > Thank you, > bug-ExtUtils-Command@rt.cpan.org > > ------------------------------------------------------------------------- > cp currently misbehaves on Win32 on NTFS under some circumstances, > because the newly copied file retains the timestamp of the old file. > > This creates critical failures in downstream functionality, in > particular it completely destroys the functionality of makefiles, > because copied files are expected to have updated timestamps. > > The cp implementation should validate that the timestamp is updated, and > if not it should touch the file to ensure that the timestamp is updated. > > >
On Tue Apr 08 01:17:56 2008, adamkennedybackup@gmail.com wrote: Show quoted text
> Followup. > > I can validate that something as simple as > > if ( $^O eq 'MSWin32' ) { > my $t = time; > utime($t, $t, $dst); > } > > ... at the end inside the main foreach in cp is enough to get it > working for Strawberry Perl. I've patched the version I bundle with > this change. > > Adam K
I'd be worried a bit about changing this behaviour, in that ExtUtils::Command::cp: http://search.cpan.org/src/RKOBES/ExtUtils-Command-1.14/lib/ExtUtils/Command.pm relies on File::Copy::copy: http://search.cpan.org/src/RGARCIA/perl-5.10.0/lib/File/Copy.pm which doesn't preserve OS-specific attributes, apparently by choice. File::Copy instead provides syscopy, the documentation for which says in part File::Copy also provides the C<syscopy> routine, which copies the file specified in the first parameter to the file specified in the second parameter, preserving OS-specific attributes and file structure. For Unix systems, this is equivalent to the simple C<copy> routine, which doesn't preserve OS-specific attributes. For VMS systems, this calls the C<rmscopy> routine (see below). For OS/2 systems, this calls the C<syscopy> XSUB directly. For Win32 systems, this calls C<Win32::CopyFile>. For the particular problem of Win32, the documentation for Win32::CopyFile says, in part: Win32::CopyFile(FROM, TO, OVERWRITE) [CORE] The Win32::CopyFile() function copies an existing file to a new file. All file information like creation time and file attributes will be copied to the new file. However it will not copy the security information. If the destination file already exists it will only be overwritten when the OVERWRITE parameter is true. But even this will not overwrite a read-only file; you have to unlink() it first yourself. So, to be in synch with File::Copy, perhaps ExtUtils::Command could provide a ExtUtils::Command::syscopy function, which would copy creation time and file attributes to the new file. This though wouldn't solve the problem of Makefiles using ExtUtils::Command::cp.
Subject: Re: [rt.cpan.org #34718] cp fails to update timestamp on Win32
Date: Thu, 10 Apr 2008 18:15:59 +0800
To: bug-ExtUtils-Command [...] rt.cpan.org
From: "Adam Kennedy" <adamkennedybackup [...] gmail.com>
As I understand itm ExtUtils::Command is intended to provide unix-style semantics? And so making Win32 behave like unix is desirable? Adam K On 10/04/2008, RKOBES via RT <bug-ExtUtils-Command@rt.cpan.org> wrote: Show quoted text
> > <URL: http://rt.cpan.org/Ticket/Display.html?id=34718 > > > On Tue Apr 08 01:17:56 2008, adamkennedybackup@gmail.com wrote:
> > Followup. > > > > I can validate that something as simple as > > > > if ( $^O eq 'MSWin32' ) { > > my $t = time; > > utime($t, $t, $dst); > > } > > > > ... at the end inside the main foreach in cp is enough to get it > > working for Strawberry Perl. I've patched the version I bundle with > > this change. > > > > Adam K
> > I'd be worried a bit about changing this behaviour, in that > ExtUtils::Command::cp: > http://search.cpan.org/src/RKOBES/ExtUtils-Command-1.14/lib/ExtUtils/Command.pm > relies on File::Copy::copy: > http://search.cpan.org/src/RGARCIA/perl-5.10.0/lib/File/Copy.pm > which doesn't preserve OS-specific attributes, apparently by choice. > File::Copy instead provides syscopy, the documentation for which says in > part > > File::Copy also provides the C<syscopy> routine, which copies the > file specified in the first parameter to the file specified in the > second parameter, preserving OS-specific attributes and file > structure. For Unix systems, this is equivalent to the simple > C<copy> routine, which doesn't preserve OS-specific attributes. For > VMS systems, this calls the C<rmscopy> routine (see below). For OS/2 > systems, this calls the C<syscopy> XSUB directly. For Win32 systems, > this calls C<Win32::CopyFile>. > > For the particular problem of Win32, the documentation for > Win32::CopyFile says, in part: > > Win32::CopyFile(FROM, TO, OVERWRITE) > [CORE] The Win32::CopyFile() function copies an existing file to a > new file. All file information like creation time and file > attributes will be copied to the new file. However it will not copy > the security information. If the destination file already exists it > will only be overwritten when the OVERWRITE parameter is true. But > even this will not overwrite a read-only file; you have to unlink() > it first yourself. > > So, to be in synch with File::Copy, perhaps ExtUtils::Command could > provide a ExtUtils::Command::syscopy function, which would copy creation > time and file attributes to the new file. This though wouldn't solve the > problem of Makefiles using ExtUtils::Command::cp. > >
Subject: Re: [rt.cpan.org #34718] cp fails to update timestamp on Win32
Date: Thu, 10 Apr 2008 17:46:26 +0200
To: bug-ExtUtils-Command [...] rt.cpan.org
From: Michael G Schwern <schwern [...] pobox.com>
Adam Kennedy via RT wrote: Show quoted text
> As I understand itm ExtUtils::Command is intended to provide > unix-style semantics? > > And so making Win32 behave like unix is desirable?
Yes, that's the idea. It's meant to provide unified cross-platform behavior. -- But there's no sense crying over every mistake. You just keep on trying till you run out of cake. -- Jonathan Coulton, "Still Alive"
In order to emulate Unix behavior, the file is only be touched if it actually changed. Otherwise the times are left alone. That's annoying to have to check, because now we have to check every time before we copy.
If this is an NTFS only thing it should be safe to make a Windows exception to always touch the file.
diff --git a/lib/ExtUtils/Command.pm b/lib/ExtUtils/Command.pm index fbb7d13..528a02f 100644 --- a/lib/ExtUtils/Command.pm +++ b/lib/ExtUtils/Command.pm @@ -14,7 +14,9 @@ use vars qw(@ISA @EXPORT @EXPORT_OK $VERSION); dos2unix); $VERSION = '1.14'; -my $Is_VMS = $^O eq 'VMS'; +my $Is_VMS = $^O eq 'VMS'; +my $Is_Win32 = $^O eq 'MSWin32'; + =head1 NAME @@ -210,6 +212,10 @@ sub cp { my $nok = 0; foreach my $src (@src) { $nok ||= !copy($src,$dst); + + # Win32 does not update the mod time of a copied file, just the + # created time which make does not look at. + utime(time, time, $dst) if $Is_Win32; } return $nok; } diff --git a/t/eu_command.t b/t/eu_command.t index e994f83..99e45aa 100644 --- a/t/eu_command.t +++ b/t/eu_command.t @@ -22,10 +22,8 @@ BEGIN { File::Path::rmtree( 'ecmddir' ); } -BEGIN { - use Test::More tests => 40; - use File::Spec; -} +use Test::More tests => 40; +use File::Spec; BEGIN { # bad neighbor, but test_f() uses exit() --- /dev/null 2008-10-08 23:59:56.000000000 -0400 +++ t/cp.t 2008-10-09 00:04:10.000000000 -0400 @@ -0,0 +1,33 @@ +#!/usr/bin/perl -w + +BEGIN { + if( $ENV{PERL_CORE} ) { + chdir 't'; + @INC = ('../lib', 'lib/'); + } + else { + unshift @INC, 't/lib/'; + } +} +chdir 't'; + +use ExtUtils::Command; +use Test::More tests => 1; + +open FILE, ">source" or die $!; +print FILE "stuff\n"; +close FILE; + +# Instead of sleeping to make the file time older +utime time - 900, time - 900, "source"; + +END { 1 while unlink "source", "dest"; } + +# Win32 bug, cp wouldn't update mtime. +{ + local @ARGV = qw(source dest); + cp(); + my $mtime = (stat("dest"))[9]; + my $now = time; + cmp_ok( abs($mtime - $now), '<=', 1, 'cp updated mtime' ); +}
Thanks very much for the patch - I applied this to the svn sources, and will make a new CPAN release shortly.