xref: /onnv-gate/usr/src/cmd/perl/5.8.4/distrib/lib/File/Copy.pm (revision 0:68f95e015346)
1*0Sstevel@tonic-gate# File/Copy.pm. Written in 1994 by Aaron Sherman <ajs@ajs.com>. This
2*0Sstevel@tonic-gate# source code has been placed in the public domain by the author.
3*0Sstevel@tonic-gate# Please be kind and preserve the documentation.
4*0Sstevel@tonic-gate#
5*0Sstevel@tonic-gate# Additions copyright 1996 by Charles Bailey.  Permission is granted
6*0Sstevel@tonic-gate# to distribute the revised code under the same terms as Perl itself.
7*0Sstevel@tonic-gate
8*0Sstevel@tonic-gatepackage File::Copy;
9*0Sstevel@tonic-gate
10*0Sstevel@tonic-gateuse 5.006;
11*0Sstevel@tonic-gateuse strict;
12*0Sstevel@tonic-gateuse warnings;
13*0Sstevel@tonic-gateuse Carp;
14*0Sstevel@tonic-gateuse File::Spec;
15*0Sstevel@tonic-gateuse Config;
16*0Sstevel@tonic-gateour(@ISA, @EXPORT, @EXPORT_OK, $VERSION, $Too_Big, $Syscopy_is_copy);
17*0Sstevel@tonic-gatesub copy;
18*0Sstevel@tonic-gatesub syscopy;
19*0Sstevel@tonic-gatesub cp;
20*0Sstevel@tonic-gatesub mv;
21*0Sstevel@tonic-gate
22*0Sstevel@tonic-gate# Note that this module implements only *part* of the API defined by
23*0Sstevel@tonic-gate# the File/Copy.pm module of the File-Tools-2.0 package.  However, that
24*0Sstevel@tonic-gate# package has not yet been updated to work with Perl 5.004, and so it
25*0Sstevel@tonic-gate# would be a Bad Thing for the CPAN module to grab it and replace this
26*0Sstevel@tonic-gate# module.  Therefore, we set this module's version higher than 2.0.
27*0Sstevel@tonic-gate$VERSION = '2.07';
28*0Sstevel@tonic-gate
29*0Sstevel@tonic-gaterequire Exporter;
30*0Sstevel@tonic-gate@ISA = qw(Exporter);
31*0Sstevel@tonic-gate@EXPORT = qw(copy move);
32*0Sstevel@tonic-gate@EXPORT_OK = qw(cp mv);
33*0Sstevel@tonic-gate
34*0Sstevel@tonic-gate$Too_Big = 1024 * 1024 * 2;
35*0Sstevel@tonic-gate
36*0Sstevel@tonic-gatemy $macfiles;
37*0Sstevel@tonic-gateif ($^O eq 'MacOS') {
38*0Sstevel@tonic-gate	$macfiles = eval { require Mac::MoreFiles };
39*0Sstevel@tonic-gate	warn 'Mac::MoreFiles could not be loaded; using non-native syscopy'
40*0Sstevel@tonic-gate		if $@ && $^W;
41*0Sstevel@tonic-gate}
42*0Sstevel@tonic-gate
43*0Sstevel@tonic-gatesub _catname {
44*0Sstevel@tonic-gate    my($from, $to) = @_;
45*0Sstevel@tonic-gate    if (not defined &basename) {
46*0Sstevel@tonic-gate	require File::Basename;
47*0Sstevel@tonic-gate	import  File::Basename 'basename';
48*0Sstevel@tonic-gate    }
49*0Sstevel@tonic-gate
50*0Sstevel@tonic-gate    if ($^O eq 'MacOS') {
51*0Sstevel@tonic-gate	# a partial dir name that's valid only in the cwd (e.g. 'tmp')
52*0Sstevel@tonic-gate	$to = ':' . $to if $to !~ /:/;
53*0Sstevel@tonic-gate    }
54*0Sstevel@tonic-gate
55*0Sstevel@tonic-gate    return File::Spec->catfile($to, basename($from));
56*0Sstevel@tonic-gate}
57*0Sstevel@tonic-gate
58*0Sstevel@tonic-gatesub copy {
59*0Sstevel@tonic-gate    croak("Usage: copy(FROM, TO [, BUFFERSIZE]) ")
60*0Sstevel@tonic-gate      unless(@_ == 2 || @_ == 3);
61*0Sstevel@tonic-gate
62*0Sstevel@tonic-gate    my $from = shift;
63*0Sstevel@tonic-gate    my $to = shift;
64*0Sstevel@tonic-gate
65*0Sstevel@tonic-gate    my $from_a_handle = (ref($from)
66*0Sstevel@tonic-gate			 ? (ref($from) eq 'GLOB'
67*0Sstevel@tonic-gate			    || UNIVERSAL::isa($from, 'GLOB')
68*0Sstevel@tonic-gate                            || UNIVERSAL::isa($from, 'IO::Handle'))
69*0Sstevel@tonic-gate			 : (ref(\$from) eq 'GLOB'));
70*0Sstevel@tonic-gate    my $to_a_handle =   (ref($to)
71*0Sstevel@tonic-gate			 ? (ref($to) eq 'GLOB'
72*0Sstevel@tonic-gate			    || UNIVERSAL::isa($to, 'GLOB')
73*0Sstevel@tonic-gate                            || UNIVERSAL::isa($to, 'IO::Handle'))
74*0Sstevel@tonic-gate			 : (ref(\$to) eq 'GLOB'));
75*0Sstevel@tonic-gate
76*0Sstevel@tonic-gate    if ($from eq $to) { # works for references, too
77*0Sstevel@tonic-gate	croak("'$from' and '$to' are identical (not copied)");
78*0Sstevel@tonic-gate    }
79*0Sstevel@tonic-gate
80*0Sstevel@tonic-gate    if ((($Config{d_symlink} && $Config{d_readlink}) || $Config{d_link}) &&
81*0Sstevel@tonic-gate	!($^O eq 'MSWin32' || $^O eq 'os2' || $^O eq 'vms')) {
82*0Sstevel@tonic-gate	my @fs = stat($from);
83*0Sstevel@tonic-gate	if (@fs) {
84*0Sstevel@tonic-gate	    my @ts = stat($to);
85*0Sstevel@tonic-gate	    if (@ts && $fs[0] == $ts[0] && $fs[1] == $ts[1]) {
86*0Sstevel@tonic-gate		croak("'$from' and '$to' are identical (not copied)");
87*0Sstevel@tonic-gate	    }
88*0Sstevel@tonic-gate	}
89*0Sstevel@tonic-gate    }
90*0Sstevel@tonic-gate
91*0Sstevel@tonic-gate    if (!$from_a_handle && !$to_a_handle && -d $to && ! -d $from) {
92*0Sstevel@tonic-gate	$to = _catname($from, $to);
93*0Sstevel@tonic-gate    }
94*0Sstevel@tonic-gate
95*0Sstevel@tonic-gate    if (defined &syscopy && !$Syscopy_is_copy
96*0Sstevel@tonic-gate	&& !$to_a_handle
97*0Sstevel@tonic-gate	&& !($from_a_handle && $^O eq 'os2' )	# OS/2 cannot handle handles
98*0Sstevel@tonic-gate	&& !($from_a_handle && $^O eq 'mpeix')	# and neither can MPE/iX.
99*0Sstevel@tonic-gate	&& !($from_a_handle && $^O eq 'MSWin32')
100*0Sstevel@tonic-gate	&& !($from_a_handle && $^O eq 'MacOS')
101*0Sstevel@tonic-gate	&& !($from_a_handle && $^O eq 'NetWare')
102*0Sstevel@tonic-gate       )
103*0Sstevel@tonic-gate    {
104*0Sstevel@tonic-gate	return syscopy($from, $to);
105*0Sstevel@tonic-gate    }
106*0Sstevel@tonic-gate
107*0Sstevel@tonic-gate    my $closefrom = 0;
108*0Sstevel@tonic-gate    my $closeto = 0;
109*0Sstevel@tonic-gate    my ($size, $status, $r, $buf);
110*0Sstevel@tonic-gate    local($\) = '';
111*0Sstevel@tonic-gate
112*0Sstevel@tonic-gate    my $from_h;
113*0Sstevel@tonic-gate    if ($from_a_handle) {
114*0Sstevel@tonic-gate       $from_h = $from;
115*0Sstevel@tonic-gate    } else {
116*0Sstevel@tonic-gate	$from = _protect($from) if $from =~ /^\s/s;
117*0Sstevel@tonic-gate       $from_h = \do { local *FH };
118*0Sstevel@tonic-gate       open($from_h, "< $from\0") or goto fail_open1;
119*0Sstevel@tonic-gate       binmode $from_h or die "($!,$^E)";
120*0Sstevel@tonic-gate	$closefrom = 1;
121*0Sstevel@tonic-gate    }
122*0Sstevel@tonic-gate
123*0Sstevel@tonic-gate    my $to_h;
124*0Sstevel@tonic-gate    if ($to_a_handle) {
125*0Sstevel@tonic-gate       $to_h = $to;
126*0Sstevel@tonic-gate    } else {
127*0Sstevel@tonic-gate	$to = _protect($to) if $to =~ /^\s/s;
128*0Sstevel@tonic-gate       $to_h = \do { local *FH };
129*0Sstevel@tonic-gate       open($to_h,"> $to\0") or goto fail_open2;
130*0Sstevel@tonic-gate       binmode $to_h or die "($!,$^E)";
131*0Sstevel@tonic-gate	$closeto = 1;
132*0Sstevel@tonic-gate    }
133*0Sstevel@tonic-gate
134*0Sstevel@tonic-gate    if (@_) {
135*0Sstevel@tonic-gate	$size = shift(@_) + 0;
136*0Sstevel@tonic-gate	croak("Bad buffer size for copy: $size\n") unless ($size > 0);
137*0Sstevel@tonic-gate    } else {
138*0Sstevel@tonic-gate	$size = tied(*$from_h) ? 0 : -s $from_h || 0;
139*0Sstevel@tonic-gate	$size = 1024 if ($size < 512);
140*0Sstevel@tonic-gate	$size = $Too_Big if ($size > $Too_Big);
141*0Sstevel@tonic-gate    }
142*0Sstevel@tonic-gate
143*0Sstevel@tonic-gate    $! = 0;
144*0Sstevel@tonic-gate    for (;;) {
145*0Sstevel@tonic-gate	my ($r, $w, $t);
146*0Sstevel@tonic-gate       defined($r = sysread($from_h, $buf, $size))
147*0Sstevel@tonic-gate	    or goto fail_inner;
148*0Sstevel@tonic-gate	last unless $r;
149*0Sstevel@tonic-gate	for ($w = 0; $w < $r; $w += $t) {
150*0Sstevel@tonic-gate           $t = syswrite($to_h, $buf, $r - $w, $w)
151*0Sstevel@tonic-gate		or goto fail_inner;
152*0Sstevel@tonic-gate	}
153*0Sstevel@tonic-gate    }
154*0Sstevel@tonic-gate
155*0Sstevel@tonic-gate    close($to_h) || goto fail_open2 if $closeto;
156*0Sstevel@tonic-gate    close($from_h) || goto fail_open1 if $closefrom;
157*0Sstevel@tonic-gate
158*0Sstevel@tonic-gate    # Use this idiom to avoid uninitialized value warning.
159*0Sstevel@tonic-gate    return 1;
160*0Sstevel@tonic-gate
161*0Sstevel@tonic-gate    # All of these contortions try to preserve error messages...
162*0Sstevel@tonic-gate  fail_inner:
163*0Sstevel@tonic-gate    if ($closeto) {
164*0Sstevel@tonic-gate	$status = $!;
165*0Sstevel@tonic-gate	$! = 0;
166*0Sstevel@tonic-gate       close $to_h;
167*0Sstevel@tonic-gate	$! = $status unless $!;
168*0Sstevel@tonic-gate    }
169*0Sstevel@tonic-gate  fail_open2:
170*0Sstevel@tonic-gate    if ($closefrom) {
171*0Sstevel@tonic-gate	$status = $!;
172*0Sstevel@tonic-gate	$! = 0;
173*0Sstevel@tonic-gate       close $from_h;
174*0Sstevel@tonic-gate	$! = $status unless $!;
175*0Sstevel@tonic-gate    }
176*0Sstevel@tonic-gate  fail_open1:
177*0Sstevel@tonic-gate    return 0;
178*0Sstevel@tonic-gate}
179*0Sstevel@tonic-gate
180*0Sstevel@tonic-gatesub move {
181*0Sstevel@tonic-gate    my($from,$to) = @_;
182*0Sstevel@tonic-gate    my($fromsz,$tosz1,$tomt1,$tosz2,$tomt2,$sts,$ossts);
183*0Sstevel@tonic-gate
184*0Sstevel@tonic-gate    if (-d $to && ! -d $from) {
185*0Sstevel@tonic-gate	$to = _catname($from, $to);
186*0Sstevel@tonic-gate    }
187*0Sstevel@tonic-gate
188*0Sstevel@tonic-gate    ($tosz1,$tomt1) = (stat($to))[7,9];
189*0Sstevel@tonic-gate    $fromsz = -s $from;
190*0Sstevel@tonic-gate    if ($^O eq 'os2' and defined $tosz1 and defined $fromsz) {
191*0Sstevel@tonic-gate      # will not rename with overwrite
192*0Sstevel@tonic-gate      unlink $to;
193*0Sstevel@tonic-gate    }
194*0Sstevel@tonic-gate    return 1 if rename $from, $to;
195*0Sstevel@tonic-gate
196*0Sstevel@tonic-gate    # Did rename return an error even though it succeeded, because $to
197*0Sstevel@tonic-gate    # is on a remote NFS file system, and NFS lost the server's ack?
198*0Sstevel@tonic-gate    return 1 if defined($fromsz) && !-e $from &&           # $from disappeared
199*0Sstevel@tonic-gate                (($tosz2,$tomt2) = (stat($to))[7,9]) &&    # $to's there
200*0Sstevel@tonic-gate                ($tosz1 != $tosz2 or $tomt1 != $tomt2) &&  #   and changed
201*0Sstevel@tonic-gate                $tosz2 == $fromsz;                         # it's all there
202*0Sstevel@tonic-gate
203*0Sstevel@tonic-gate    ($tosz1,$tomt1) = (stat($to))[7,9];  # just in case rename did something
204*0Sstevel@tonic-gate    return 1 if copy($from,$to) && unlink($from);
205*0Sstevel@tonic-gate    ($sts,$ossts) = ($! + 0, $^E + 0);
206*0Sstevel@tonic-gate
207*0Sstevel@tonic-gate    ($tosz2,$tomt2) = ((stat($to))[7,9],0,0) if defined $tomt1;
208*0Sstevel@tonic-gate    unlink($to) if !defined($tomt1) or $tomt1 != $tomt2 or $tosz1 != $tosz2;
209*0Sstevel@tonic-gate    ($!,$^E) = ($sts,$ossts);
210*0Sstevel@tonic-gate    return 0;
211*0Sstevel@tonic-gate}
212*0Sstevel@tonic-gate
213*0Sstevel@tonic-gate*cp = \&copy;
214*0Sstevel@tonic-gate*mv = \&move;
215*0Sstevel@tonic-gate
216*0Sstevel@tonic-gate
217*0Sstevel@tonic-gateif ($^O eq 'MacOS') {
218*0Sstevel@tonic-gate    *_protect = sub { MacPerl::MakeFSSpec($_[0]) };
219*0Sstevel@tonic-gate} else {
220*0Sstevel@tonic-gate    *_protect = sub { "./$_[0]" };
221*0Sstevel@tonic-gate}
222*0Sstevel@tonic-gate
223*0Sstevel@tonic-gate# &syscopy is an XSUB under OS/2
224*0Sstevel@tonic-gateunless (defined &syscopy) {
225*0Sstevel@tonic-gate    if ($^O eq 'VMS') {
226*0Sstevel@tonic-gate	*syscopy = \&rmscopy;
227*0Sstevel@tonic-gate    } elsif ($^O eq 'mpeix') {
228*0Sstevel@tonic-gate	*syscopy = sub {
229*0Sstevel@tonic-gate	    return 0 unless @_ == 2;
230*0Sstevel@tonic-gate	    # Use the MPE cp program in order to
231*0Sstevel@tonic-gate	    # preserve MPE file attributes.
232*0Sstevel@tonic-gate	    return system('/bin/cp', '-f', $_[0], $_[1]) == 0;
233*0Sstevel@tonic-gate	};
234*0Sstevel@tonic-gate    } elsif ($^O eq 'MSWin32') {
235*0Sstevel@tonic-gate	*syscopy = sub {
236*0Sstevel@tonic-gate	    return 0 unless @_ == 2;
237*0Sstevel@tonic-gate	    return Win32::CopyFile(@_, 1);
238*0Sstevel@tonic-gate	};
239*0Sstevel@tonic-gate    } elsif ($macfiles) {
240*0Sstevel@tonic-gate	*syscopy = sub {
241*0Sstevel@tonic-gate	    my($from, $to) = @_;
242*0Sstevel@tonic-gate	    my($dir, $toname);
243*0Sstevel@tonic-gate
244*0Sstevel@tonic-gate	    return 0 unless -e $from;
245*0Sstevel@tonic-gate
246*0Sstevel@tonic-gate	    if ($to =~ /(.*:)([^:]+):?$/) {
247*0Sstevel@tonic-gate		($dir, $toname) = ($1, $2);
248*0Sstevel@tonic-gate	    } else {
249*0Sstevel@tonic-gate		($dir, $toname) = (":", $to);
250*0Sstevel@tonic-gate	    }
251*0Sstevel@tonic-gate
252*0Sstevel@tonic-gate	    unlink($to);
253*0Sstevel@tonic-gate	    Mac::MoreFiles::FSpFileCopy($from, $dir, $toname, 1);
254*0Sstevel@tonic-gate	};
255*0Sstevel@tonic-gate    } else {
256*0Sstevel@tonic-gate	$Syscopy_is_copy = 1;
257*0Sstevel@tonic-gate	*syscopy = \&copy;
258*0Sstevel@tonic-gate    }
259*0Sstevel@tonic-gate}
260*0Sstevel@tonic-gate
261*0Sstevel@tonic-gate1;
262*0Sstevel@tonic-gate
263*0Sstevel@tonic-gate__END__
264*0Sstevel@tonic-gate
265*0Sstevel@tonic-gate=head1 NAME
266*0Sstevel@tonic-gate
267*0Sstevel@tonic-gateFile::Copy - Copy files or filehandles
268*0Sstevel@tonic-gate
269*0Sstevel@tonic-gate=head1 SYNOPSIS
270*0Sstevel@tonic-gate
271*0Sstevel@tonic-gate	use File::Copy;
272*0Sstevel@tonic-gate
273*0Sstevel@tonic-gate	copy("file1","file2") or die "Copy failed: $!";
274*0Sstevel@tonic-gate	copy("Copy.pm",\*STDOUT);
275*0Sstevel@tonic-gate	move("/dev1/fileA","/dev2/fileB");
276*0Sstevel@tonic-gate
277*0Sstevel@tonic-gate	use POSIX;
278*0Sstevel@tonic-gate	use File::Copy cp;
279*0Sstevel@tonic-gate
280*0Sstevel@tonic-gate	$n = FileHandle->new("/a/file","r");
281*0Sstevel@tonic-gate	cp($n,"x");'
282*0Sstevel@tonic-gate
283*0Sstevel@tonic-gate=head1 DESCRIPTION
284*0Sstevel@tonic-gate
285*0Sstevel@tonic-gateThe File::Copy module provides two basic functions, C<copy> and
286*0Sstevel@tonic-gateC<move>, which are useful for getting the contents of a file from
287*0Sstevel@tonic-gateone place to another.
288*0Sstevel@tonic-gate
289*0Sstevel@tonic-gate=over 4
290*0Sstevel@tonic-gate
291*0Sstevel@tonic-gate=item *
292*0Sstevel@tonic-gate
293*0Sstevel@tonic-gateThe C<copy> function takes two
294*0Sstevel@tonic-gateparameters: a file to copy from and a file to copy to. Either
295*0Sstevel@tonic-gateargument may be a string, a FileHandle reference or a FileHandle
296*0Sstevel@tonic-gateglob. Obviously, if the first argument is a filehandle of some
297*0Sstevel@tonic-gatesort, it will be read from, and if it is a file I<name> it will
298*0Sstevel@tonic-gatebe opened for reading. Likewise, the second argument will be
299*0Sstevel@tonic-gatewritten to (and created if need be).  Trying to copy a file on top
300*0Sstevel@tonic-gateof itself is a fatal error.
301*0Sstevel@tonic-gate
302*0Sstevel@tonic-gateB<Note that passing in
303*0Sstevel@tonic-gatefiles as handles instead of names may lead to loss of information
304*0Sstevel@tonic-gateon some operating systems; it is recommended that you use file
305*0Sstevel@tonic-gatenames whenever possible.>  Files are opened in binary mode where
306*0Sstevel@tonic-gateapplicable.  To get a consistent behaviour when copying from a
307*0Sstevel@tonic-gatefilehandle to a file, use C<binmode> on the filehandle.
308*0Sstevel@tonic-gate
309*0Sstevel@tonic-gateAn optional third parameter can be used to specify the buffer
310*0Sstevel@tonic-gatesize used for copying. This is the number of bytes from the
311*0Sstevel@tonic-gatefirst file, that wil be held in memory at any given time, before
312*0Sstevel@tonic-gatebeing written to the second file. The default buffer size depends
313*0Sstevel@tonic-gateupon the file, but will generally be the whole file (up to 2Mb), or
314*0Sstevel@tonic-gate1k for filehandles that do not reference files (eg. sockets).
315*0Sstevel@tonic-gate
316*0Sstevel@tonic-gateYou may use the syntax C<use File::Copy "cp"> to get at the
317*0Sstevel@tonic-gate"cp" alias for this function. The syntax is I<exactly> the same.
318*0Sstevel@tonic-gate
319*0Sstevel@tonic-gate=item *
320*0Sstevel@tonic-gate
321*0Sstevel@tonic-gateThe C<move> function also takes two parameters: the current name
322*0Sstevel@tonic-gateand the intended name of the file to be moved.  If the destination
323*0Sstevel@tonic-gatealready exists and is a directory, and the source is not a
324*0Sstevel@tonic-gatedirectory, then the source file will be renamed into the directory
325*0Sstevel@tonic-gatespecified by the destination.
326*0Sstevel@tonic-gate
327*0Sstevel@tonic-gateIf possible, move() will simply rename the file.  Otherwise, it copies
328*0Sstevel@tonic-gatethe file to the new location and deletes the original.  If an error occurs
329*0Sstevel@tonic-gateduring this copy-and-delete process, you may be left with a (possibly partial)
330*0Sstevel@tonic-gatecopy of the file under the destination name.
331*0Sstevel@tonic-gate
332*0Sstevel@tonic-gateYou may use the "mv" alias for this function in the same way that
333*0Sstevel@tonic-gateyou may use the "cp" alias for C<copy>.
334*0Sstevel@tonic-gate
335*0Sstevel@tonic-gate=back
336*0Sstevel@tonic-gate
337*0Sstevel@tonic-gateFile::Copy also provides the C<syscopy> routine, which copies the
338*0Sstevel@tonic-gatefile specified in the first parameter to the file specified in the
339*0Sstevel@tonic-gatesecond parameter, preserving OS-specific attributes and file
340*0Sstevel@tonic-gatestructure.  For Unix systems, this is equivalent to the simple
341*0Sstevel@tonic-gateC<copy> routine, which doesn't preserve OS-specific attributes.  For
342*0Sstevel@tonic-gateVMS systems, this calls the C<rmscopy> routine (see below).  For OS/2
343*0Sstevel@tonic-gatesystems, this calls the C<syscopy> XSUB directly. For Win32 systems,
344*0Sstevel@tonic-gatethis calls C<Win32::CopyFile>.
345*0Sstevel@tonic-gate
346*0Sstevel@tonic-gateOn Mac OS (Classic), C<syscopy> calls C<Mac::MoreFiles::FSpFileCopy>,
347*0Sstevel@tonic-gateif available.
348*0Sstevel@tonic-gate
349*0Sstevel@tonic-gate=head2 Special behaviour if C<syscopy> is defined (OS/2, VMS and Win32)
350*0Sstevel@tonic-gate
351*0Sstevel@tonic-gateIf both arguments to C<copy> are not file handles,
352*0Sstevel@tonic-gatethen C<copy> will perform a "system copy" of
353*0Sstevel@tonic-gatethe input file to a new output file, in order to preserve file
354*0Sstevel@tonic-gateattributes, indexed file structure, I<etc.>  The buffer size
355*0Sstevel@tonic-gateparameter is ignored.  If either argument to C<copy> is a
356*0Sstevel@tonic-gatehandle to an opened file, then data is copied using Perl
357*0Sstevel@tonic-gateoperators, and no effort is made to preserve file attributes
358*0Sstevel@tonic-gateor record structure.
359*0Sstevel@tonic-gate
360*0Sstevel@tonic-gateThe system copy routine may also be called directly under VMS and OS/2
361*0Sstevel@tonic-gateas C<File::Copy::syscopy> (or under VMS as C<File::Copy::rmscopy>, which
362*0Sstevel@tonic-gateis the routine that does the actual work for syscopy).
363*0Sstevel@tonic-gate
364*0Sstevel@tonic-gate=over 4
365*0Sstevel@tonic-gate
366*0Sstevel@tonic-gate=item rmscopy($from,$to[,$date_flag])
367*0Sstevel@tonic-gate
368*0Sstevel@tonic-gateThe first and second arguments may be strings, typeglobs, typeglob
369*0Sstevel@tonic-gatereferences, or objects inheriting from IO::Handle;
370*0Sstevel@tonic-gatethey are used in all cases to obtain the
371*0Sstevel@tonic-gateI<filespec> of the input and output files, respectively.  The
372*0Sstevel@tonic-gatename and type of the input file are used as defaults for the
373*0Sstevel@tonic-gateoutput file, if necessary.
374*0Sstevel@tonic-gate
375*0Sstevel@tonic-gateA new version of the output file is always created, which
376*0Sstevel@tonic-gateinherits the structure and RMS attributes of the input file,
377*0Sstevel@tonic-gateexcept for owner and protections (and possibly timestamps;
378*0Sstevel@tonic-gatesee below).  All data from the input file is copied to the
379*0Sstevel@tonic-gateoutput file; if either of the first two parameters to C<rmscopy>
380*0Sstevel@tonic-gateis a file handle, its position is unchanged.  (Note that this
381*0Sstevel@tonic-gatemeans a file handle pointing to the output file will be
382*0Sstevel@tonic-gateassociated with an old version of that file after C<rmscopy>
383*0Sstevel@tonic-gatereturns, not the newly created version.)
384*0Sstevel@tonic-gate
385*0Sstevel@tonic-gateThe third parameter is an integer flag, which tells C<rmscopy>
386*0Sstevel@tonic-gatehow to handle timestamps.  If it is E<lt> 0, none of the input file's
387*0Sstevel@tonic-gatetimestamps are propagated to the output file.  If it is E<gt> 0, then
388*0Sstevel@tonic-gateit is interpreted as a bitmask: if bit 0 (the LSB) is set, then
389*0Sstevel@tonic-gatetimestamps other than the revision date are propagated; if bit 1
390*0Sstevel@tonic-gateis set, the revision date is propagated.  If the third parameter
391*0Sstevel@tonic-gateto C<rmscopy> is 0, then it behaves much like the DCL COPY command:
392*0Sstevel@tonic-gateif the name or type of the output file was explicitly specified,
393*0Sstevel@tonic-gatethen no timestamps are propagated, but if they were taken implicitly
394*0Sstevel@tonic-gatefrom the input filespec, then all timestamps other than the
395*0Sstevel@tonic-gaterevision date are propagated.  If this parameter is not supplied,
396*0Sstevel@tonic-gateit defaults to 0.
397*0Sstevel@tonic-gate
398*0Sstevel@tonic-gateLike C<copy>, C<rmscopy> returns 1 on success.  If an error occurs,
399*0Sstevel@tonic-gateit sets C<$!>, deletes the output file, and returns 0.
400*0Sstevel@tonic-gate
401*0Sstevel@tonic-gate=back
402*0Sstevel@tonic-gate
403*0Sstevel@tonic-gate=head1 RETURN
404*0Sstevel@tonic-gate
405*0Sstevel@tonic-gateAll functions return 1 on success, 0 on failure.
406*0Sstevel@tonic-gate$! will be set if an error was encountered.
407*0Sstevel@tonic-gate
408*0Sstevel@tonic-gate=head1 NOTES
409*0Sstevel@tonic-gate
410*0Sstevel@tonic-gate=over 4
411*0Sstevel@tonic-gate
412*0Sstevel@tonic-gate=item *
413*0Sstevel@tonic-gate
414*0Sstevel@tonic-gateOn Mac OS (Classic), the path separator is ':', not '/', and the
415*0Sstevel@tonic-gatecurrent directory is denoted as ':', not '.'. You should be careful
416*0Sstevel@tonic-gateabout specifying relative pathnames. While a full path always begins
417*0Sstevel@tonic-gatewith a volume name, a relative pathname should always begin with a
418*0Sstevel@tonic-gate':'.  If specifying a volume name only, a trailing ':' is required.
419*0Sstevel@tonic-gate
420*0Sstevel@tonic-gateE.g.
421*0Sstevel@tonic-gate
422*0Sstevel@tonic-gate  copy("file1", "tmp");        # creates the file 'tmp' in the current directory
423*0Sstevel@tonic-gate  copy("file1", ":tmp:");      # creates :tmp:file1
424*0Sstevel@tonic-gate  copy("file1", ":tmp");       # same as above
425*0Sstevel@tonic-gate  copy("file1", "tmp");        # same as above, if 'tmp' is a directory (but don't do
426*0Sstevel@tonic-gate                               # that, since it may cause confusion, see example #1)
427*0Sstevel@tonic-gate  copy("file1", "tmp:file1");  # error, since 'tmp:' is not a volume
428*0Sstevel@tonic-gate  copy("file1", ":tmp:file1"); # ok, partial path
429*0Sstevel@tonic-gate  copy("file1", "DataHD:");    # creates DataHD:file1
430*0Sstevel@tonic-gate
431*0Sstevel@tonic-gate  move("MacintoshHD:fileA", "DataHD:fileB"); # moves (don't copies) files from one
432*0Sstevel@tonic-gate                                             # volume to another
433*0Sstevel@tonic-gate
434*0Sstevel@tonic-gate=back
435*0Sstevel@tonic-gate
436*0Sstevel@tonic-gate=head1 AUTHOR
437*0Sstevel@tonic-gate
438*0Sstevel@tonic-gateFile::Copy was written by Aaron Sherman I<E<lt>ajs@ajs.comE<gt>> in 1995,
439*0Sstevel@tonic-gateand updated by Charles Bailey I<E<lt>bailey@newman.upenn.eduE<gt>> in 1996.
440*0Sstevel@tonic-gate
441*0Sstevel@tonic-gate=cut
442*0Sstevel@tonic-gate
443