Re: [perl #41555] Bug in File::Find on Windows when target
[p5sagit/p5-mst-13.2.git] / lib / File / Copy.pm
CommitLineData
f716a1dd 1# File/Copy.pm. Written in 1994 by Aaron Sherman <ajs@ajs.com>. This
2# source code has been placed in the public domain by the author.
3# Please be kind and preserve the documentation.
4#
71be2cbc 5# Additions copyright 1996 by Charles Bailey. Permission is granted
6# to distribute the revised code under the same terms as Perl itself.
f716a1dd 7
8package File::Copy;
9
3b825e41 10use 5.006;
71be2cbc 11use strict;
b395063c 12use warnings;
6c254d95 13use File::Spec;
96a91e01 14use Config;
91ca337e 15# During perl build, we need File::Copy but Fcntl might not be built yet
16my $Fcntl_loaded = eval q{ use Fcntl qw [O_CREAT O_WRONLY O_TRUNC]; 1 };
17f410f9 17our(@ISA, @EXPORT, @EXPORT_OK, $VERSION, $Too_Big, $Syscopy_is_copy);
18sub copy;
19sub syscopy;
20sub cp;
21sub mv;
71be2cbc 22
9c76cba2 23$VERSION = '2.13';
f716a1dd 24
71be2cbc 25require Exporter;
26@ISA = qw(Exporter);
27@EXPORT = qw(copy move);
28@EXPORT_OK = qw(cp mv);
f716a1dd 29
441496b2 30$Too_Big = 1024 * 1024 * 2;
f716a1dd 31
8878f897 32sub croak {
33 require Carp;
34 goto &Carp::croak;
35}
36
754f2cd0 37sub carp {
38 require Carp;
39 goto &Carp::carp;
40}
41
bcdb689b 42my $macfiles;
43if ($^O eq 'MacOS') {
44 $macfiles = eval { require Mac::MoreFiles };
45 warn 'Mac::MoreFiles could not be loaded; using non-native syscopy'
3a2263fe 46 if $@ && $^W;
bcdb689b 47}
48
6c254d95 49sub _catname {
71be2cbc 50 my($from, $to) = @_;
51 if (not defined &basename) {
52 require File::Basename;
53 import File::Basename 'basename';
54 }
6c254d95 55
56 if ($^O eq 'MacOS') {
57 # a partial dir name that's valid only in the cwd (e.g. 'tmp')
58 $to = ':' . $to if $to !~ /:/;
59 }
60
61 return File::Spec->catfile($to, basename($from));
f716a1dd 62}
63
236a0738 64# _eq($from, $to) tells whether $from and $to are identical
65# works for strings and references
66sub _eq {
67 return $_[0] == $_[1] if ref $_[0] && ref $_[1];
68 return $_[0] eq $_[1] if !ref $_[0] && !ref $_[1];
69 return "";
70}
71
f716a1dd 72sub copy {
71be2cbc 73 croak("Usage: copy(FROM, TO [, BUFFERSIZE]) ")
f716a1dd 74 unless(@_ == 2 || @_ == 3);
75
76 my $from = shift;
77 my $to = shift;
71be2cbc 78
671637fe 79 my $size;
80 if (@_) {
81 $size = shift(@_) + 0;
82 croak("Bad buffer size for copy: $size\n") unless ($size > 0);
83 }
84
71be2cbc 85 my $from_a_handle = (ref($from)
86 ? (ref($from) eq 'GLOB'
d704f39a 87 || UNIVERSAL::isa($from, 'GLOB')
88 || UNIVERSAL::isa($from, 'IO::Handle'))
71be2cbc 89 : (ref(\$from) eq 'GLOB'));
90 my $to_a_handle = (ref($to)
91 ? (ref($to) eq 'GLOB'
d704f39a 92 || UNIVERSAL::isa($to, 'GLOB')
93 || UNIVERSAL::isa($to, 'IO::Handle'))
71be2cbc 94 : (ref(\$to) eq 'GLOB'));
95
236a0738 96 if (_eq($from, $to)) { # works for references, too
754f2cd0 97 carp("'$from' and '$to' are identical (not copied)");
98 # The "copy" was a success as the source and destination contain
99 # the same data.
100 return 1;
96a91e01 101 }
102
ac7b122d 103 if ((($Config{d_symlink} && $Config{d_readlink}) || $Config{d_link}) &&
4c38808d 104 !($^O eq 'MSWin32' || $^O eq 'os2')) {
ac7b122d 105 my @fs = stat($from);
106 if (@fs) {
96a91e01 107 my @ts = stat($to);
ac7b122d 108 if (@ts && $fs[0] == $ts[0] && $fs[1] == $ts[1]) {
754f2cd0 109 carp("'$from' and '$to' are identical (not copied)");
110 return 0;
96a91e01 111 }
112 }
113 }
114
71be2cbc 115 if (!$from_a_handle && !$to_a_handle && -d $to && ! -d $from) {
116 $to = _catname($from, $to);
117 }
118
1a04d035 119 if (defined &syscopy && !$Syscopy_is_copy
e6434134 120 && !$to_a_handle
1d84e8df 121 && !($from_a_handle && $^O eq 'os2' ) # OS/2 cannot handle handles
122 && !($from_a_handle && $^O eq 'mpeix') # and neither can MPE/iX.
7509b657 123 && !($from_a_handle && $^O eq 'MSWin32')
fa648be5 124 && !($from_a_handle && $^O eq 'MacOS')
2986a63f 125 && !($from_a_handle && $^O eq 'NetWare')
1a04d035 126 )
71be2cbc 127 {
4c38808d 128 my $copy_to = $to;
129
130 if ($^O eq 'VMS' && -e $from) {
131
132 if (! -d $to && ! -d $from) {
133
134 # VMS has sticky defaults on extensions, which means that
135 # if there is a null extension on the destination file, it
136 # will inherit the extension of the source file
137 # So add a '.' for a null extension.
138
139 $copy_to = VMS::Filespec::vmsify($to);
140 my ($vol, $dirs, $file) = File::Spec->splitpath($copy_to);
141 $file = $file . '.' unless ($file =~ /(?<!\^)\./);
142 $copy_to = File::Spec->catpath($vol, $dirs, $file);
143
144 # Get rid of the old versions to be like UNIX
145 1 while unlink $copy_to;
146 }
147 }
148
149 return syscopy($from, $copy_to);
71be2cbc 150 }
151
152 my $closefrom = 0;
153 my $closeto = 0;
671637fe 154 my ($status, $r, $buf);
48a5c399 155 local($\) = '';
f716a1dd 156
23ba2776 157 my $from_h;
71be2cbc 158 if ($from_a_handle) {
23ba2776 159 $from_h = $from;
f716a1dd 160 } else {
cfa308ca 161 open $from_h, "<", $from or goto fail_open1;
23ba2776 162 binmode $from_h or die "($!,$^E)";
f716a1dd 163 $closefrom = 1;
1a04d035 164 }
165
671637fe 166 # Seems most logical to do this here, in case future changes would want to
167 # make this croak for some reason.
168 unless (defined $size) {
169 $size = tied(*$from_h) ? 0 : -s $from_h || 0;
170 $size = 1024 if ($size < 512);
171 $size = $Too_Big if ($size > $Too_Big);
172 }
173
23ba2776 174 my $to_h;
71be2cbc 175 if ($to_a_handle) {
23ba2776 176 $to_h = $to;
1a04d035 177 } else {
fa648be5 178 $to = _protect($to) if $to =~ /^\s/s;
91ca337e 179 if ($Fcntl_loaded) {
180 my $perm = (stat $from_h) [2] & 0xFFF;
181 sysopen $to_h, $to, O_CREAT() | O_TRUNC() | O_WRONLY(), $perm
182 or goto fail_open2;
183 }
184 else {
185 $to_h = \do { local *FH };
186 open $to_h, ">", $to or goto fail_open2;
187 }
188 binmode $to_h or die "($!,$^E)";
71be2cbc 189 $closeto = 1;
1a04d035 190 }
f716a1dd 191
71be2cbc 192 $! = 0;
193 for (;;) {
194 my ($r, $w, $t);
23ba2776 195 defined($r = sysread($from_h, $buf, $size))
71be2cbc 196 or goto fail_inner;
197 last unless $r;
198 for ($w = 0; $w < $r; $w += $t) {
23ba2776 199 $t = syswrite($to_h, $buf, $r - $w, $w)
71be2cbc 200 or goto fail_inner;
f716a1dd 201 }
202 }
71be2cbc 203
23ba2776 204 close($to_h) || goto fail_open2 if $closeto;
205 close($from_h) || goto fail_open1 if $closefrom;
71be2cbc 206
48a5c399 207 # Use this idiom to avoid uninitialized value warning.
f716a1dd 208 return 1;
1a04d035 209
f716a1dd 210 # All of these contortions try to preserve error messages...
211 fail_inner:
212 if ($closeto) {
213 $status = $!;
214 $! = 0;
23ba2776 215 close $to_h;
f716a1dd 216 $! = $status unless $!;
217 }
218 fail_open2:
219 if ($closefrom) {
220 $status = $!;
221 $! = 0;
23ba2776 222 close $from_h;
f716a1dd 223 $! = $status unless $!;
224 }
225 fail_open1:
f716a1dd 226 return 0;
227}
9b957b78 228
441496b2 229sub move {
754f2cd0 230 croak("Usage: move(FROM, TO) ") unless @_ == 2;
231
71be2cbc 232 my($from,$to) = @_;
754f2cd0 233
fa76202e 234 my($fromsz,$tosz1,$tomt1,$tosz2,$tomt2,$sts,$ossts);
441496b2 235
71be2cbc 236 if (-d $to && ! -d $from) {
237 $to = _catname($from, $to);
238 }
239
240 ($tosz1,$tomt1) = (stat($to))[7,9];
241 $fromsz = -s $from;
e6434134 242 if ($^O eq 'os2' and defined $tosz1 and defined $fromsz) {
243 # will not rename with overwrite
244 unlink $to;
245 }
4c38808d 246
247 my $rename_to = $to;
248 if (-$^O eq 'VMS' && -e $from) {
249
250 if (! -d $to && ! -d $from) {
251 # VMS has sticky defaults on extensions, which means that
252 # if there is a null extension on the destination file, it
253 # will inherit the extension of the source file
254 # So add a '.' for a null extension.
255
256 $rename_to = VMS::Filespec::vmsify($to);
257 my ($vol, $dirs, $file) = File::Spec->splitpath($rename_to);
258 $file = $file . '.' unless ($file =~ /(?<!\^)\./);
259 $rename_to = File::Spec->catpath($vol, $dirs, $file);
260
261 # Get rid of the old versions to be like UNIX
262 1 while unlink $rename_to;
263 }
264 }
265
266 return 1 if rename $from, $rename_to;
71be2cbc 267
71be2cbc 268 # Did rename return an error even though it succeeded, because $to
269 # is on a remote NFS file system, and NFS lost the server's ack?
270 return 1 if defined($fromsz) && !-e $from && # $from disappeared
271 (($tosz2,$tomt2) = (stat($to))[7,9]) && # $to's there
c9fbd0c8 272 ((!defined $tosz1) || # not before or
273 ($tosz1 != $tosz2 or $tomt1 != $tomt2)) && # was changed
71be2cbc 274 $tosz2 == $fromsz; # it's all there
1a04d035 275
71be2cbc 276 ($tosz1,$tomt1) = (stat($to))[7,9]; # just in case rename did something
762548ba 277
278 {
279 local $@;
280 eval {
754f2cd0 281 local $SIG{__DIE__};
762548ba 282 copy($from,$to) or die;
283 my($atime, $mtime) = (stat($from))[8,9];
284 utime($atime, $mtime, $to);
285 unlink($from) or die;
286 };
287 return 1 unless $@;
288 }
fa76202e 289 ($sts,$ossts) = ($! + 0, $^E + 0);
1a04d035 290
71be2cbc 291 ($tosz2,$tomt2) = ((stat($to))[7,9],0,0) if defined $tomt1;
292 unlink($to) if !defined($tomt1) or $tomt1 != $tomt2 or $tosz1 != $tosz2;
293 ($!,$^E) = ($sts,$ossts);
294 return 0;
441496b2 295}
9b957b78 296
71be2cbc 297*cp = \&copy;
298*mv = \&move;
299
9b957b78 300# &syscopy is an XSUB under OS/2
1d84e8df 301unless (defined &syscopy) {
302 if ($^O eq 'VMS') {
303 *syscopy = \&rmscopy;
304 } elsif ($^O eq 'mpeix') {
305 *syscopy = sub {
3f5ee302 306 return 0 unless @_ == 2;
1d84e8df 307 # Use the MPE cp program in order to
308 # preserve MPE file attributes.
309 return system('/bin/cp', '-f', $_[0], $_[1]) == 0;
310 };
cf2f24a4 311 } elsif ($^O eq 'MSWin32' && defined &DynaLoader::boot_DynaLoader) {
312 # Win32::CopyFile() fill only work if we can load Win32.xs
7509b657 313 *syscopy = sub {
314 return 0 unless @_ == 2;
315 return Win32::CopyFile(@_, 1);
316 };
bcdb689b 317 } elsif ($macfiles) {
fa648be5 318 *syscopy = sub {
319 my($from, $to) = @_;
320 my($dir, $toname);
321
322 return 0 unless -e $from;
323
324 if ($to =~ /(.*:)([^:]+):?$/) {
325 ($dir, $toname) = ($1, $2);
326 } else {
327 ($dir, $toname) = (":", $to);
328 }
329
330 unlink($to);
331 Mac::MoreFiles::FSpFileCopy($from, $dir, $toname, 1);
332 };
1d84e8df 333 } else {
1a04d035 334 $Syscopy_is_copy = 1;
1d84e8df 335 *syscopy = \&copy;
336 }
337}
f716a1dd 338
3391;
340
341__END__
a5f75d66 342
f716a1dd 343=head1 NAME
344
345File::Copy - Copy files or filehandles
346
a5f75d66 347=head1 SYNOPSIS
f716a1dd 348
5ce10329 349 use File::Copy;
f716a1dd 350
5ce10329 351 copy("file1","file2") or die "Copy failed: $!";
352 copy("Copy.pm",\*STDOUT);
441496b2 353 move("/dev1/fileA","/dev2/fileB");
f716a1dd 354
78e38bb6 355 use File::Copy "cp";
f716a1dd 356
23f3aea0 357 $n = FileHandle->new("/a/file","r");
c6dfe06b 358 cp($n,"x");
f716a1dd 359
360=head1 DESCRIPTION
361
441496b2 362The File::Copy module provides two basic functions, C<copy> and
363C<move>, which are useful for getting the contents of a file from
364one place to another.
365
366=over 4
367
0cdecedb 368=item copy
369X<copy> X<cp>
441496b2 370
371The C<copy> function takes two
f716a1dd 372parameters: a file to copy from and a file to copy to. Either
373argument may be a string, a FileHandle reference or a FileHandle
374glob. Obviously, if the first argument is a filehandle of some
375sort, it will be read from, and if it is a file I<name> it will
376be opened for reading. Likewise, the second argument will be
96a91e01 377written to (and created if need be). Trying to copy a file on top
378of itself is a fatal error.
71be2cbc 379
380B<Note that passing in
9b957b78 381files as handles instead of names may lead to loss of information
382on some operating systems; it is recommended that you use file
e6434134 383names whenever possible.> Files are opened in binary mode where
8dcee03e 384applicable. To get a consistent behaviour when copying from a
e6434134 385filehandle to a file, use C<binmode> on the filehandle.
f716a1dd 386
387An optional third parameter can be used to specify the buffer
388size used for copying. This is the number of bytes from the
3a964d77 389first file, that will be held in memory at any given time, before
f716a1dd 390being written to the second file. The default buffer size depends
338de517 391upon the file, but will generally be the whole file (up to 2MB), or
f716a1dd 3921k for filehandles that do not reference files (eg. sockets).
393
394You may use the syntax C<use File::Copy "cp"> to get at the
395"cp" alias for this function. The syntax is I<exactly> the same.
396
9c76cba2 397As of version 2.13, on UNIX systems, "copy" will preserve permission
398bits like the shell utility C<cp> would do.
399
0cdecedb 400=item move
401X<move> X<mv> X<rename>
441496b2 402
403The C<move> function also takes two parameters: the current name
71be2cbc 404and the intended name of the file to be moved. If the destination
405already exists and is a directory, and the source is not a
406directory, then the source file will be renamed into the directory
407specified by the destination.
408
409If possible, move() will simply rename the file. Otherwise, it copies
410the file to the new location and deletes the original. If an error occurs
411during this copy-and-delete process, you may be left with a (possibly partial)
441496b2 412copy of the file under the destination name.
413
414You may use the "mv" alias for this function in the same way that
415you may use the "cp" alias for C<copy>.
416
0cdecedb 417=item syscopy
418X<syscopy>
441496b2 419
9b957b78 420File::Copy also provides the C<syscopy> routine, which copies the
421file specified in the first parameter to the file specified in the
422second parameter, preserving OS-specific attributes and file
423structure. For Unix systems, this is equivalent to the simple
f1442e8b 424C<copy> routine, which doesn't preserve OS-specific attributes. For
425VMS systems, this calls the C<rmscopy> routine (see below). For OS/2
426systems, this calls the C<syscopy> XSUB directly. For Win32 systems,
427this calls C<Win32::CopyFile>.
9b957b78 428
bcdb689b 429On Mac OS (Classic), C<syscopy> calls C<Mac::MoreFiles::FSpFileCopy>,
430if available.
431
338de517 432B<Special behaviour if C<syscopy> is defined (OS/2, VMS and Win32)>:
9b957b78 433
71be2cbc 434If both arguments to C<copy> are not file handles,
435then C<copy> will perform a "system copy" of
9b957b78 436the input file to a new output file, in order to preserve file
437attributes, indexed file structure, I<etc.> The buffer size
71be2cbc 438parameter is ignored. If either argument to C<copy> is a
439handle to an opened file, then data is copied using Perl
9b957b78 440operators, and no effort is made to preserve file attributes
441or record structure.
442
55497cff 443The system copy routine may also be called directly under VMS and OS/2
444as C<File::Copy::syscopy> (or under VMS as C<File::Copy::rmscopy>, which
71be2cbc 445is the routine that does the actual work for syscopy).
9b957b78 446
447=item rmscopy($from,$to[,$date_flag])
0cdecedb 448X<rmscopy>
9b957b78 449
71be2cbc 450The first and second arguments may be strings, typeglobs, typeglob
451references, or objects inheriting from IO::Handle;
452they are used in all cases to obtain the
9b957b78 453I<filespec> of the input and output files, respectively. The
454name and type of the input file are used as defaults for the
455output file, if necessary.
456
457A new version of the output file is always created, which
458inherits the structure and RMS attributes of the input file,
459except for owner and protections (and possibly timestamps;
460see below). All data from the input file is copied to the
461output file; if either of the first two parameters to C<rmscopy>
462is a file handle, its position is unchanged. (Note that this
463means a file handle pointing to the output file will be
464associated with an old version of that file after C<rmscopy>
465returns, not the newly created version.)
466
467The third parameter is an integer flag, which tells C<rmscopy>
1fef88e7 468how to handle timestamps. If it is E<lt> 0, none of the input file's
469timestamps are propagated to the output file. If it is E<gt> 0, then
9b957b78 470it is interpreted as a bitmask: if bit 0 (the LSB) is set, then
471timestamps other than the revision date are propagated; if bit 1
472is set, the revision date is propagated. If the third parameter
473to C<rmscopy> is 0, then it behaves much like the DCL COPY command:
474if the name or type of the output file was explicitly specified,
475then no timestamps are propagated, but if they were taken implicitly
476from the input filespec, then all timestamps other than the
477revision date are propagated. If this parameter is not supplied,
478it defaults to 0.
479
480Like C<copy>, C<rmscopy> returns 1 on success. If an error occurs,
481it sets C<$!>, deletes the output file, and returns 0.
482
55497cff 483=back
484
f716a1dd 485=head1 RETURN
486
441496b2 487All functions return 1 on success, 0 on failure.
488$! will be set if an error was encountered.
f716a1dd 489
6c254d95 490=head1 NOTES
491
492=over 4
493
494=item *
495
496On Mac OS (Classic), the path separator is ':', not '/', and the
497current directory is denoted as ':', not '.'. You should be careful
498about specifying relative pathnames. While a full path always begins
499with a volume name, a relative pathname should always begin with a
500':'. If specifying a volume name only, a trailing ':' is required.
501
502E.g.
503
504 copy("file1", "tmp"); # creates the file 'tmp' in the current directory
505 copy("file1", ":tmp:"); # creates :tmp:file1
506 copy("file1", ":tmp"); # same as above
0cdecedb 507 copy("file1", "tmp"); # same as above, if 'tmp' is a directory (but don't do
6c254d95 508 # that, since it may cause confusion, see example #1)
509 copy("file1", "tmp:file1"); # error, since 'tmp:' is not a volume
510 copy("file1", ":tmp:file1"); # ok, partial path
511 copy("file1", "DataHD:"); # creates DataHD:file1
0cdecedb 512
907fbfa1 513 move("MacintoshHD:fileA", "DataHD:fileB"); # moves (doesn't copy) files from one
6c254d95 514 # volume to another
515
516=back
517
f716a1dd 518=head1 AUTHOR
519
441496b2 520File::Copy was written by Aaron Sherman I<E<lt>ajs@ajs.comE<gt>> in 1995,
bd3fa61c 521and updated by Charles Bailey I<E<lt>bailey@newman.upenn.eduE<gt>> in 1996.
f716a1dd 522
523=cut
441496b2 524