#line 1 "/usr/local/lib/perl5/5.8.8/File/Copy.pm" # File/Copy.pm. Written in 1994 by Aaron Sherman . This # source code has been placed in the public domain by the author. # Please be kind and preserve the documentation. # # Additions copyright 1996 by Charles Bailey. Permission is granted # to distribute the revised code under the same terms as Perl itself. package File::Copy; use 5.006; use strict; use warnings; use Carp; use File::Spec; use Config; our(@ISA, @EXPORT, @EXPORT_OK, $VERSION, $Too_Big, $Syscopy_is_copy); sub copy; sub syscopy; sub cp; sub mv; # Note that this module implements only *part* of the API defined by # the File/Copy.pm module of the File-Tools-2.0 package. However, that # package has not yet been updated to work with Perl 5.004, and so it # would be a Bad Thing for the CPAN module to grab it and replace this # module. Therefore, we set this module's version higher than 2.0. $VERSION = '2.09'; require Exporter; @ISA = qw(Exporter); @EXPORT = qw(copy move); @EXPORT_OK = qw(cp mv); $Too_Big = 1024 * 1024 * 2; my $macfiles; if ($^O eq 'MacOS') { $macfiles = eval { require Mac::MoreFiles }; warn 'Mac::MoreFiles could not be loaded; using non-native syscopy' if $@ && $^W; } sub _catname { my($from, $to) = @_; if (not defined &basename) { require File::Basename; import File::Basename 'basename'; } if ($^O eq 'MacOS') { # a partial dir name that's valid only in the cwd (e.g. 'tmp') $to = ':' . $to if $to !~ /:/; } return File::Spec->catfile($to, basename($from)); } sub copy { croak("Usage: copy(FROM, TO [, BUFFERSIZE]) ") unless(@_ == 2 || @_ == 3); my $from = shift; my $to = shift; my $from_a_handle = (ref($from) ? (ref($from) eq 'GLOB' || UNIVERSAL::isa($from, 'GLOB') || UNIVERSAL::isa($from, 'IO::Handle')) : (ref(\$from) eq 'GLOB')); my $to_a_handle = (ref($to) ? (ref($to) eq 'GLOB' || UNIVERSAL::isa($to, 'GLOB') || UNIVERSAL::isa($to, 'IO::Handle')) : (ref(\$to) eq 'GLOB')); if ($from eq $to) { # works for references, too carp("'$from' and '$to' are identical (not copied)"); # The "copy" was a success as the source and destination contain # the same data. return 1; } if ((($Config{d_symlink} && $Config{d_readlink}) || $Config{d_link}) && !($^O eq 'MSWin32' || $^O eq 'os2' || $^O eq 'vms')) { my @fs = stat($from); if (@fs) { my @ts = stat($to); if (@ts && $fs[0] == $ts[0] && $fs[1] == $ts[1]) { carp("'$from' and '$to' are identical (not copied)"); return 0; } } } if (!$from_a_handle && !$to_a_handle && -d $to && ! -d $from) { $to = _catname($from, $to); } if (defined &syscopy && !$Syscopy_is_copy && !$to_a_handle && !($from_a_handle && $^O eq 'os2' ) # OS/2 cannot handle handles && !($from_a_handle && $^O eq 'mpeix') # and neither can MPE/iX. && !($from_a_handle && $^O eq 'MSWin32') && !($from_a_handle && $^O eq 'MacOS') && !($from_a_handle && $^O eq 'NetWare') ) { return syscopy($from, $to); } my $closefrom = 0; my $closeto = 0; my ($size, $status, $r, $buf); local($\) = ''; my $from_h; if ($from_a_handle) { $from_h = $from; } else { $from = _protect($from) if $from =~ /^\s/s; $from_h = \do { local *FH }; open($from_h, "< $from\0") or goto fail_open1; binmode $from_h or die "($!,$^E)"; $closefrom = 1; } my $to_h; if ($to_a_handle) { $to_h = $to; } else { $to = _protect($to) if $to =~ /^\s/s; $to_h = \do { local *FH }; open($to_h,"> $to\0") or goto fail_open2; binmode $to_h or die "($!,$^E)"; $closeto = 1; } if (@_) { $size = shift(@_) + 0; croak("Bad buffer size for copy: $size\n") unless ($size > 0); } else { $size = tied(*$from_h) ? 0 : -s $from_h || 0; $size = 1024 if ($size < 512); $size = $Too_Big if ($size > $Too_Big); } $! = 0; for (;;) { my ($r, $w, $t); defined($r = sysread($from_h, $buf, $size)) or goto fail_inner; last unless $r; for ($w = 0; $w < $r; $w += $t) { $t = syswrite($to_h, $buf, $r - $w, $w) or goto fail_inner; } } close($to_h) || goto fail_open2 if $closeto; close($from_h) || goto fail_open1 if $closefrom; # Use this idiom to avoid uninitialized value warning. return 1; # All of these contortions try to preserve error messages... fail_inner: if ($closeto) { $status = $!; $! = 0; close $to_h; $! = $status unless $!; } fail_open2: if ($closefrom) { $status = $!; $! = 0; close $from_h; $! = $status unless $!; } fail_open1: return 0; } sub move { croak("Usage: move(FROM, TO) ") unless @_ == 2; my($from,$to) = @_; my($fromsz,$tosz1,$tomt1,$tosz2,$tomt2,$sts,$ossts); if (-d $to && ! -d $from) { $to = _catname($from, $to); } ($tosz1,$tomt1) = (stat($to))[7,9]; $fromsz = -s $from; if ($^O eq 'os2' and defined $tosz1 and defined $fromsz) { # will not rename with overwrite unlink $to; } return 1 if rename $from, $to; # Did rename return an error even though it succeeded, because $to # is on a remote NFS file system, and NFS lost the server's ack? return 1 if defined($fromsz) && !-e $from && # $from disappeared (($tosz2,$tomt2) = (stat($to))[7,9]) && # $to's there ($tosz1 != $tosz2 or $tomt1 != $tomt2) && # and changed $tosz2 == $fromsz; # it's all there ($tosz1,$tomt1) = (stat($to))[7,9]; # just in case rename did something { local $@; eval { local $SIG{__DIE__}; copy($from,$to) or die; my($atime, $mtime) = (stat($from))[8,9]; utime($atime, $mtime, $to); unlink($from) or die; }; return 1 unless $@; } ($sts,$ossts) = ($! + 0, $^E + 0); ($tosz2,$tomt2) = ((stat($to))[7,9],0,0) if defined $tomt1; unlink($to) if !defined($tomt1) or $tomt1 != $tomt2 or $tosz1 != $tosz2; ($!,$^E) = ($sts,$ossts); return 0; } *cp = \© *mv = \&move; if ($^O eq 'MacOS') { *_protect = sub { MacPerl::MakeFSSpec($_[0]) }; } else { *_protect = sub { "./$_[0]" }; } # &syscopy is an XSUB under OS/2 unless (defined &syscopy) { if ($^O eq 'VMS') { *syscopy = \&rmscopy; } elsif ($^O eq 'mpeix') { *syscopy = sub { return 0 unless @_ == 2; # Use the MPE cp program in order to # preserve MPE file attributes. return system('/bin/cp', '-f', $_[0], $_[1]) == 0; }; } elsif ($^O eq 'MSWin32') { *syscopy = sub { return 0 unless @_ == 2; return Win32::CopyFile(@_, 1); }; } elsif ($macfiles) { *syscopy = sub { my($from, $to) = @_; my($dir, $toname); return 0 unless -e $from; if ($to =~ /(.*:)([^:]+):?$/) { ($dir, $toname) = ($1, $2); } else { ($dir, $toname) = (":", $to); } unlink($to); Mac::MoreFiles::FSpFileCopy($from, $dir, $toname, 1); }; } else { $Syscopy_is_copy = 1; *syscopy = \© } } 1; __END__ #line 459