RiscOS is case-insensitive
[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
71be2cbc 10use strict;
f716a1dd 11use Carp;
55497cff 12use UNIVERSAL qw(isa);
71be2cbc 13use vars qw(@ISA @EXPORT @EXPORT_OK $VERSION $Too_Big
14 &copy &syscopy &cp &mv);
15
16# Note that this module implements only *part* of the API defined by
17# the File/Copy.pm module of the File-Tools-2.0 package. However, that
18# package has not yet been updated to work with Perl 5.004, and so it
19# would be a Bad Thing for the CPAN module to grab it and replace this
20# module. Therefore, we set this module's version higher than 2.0.
e6434134 21$VERSION = '2.02';
f716a1dd 22
71be2cbc 23require Exporter;
24@ISA = qw(Exporter);
25@EXPORT = qw(copy move);
26@EXPORT_OK = qw(cp mv);
f716a1dd 27
441496b2 28$Too_Big = 1024 * 1024 * 2;
f716a1dd 29
71be2cbc 30sub _catname { # Will be replaced by File::Spec when it arrives
31 my($from, $to) = @_;
32 if (not defined &basename) {
33 require File::Basename;
34 import File::Basename 'basename';
35 }
36 if ($^O eq 'VMS') { $to = VMS::Filespec::vmspath($to) . basename($from); }
37 elsif ($^O eq 'MacOS') { $to .= ':' . basename($from); }
38 elsif ($to =~ m|\\|) { $to .= '\\' . basename($from); }
39 else { $to .= '/' . basename($from); }
f716a1dd 40}
41
42sub copy {
71be2cbc 43 croak("Usage: copy(FROM, TO [, BUFFERSIZE]) ")
f716a1dd 44 unless(@_ == 2 || @_ == 3);
45
46 my $from = shift;
47 my $to = shift;
71be2cbc 48
49 my $from_a_handle = (ref($from)
50 ? (ref($from) eq 'GLOB'
51 || isa($from, 'GLOB') || isa($from, 'IO::Handle'))
52 : (ref(\$from) eq 'GLOB'));
53 my $to_a_handle = (ref($to)
54 ? (ref($to) eq 'GLOB'
55 || isa($to, 'GLOB') || isa($to, 'IO::Handle'))
56 : (ref(\$to) eq 'GLOB'));
57
58 if (!$from_a_handle && !$to_a_handle && -d $to && ! -d $from) {
59 $to = _catname($from, $to);
60 }
61
62 if (defined &syscopy && \&syscopy != \&copy
e6434134 63 && !$to_a_handle
64 && !($from_a_handle && $^O eq 'os2')) # OS/2 cannot handle handles
71be2cbc 65 {
66 return syscopy($from, $to);
67 }
68
69 my $closefrom = 0;
70 my $closeto = 0;
f716a1dd 71 my ($size, $status, $r, $buf);
72 local(*FROM, *TO);
48a5c399 73 local($\) = '';
f716a1dd 74
71be2cbc 75 if ($from_a_handle) {
76 *FROM = *$from{FILEHANDLE};
f716a1dd 77 } else {
71be2cbc 78 $from = "./$from" if $from =~ /^\s/;
79 open(FROM, "< $from\0") or goto fail_open1;
80 binmode FROM or die "($!,$^E)";
f716a1dd 81 $closefrom = 1;
71be2cbc 82 }
83
84 if ($to_a_handle) {
85 *TO = *$to{FILEHANDLE};
86 } else {
87 $to = "./$to" if $to =~ /^\s/;
88 open(TO,"> $to\0") or goto fail_open2;
89 binmode TO or die "($!,$^E)";
90 $closeto = 1;
91 }
f716a1dd 92
93 if (@_) {
94 $size = shift(@_) + 0;
95 croak("Bad buffer size for copy: $size\n") unless ($size > 0);
96 } else {
97 $size = -s FROM;
98 $size = 1024 if ($size < 512);
441496b2 99 $size = $Too_Big if ($size > $Too_Big);
f716a1dd 100 }
101
71be2cbc 102 $! = 0;
103 for (;;) {
104 my ($r, $w, $t);
105 defined($r = sysread(FROM, $buf, $size))
106 or goto fail_inner;
107 last unless $r;
108 for ($w = 0; $w < $r; $w += $t) {
109 $t = syswrite(TO, $buf, $r - $w, $w)
110 or goto fail_inner;
f716a1dd 111 }
112 }
71be2cbc 113
f716a1dd 114 close(TO) || goto fail_open2 if $closeto;
115 close(FROM) || goto fail_open1 if $closefrom;
71be2cbc 116
48a5c399 117 # Use this idiom to avoid uninitialized value warning.
f716a1dd 118 return 1;
119
120 # All of these contortions try to preserve error messages...
121 fail_inner:
122 if ($closeto) {
123 $status = $!;
124 $! = 0;
125 close TO;
126 $! = $status unless $!;
127 }
128 fail_open2:
129 if ($closefrom) {
130 $status = $!;
131 $! = 0;
132 close FROM;
133 $! = $status unless $!;
134 }
135 fail_open1:
f716a1dd 136 return 0;
137}
9b957b78 138
441496b2 139sub move {
71be2cbc 140 my($from,$to) = @_;
141 my($copied,$fromsz,$tosz1,$tomt1,$tosz2,$tomt2,$sts,$ossts);
441496b2 142
71be2cbc 143 if (-d $to && ! -d $from) {
144 $to = _catname($from, $to);
145 }
146
147 ($tosz1,$tomt1) = (stat($to))[7,9];
148 $fromsz = -s $from;
e6434134 149 if ($^O eq 'os2' and defined $tosz1 and defined $fromsz) {
150 # will not rename with overwrite
151 unlink $to;
152 }
71be2cbc 153 return 1 if rename $from, $to;
154
155 ($sts,$ossts) = ($! + 0, $^E + 0);
156 # Did rename return an error even though it succeeded, because $to
157 # is on a remote NFS file system, and NFS lost the server's ack?
158 return 1 if defined($fromsz) && !-e $from && # $from disappeared
159 (($tosz2,$tomt2) = (stat($to))[7,9]) && # $to's there
160 ($tosz1 != $tosz2 or $tomt1 != $tomt2) && # and changed
161 $tosz2 == $fromsz; # it's all there
441496b2 162
71be2cbc 163 ($tosz1,$tomt1) = (stat($to))[7,9]; # just in case rename did something
164 return 1 if ($copied = copy($from,$to)) && unlink($from);
441496b2 165
71be2cbc 166 ($tosz2,$tomt2) = ((stat($to))[7,9],0,0) if defined $tomt1;
167 unlink($to) if !defined($tomt1) or $tomt1 != $tomt2 or $tosz1 != $tosz2;
168 ($!,$^E) = ($sts,$ossts);
169 return 0;
441496b2 170}
9b957b78 171
71be2cbc 172*cp = \&copy;
173*mv = \&move;
174
9b957b78 175# &syscopy is an XSUB under OS/2
441496b2 176*syscopy = ($^O eq 'VMS' ? \&rmscopy : \&copy) unless defined &syscopy;
f716a1dd 177
1781;
179
180__END__
a5f75d66 181
f716a1dd 182=head1 NAME
183
184File::Copy - Copy files or filehandles
185
a5f75d66 186=head1 SYNOPSIS
f716a1dd 187
188 use File::Copy;
189
190 copy("file1","file2");
191 copy("Copy.pm",\*STDOUT);'
441496b2 192 move("/dev1/fileA","/dev2/fileB");
f716a1dd 193
194 use POSIX;
195 use File::Copy cp;
196
197 $n=FileHandle->new("/dev/null","r");
198 cp($n,"x");'
199
200=head1 DESCRIPTION
201
441496b2 202The File::Copy module provides two basic functions, C<copy> and
203C<move>, which are useful for getting the contents of a file from
204one place to another.
205
206=over 4
207
208=item *
209
210The C<copy> function takes two
f716a1dd 211parameters: a file to copy from and a file to copy to. Either
212argument may be a string, a FileHandle reference or a FileHandle
213glob. Obviously, if the first argument is a filehandle of some
214sort, it will be read from, and if it is a file I<name> it will
215be opened for reading. Likewise, the second argument will be
e6434134 216written to (and created if need be).
71be2cbc 217
218B<Note that passing in
9b957b78 219files as handles instead of names may lead to loss of information
220on some operating systems; it is recommended that you use file
e6434134 221names whenever possible.> Files are opened in binary mode where
222applicable. To get a consistent behavour when copying from a
223filehandle to a file, use C<binmode> on the filehandle.
f716a1dd 224
225An optional third parameter can be used to specify the buffer
226size used for copying. This is the number of bytes from the
227first file, that wil be held in memory at any given time, before
228being written to the second file. The default buffer size depends
229upon the file, but will generally be the whole file (up to 2Mb), or
2301k for filehandles that do not reference files (eg. sockets).
231
232You may use the syntax C<use File::Copy "cp"> to get at the
233"cp" alias for this function. The syntax is I<exactly> the same.
234
441496b2 235=item *
236
237The C<move> function also takes two parameters: the current name
71be2cbc 238and the intended name of the file to be moved. If the destination
239already exists and is a directory, and the source is not a
240directory, then the source file will be renamed into the directory
241specified by the destination.
242
243If possible, move() will simply rename the file. Otherwise, it copies
244the file to the new location and deletes the original. If an error occurs
245during this copy-and-delete process, you may be left with a (possibly partial)
441496b2 246copy of the file under the destination name.
247
248You may use the "mv" alias for this function in the same way that
249you may use the "cp" alias for C<copy>.
250
251=back
252
9b957b78 253File::Copy also provides the C<syscopy> routine, which copies the
254file specified in the first parameter to the file specified in the
255second parameter, preserving OS-specific attributes and file
256structure. For Unix systems, this is equivalent to the simple
257C<copy> routine. For VMS systems, this calls the C<rmscopy>
258routine (see below). For OS/2 systems, this calls the C<syscopy>
259XSUB directly.
260
55497cff 261=head2 Special behavior if C<syscopy> is defined (VMS and OS/2)
9b957b78 262
71be2cbc 263If both arguments to C<copy> are not file handles,
264then C<copy> will perform a "system copy" of
9b957b78 265the input file to a new output file, in order to preserve file
266attributes, indexed file structure, I<etc.> The buffer size
71be2cbc 267parameter is ignored. If either argument to C<copy> is a
268handle to an opened file, then data is copied using Perl
9b957b78 269operators, and no effort is made to preserve file attributes
270or record structure.
271
55497cff 272The system copy routine may also be called directly under VMS and OS/2
273as C<File::Copy::syscopy> (or under VMS as C<File::Copy::rmscopy>, which
71be2cbc 274is the routine that does the actual work for syscopy).
9b957b78 275
441496b2 276=over 4
55497cff 277
9b957b78 278=item rmscopy($from,$to[,$date_flag])
279
71be2cbc 280The first and second arguments may be strings, typeglobs, typeglob
281references, or objects inheriting from IO::Handle;
282they are used in all cases to obtain the
9b957b78 283I<filespec> of the input and output files, respectively. The
284name and type of the input file are used as defaults for the
285output file, if necessary.
286
287A new version of the output file is always created, which
288inherits the structure and RMS attributes of the input file,
289except for owner and protections (and possibly timestamps;
290see below). All data from the input file is copied to the
291output file; if either of the first two parameters to C<rmscopy>
292is a file handle, its position is unchanged. (Note that this
293means a file handle pointing to the output file will be
294associated with an old version of that file after C<rmscopy>
295returns, not the newly created version.)
296
297The third parameter is an integer flag, which tells C<rmscopy>
1fef88e7 298how to handle timestamps. If it is E<lt> 0, none of the input file's
299timestamps are propagated to the output file. If it is E<gt> 0, then
9b957b78 300it is interpreted as a bitmask: if bit 0 (the LSB) is set, then
301timestamps other than the revision date are propagated; if bit 1
302is set, the revision date is propagated. If the third parameter
303to C<rmscopy> is 0, then it behaves much like the DCL COPY command:
304if the name or type of the output file was explicitly specified,
305then no timestamps are propagated, but if they were taken implicitly
306from the input filespec, then all timestamps other than the
307revision date are propagated. If this parameter is not supplied,
308it defaults to 0.
309
310Like C<copy>, C<rmscopy> returns 1 on success. If an error occurs,
311it sets C<$!>, deletes the output file, and returns 0.
312
55497cff 313=back
314
f716a1dd 315=head1 RETURN
316
441496b2 317All functions return 1 on success, 0 on failure.
318$! will be set if an error was encountered.
f716a1dd 319
320=head1 AUTHOR
321
441496b2 322File::Copy was written by Aaron Sherman I<E<lt>ajs@ajs.comE<gt>> in 1995,
323and updated by Charles Bailey I<E<lt>bailey@genetics.upenn.eduE<gt>> in 1996.
f716a1dd 324
325=cut
441496b2 326