Beefy Boxes and Bandwidth Generously Provided by pair Networks
The stupid question is the question not asked
 
PerlMonks  

File::Copy dying on Win2k when target file already there

by scain (Curate)
on Jan 16, 2003 at 17:49 UTC ( #227431=perlquestion: print w/ replies, xml ) Need Help??
scain has asked for the wisdom of the Perl Monks concerning the following question:

Hello Fine Monks,

In an effort to make my webapp install cross-platform, I have written several small Perl scripts that do some of the moving of files for 'make install'. These scripts work fine when installing on a Linux box, and they work when installing on a Win2k box, as long as the files that it is trying to install don't already exist in the install location. If the files are alread there, the script dies thusly:

conf\plugins\BatchDumper.pm unable to copy to C:\progra~1\apache~1\apa +che\conf\gbrowse.conf\plugins\BatchDumper.pm : Bad file descriptor NMAKE : fatal error U1077: 'C:\WINNT\system32\cmd.exe' : return code ' +0x9' Stop.
Now, I suppose I could check for the existence of the file, unlink it and then copy it, but that seems quite ugly to me, when File::Copy's copy should work just fine. Any suggestions? The code follows:
#!/usr/bin/perl -w use strict; #Perform installation of gbrowse apache configuration files use File::Copy; use Bio::Root::IO; # get configuration stuff from command line my $dir = $ARGV[0]; # use Bio::Root::IO now #my $delim = '/'; #if ($Config{'osname'} =~ /win/i && $Config{'osname'} !~ /darwin/i ) { # $dir =~ s!\/!\\!g; # $delim = '\\'; #} #start the installation... print "Installing sample configuration files...\n"; if (! (-e $dir)) { mkdir($dir,0777) or die "unable to make $dir directory\n"; } opendir CONFDIR, "conf" or die "unable to opendir conf\n"; while (my $conffile = readdir(CONFDIR) ) { my $localfile = Bio::Root::IO->catfile('conf', $conffile); if (-f $localfile) { my $installfile = Bio::Root::IO->catfile($dir, $conffile); if (-f $installfile) { print " Found $conffile in $dir. Skipping...\n"; } else { copy($localfile, $installfile) or die "unable to copy to $installfile\n"; } } } closedir CONFDIR; my $plugindir = Bio::Root::IO->catfile($dir, "plugins"); if (! (-e $plugindir)) { mkdir($plugindir,0777) or die "unable to mkdir $plugindir\n"; } opendir PLUGINS, "conf/plugins" or die "unable to opendir ./conf/plugi +ns\n"; while (my $pluginfile = readdir(PLUGINS) ) { my $localfile = Bio::Root::IO->catfile('conf/plugins',$pluginfile) +; if (-f $localfile) { my $installfile = Bio::Root::IO->catfile($plugindir, $pluginfi +le); copy($localfile, $installfile) or die "unable to copy to $installfile\n"; } } closedir PLUGINS; my $langdir = Bio::Root::IO->catfile($dir, 'languages'); if (! (-e $langdir)) { mkdir($langdir,0777) or die "unable to mkdir $langdir\n"; } opendir LANGS, "conf/languages" or die "unable to opendir ./conf/langu +ages\n"; while (my $langfile = readdir(LANGS)) { my $localfile = Bio::Root::IO->catfile("conf/languages", $langfile +); if (-f $localfile) { my $installfile = Bio::Root::IO->catfile($langdir, $langfile); copy($localfile, $installfile) or die "unable to copy to $installfile\n"; } } closedir LANGS;

Thanks,
Scott
Project coordinator of the Generic Model Organism Database Project

Comment on File::Copy dying on Win2k when target file already there
Select or Download Code
Replies are listed 'Best First'.
Re: File::Copy dying on Win2k when target file already there
by bart (Canon) on Jan 16, 2003 at 20:12 UTC
    Actually, it's your own script, not File::Copy, that causes the script to die:
    copy($localfile, $installfile) or die "unable to copy to $installfile\n";
    If you were to drop the "or die..." part, it wouldn't do that. It wouldn't replace the file that was there, either, so it's not the best of solutions.

    $installfile looks like it contains an absolute path to me. You may try to delete a file without checking if it did indeed exist, like this:

    unlink $installfile;
    No error checking here: if it fails, nothing happens. If you were to put this line just in front of the line containing the copy(), including the die() part, this would likely do the proper thing: replace an existing file, and die() if it fails.
Re: File::Copy dying on Win2k when target file already there
by John M. Dlugosz (Monsignor) on Jan 16, 2003 at 21:03 UTC
    Very strange. Your code is die "unable to copy to $installfile\n"; so where is it getting the " : invalid file descriptor" before the \n?

    You might print $! and $^E also to find out why the copy failed.

    One time when I had an "already there" problem, it's because the file was read-only. So you can't just delete it either. I unconditionally reset the attribute on the target, ignoring any error if it didn't exist, then did the copy.

    —John

      Very sorry about the confusion. I had a little bit of a versioning problem. I modified the error message line after I pasted in the code for the script to get a more informative error message, and forgot to fix the code. The modified line looks like this:
      copy($localfile, $installfile) or die "$localfile unable to copy to $installfile : $!\n";

      That said, demerphq helped me track down the problem. The problematic files where read-only, and apparently File::Copy won't let you copy over read-only files (even if you are the Administrator). I modified the code to add lines like this:

      fixreadonly($plugindir) if $^O =~ /win32/i; sub fixreadonly { my $dir = shift; my $unsetreadonly = Bio::Root::IO->catfile( $dir, "*.*"); system("attrib -r /s $unsetreadonly"); }

      Scott
      Project coordinator of the Generic Model Organism Database Project

        You can change the attribute using chmod, built into Perl, instead of calling out to system. I tried it using the UNIX bits meanings, and it did indeed turn off the R flag on Windows NT.

        That works the same on both platforms, so you don't even have to make it conditional.

Re: File::Copy dying on Win2k when target file already there
by runrig (Abbot) on Jan 16, 2003 at 20:56 UTC
    You really ought to include $! or $^E in your die error messages...that being said, I don't see how your error message relates to your code; what is BatchDumper.pm, and where is it called in your code?
      Agreed about $!; I added in between posting the code and posting the error message.

      BatchDumper.pm is part of the app and it has to be installed in a subdirectory of Apache\conf. The error message comes from the fact that the script that does the copying for the install dies because BatchDumper.pm is read-only.

      Scott
      Project coordinator of the Generic Model Organism Database Project

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://227431]
Approved by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others meditating upon the Monastery: (10)
As of 2015-07-31 18:45 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (280 votes), past polls