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