ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/staticperl/perl/lib/File/Copy.pm
Revision: 1.1
Committed: Thu Jun 30 14:27:11 2005 UTC (21 years, 3 months ago) by root
Branch: MAIN
CVS Tags: PERL-5-8-7, HEAD
Branch point for: PERL
Log Message:
*** empty log message ***

File Contents

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