Filename | /usr/local/perls/perl-5.26.1/lib/5.26.1/File/Copy.pm |
Statements | Executed 180 statements in 4.03ms |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
18 | 1 | 1 | 2.75ms | 2.75ms | CORE:rename (opcode) | File::Copy::
18 | 1 | 1 | 558µs | 3.87ms | _move | File::Copy::
18 | 1 | 1 | 276µs | 276µs | CORE:ftdir (opcode) | File::Copy::
18 | 1 | 1 | 222µs | 222µs | CORE:ftsize (opcode) | File::Copy::
18 | 1 | 1 | 175µs | 4.04ms | move | File::Copy::
18 | 1 | 1 | 63µs | 63µs | CORE:stat (opcode) | File::Copy::
0 | 0 | 0 | 0s | 0s | BEGIN | File::Copy::
0 | 0 | 0 | 0s | 0s | __ANON__[:324] | File::Copy::
0 | 0 | 0 | 0s | 0s | _catname | File::Copy::
0 | 0 | 0 | 0s | 0s | _eq | File::Copy::
0 | 0 | 0 | 0s | 0s | carp | File::Copy::
0 | 0 | 0 | 0s | 0s | copy | File::Copy::
0 | 0 | 0 | 0s | 0s | cp | File::Copy::
0 | 0 | 0 | 0s | 0s | croak | File::Copy::
0 | 0 | 0 | 0s | 0s | mv | File::Copy::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | # File/Copy.pm. Written in 1994 by Aaron Sherman <[email protected]>. 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; no warnings 'newline'; | ||||
13 | use File::Spec; | ||||
14 | use Config; | ||||
15 | # During perl build, we need File::Copy but Scalar::Util might not be built yet | ||||
16 | # And then we need these games to avoid loading overload, as that will | ||||
17 | # confuse miniperl during the bootstrap of perl. | ||||
18 | my $Scalar_Util_loaded = eval q{ require Scalar::Util; require overload; 1 }; | ||||
19 | our(@ISA, @EXPORT, @EXPORT_OK, $VERSION, $Too_Big, $Syscopy_is_copy); | ||||
20 | sub copy; | ||||
21 | sub syscopy; | ||||
22 | sub cp; | ||||
23 | sub mv; | ||||
24 | |||||
25 | $VERSION = '2.32'; | ||||
26 | |||||
27 | require Exporter; | ||||
28 | @ISA = qw(Exporter); | ||||
29 | @EXPORT = qw(copy move); | ||||
30 | @EXPORT_OK = qw(cp mv); | ||||
31 | |||||
32 | $Too_Big = 1024 * 1024 * 2; | ||||
33 | |||||
34 | sub croak { | ||||
35 | require Carp; | ||||
36 | goto &Carp::croak; | ||||
37 | } | ||||
38 | |||||
39 | sub carp { | ||||
40 | require Carp; | ||||
41 | goto &Carp::carp; | ||||
42 | } | ||||
43 | |||||
44 | sub _catname { | ||||
45 | my($from, $to) = @_; | ||||
46 | if (not defined &basename) { | ||||
47 | require File::Basename; | ||||
48 | import File::Basename 'basename'; | ||||
49 | } | ||||
50 | |||||
51 | return File::Spec->catfile($to, basename($from)); | ||||
52 | } | ||||
53 | |||||
54 | # _eq($from, $to) tells whether $from and $to are identical | ||||
55 | sub _eq { | ||||
56 | my ($from, $to) = map { | ||||
57 | $Scalar_Util_loaded && Scalar::Util::blessed($_) | ||||
58 | && overload::Method($_, q{""}) | ||||
59 | ? "$_" | ||||
60 | : $_ | ||||
61 | } (@_); | ||||
62 | return '' if ( (ref $from) xor (ref $to) ); | ||||
63 | return $from == $to if ref $from; | ||||
64 | return $from eq $to; | ||||
65 | } | ||||
66 | |||||
67 | sub copy { | ||||
68 | croak("Usage: copy(FROM, TO [, BUFFERSIZE]) ") | ||||
69 | unless(@_ == 2 || @_ == 3); | ||||
70 | |||||
71 | my $from = shift; | ||||
72 | my $to = shift; | ||||
73 | |||||
74 | my $size; | ||||
75 | if (@_) { | ||||
76 | $size = shift(@_) + 0; | ||||
77 | croak("Bad buffer size for copy: $size\n") unless ($size > 0); | ||||
78 | } | ||||
79 | |||||
80 | my $from_a_handle = (ref($from) | ||||
81 | ? (ref($from) eq 'GLOB' | ||||
82 | || UNIVERSAL::isa($from, 'GLOB') | ||||
83 | || UNIVERSAL::isa($from, 'IO::Handle')) | ||||
84 | : (ref(\$from) eq 'GLOB')); | ||||
85 | my $to_a_handle = (ref($to) | ||||
86 | ? (ref($to) eq 'GLOB' | ||||
87 | || UNIVERSAL::isa($to, 'GLOB') | ||||
88 | || UNIVERSAL::isa($to, 'IO::Handle')) | ||||
89 | : (ref(\$to) eq 'GLOB')); | ||||
90 | |||||
91 | if (_eq($from, $to)) { # works for references, too | ||||
92 | carp("'$from' and '$to' are identical (not copied)"); | ||||
93 | return 0; | ||||
94 | } | ||||
95 | |||||
96 | if (!$from_a_handle && !$to_a_handle && -d $to && ! -d $from) { | ||||
97 | $to = _catname($from, $to); | ||||
98 | } | ||||
99 | |||||
100 | if ((($Config{d_symlink} && $Config{d_readlink}) || $Config{d_link}) && | ||||
101 | !($^O eq 'MSWin32' || $^O eq 'os2')) { | ||||
102 | my @fs = stat($from); | ||||
103 | if (@fs) { | ||||
104 | my @ts = stat($to); | ||||
105 | if (@ts && $fs[0] == $ts[0] && $fs[1] == $ts[1] && !-p $from) { | ||||
106 | carp("'$from' and '$to' are identical (not copied)"); | ||||
107 | return 0; | ||||
108 | } | ||||
109 | } | ||||
110 | } | ||||
111 | elsif (_eq($from, $to)) { | ||||
112 | carp("'$from' and '$to' are identical (not copied)"); | ||||
113 | return 0; | ||||
114 | } | ||||
115 | |||||
116 | if (defined &syscopy && !$Syscopy_is_copy | ||||
117 | && !$to_a_handle | ||||
118 | && !($from_a_handle && $^O eq 'os2' ) # OS/2 cannot handle handles | ||||
119 | && !($from_a_handle && $^O eq 'MSWin32') | ||||
120 | && !($from_a_handle && $^O eq 'NetWare') | ||||
121 | ) | ||||
122 | { | ||||
123 | if ($^O eq 'VMS' && -e $from | ||||
124 | && ! -d $to && ! -d $from) { | ||||
125 | |||||
126 | # VMS natively inherits path components from the source of a | ||||
127 | # copy, but we want the Unixy behavior of inheriting from | ||||
128 | # the current working directory. Also, default in a trailing | ||||
129 | # dot for null file types. | ||||
130 | |||||
131 | $to = VMS::Filespec::rmsexpand(VMS::Filespec::vmsify($to), '.'); | ||||
132 | |||||
133 | # Get rid of the old versions to be like UNIX | ||||
134 | 1 while unlink $to; | ||||
135 | } | ||||
136 | |||||
137 | return syscopy($from, $to) || 0; | ||||
138 | } | ||||
139 | |||||
140 | my $closefrom = 0; | ||||
141 | my $closeto = 0; | ||||
142 | my ($status, $r, $buf); | ||||
143 | local($\) = ''; | ||||
144 | |||||
145 | my $from_h; | ||||
146 | if ($from_a_handle) { | ||||
147 | $from_h = $from; | ||||
148 | } else { | ||||
149 | open $from_h, "<", $from or goto fail_open1; | ||||
150 | binmode $from_h or die "($!,$^E)"; | ||||
151 | $closefrom = 1; | ||||
152 | } | ||||
153 | |||||
154 | # Seems most logical to do this here, in case future changes would want to | ||||
155 | # make this croak for some reason. | ||||
156 | unless (defined $size) { | ||||
157 | $size = tied(*$from_h) ? 0 : -s $from_h || 0; | ||||
158 | $size = 1024 if ($size < 512); | ||||
159 | $size = $Too_Big if ($size > $Too_Big); | ||||
160 | } | ||||
161 | |||||
162 | my $to_h; | ||||
163 | if ($to_a_handle) { | ||||
164 | $to_h = $to; | ||||
165 | } else { | ||||
166 | $to_h = \do { local *FH }; # XXX is this line obsolete? | ||||
167 | open $to_h, ">", $to or goto fail_open2; | ||||
168 | binmode $to_h or die "($!,$^E)"; | ||||
169 | $closeto = 1; | ||||
170 | } | ||||
171 | |||||
172 | $! = 0; | ||||
173 | for (;;) { | ||||
174 | my ($r, $w, $t); | ||||
175 | defined($r = sysread($from_h, $buf, $size)) | ||||
176 | or goto fail_inner; | ||||
177 | last unless $r; | ||||
178 | for ($w = 0; $w < $r; $w += $t) { | ||||
179 | $t = syswrite($to_h, $buf, $r - $w, $w) | ||||
180 | or goto fail_inner; | ||||
181 | } | ||||
182 | } | ||||
183 | |||||
184 | close($to_h) || goto fail_open2 if $closeto; | ||||
185 | close($from_h) || goto fail_open1 if $closefrom; | ||||
186 | |||||
187 | # Use this idiom to avoid uninitialized value warning. | ||||
188 | return 1; | ||||
189 | |||||
190 | # All of these contortions try to preserve error messages... | ||||
191 | fail_inner: | ||||
192 | if ($closeto) { | ||||
193 | $status = $!; | ||||
194 | $! = 0; | ||||
195 | close $to_h; | ||||
196 | $! = $status unless $!; | ||||
197 | } | ||||
198 | fail_open2: | ||||
199 | if ($closefrom) { | ||||
200 | $status = $!; | ||||
201 | $! = 0; | ||||
202 | close $from_h; | ||||
203 | $! = $status unless $!; | ||||
204 | } | ||||
205 | fail_open1: | ||||
206 | return 0; | ||||
207 | } | ||||
208 | |||||
209 | sub cp { | ||||
210 | my($from,$to) = @_; | ||||
211 | my(@fromstat) = stat $from; | ||||
212 | my(@tostat) = stat $to; | ||||
213 | my $perm; | ||||
214 | |||||
215 | return 0 unless copy(@_) and @fromstat; | ||||
216 | |||||
217 | if (@tostat) { | ||||
218 | $perm = $tostat[2]; | ||||
219 | } else { | ||||
220 | $perm = $fromstat[2] & ~(umask || 0); | ||||
221 | @tostat = stat $to; | ||||
222 | } | ||||
223 | # Might be more robust to look for S_I* in Fcntl, but we're | ||||
224 | # trying to avoid dependence on any XS-containing modules, | ||||
225 | # since File::Copy is used during the Perl build. | ||||
226 | $perm &= 07777; | ||||
227 | if ($perm & 06000) { | ||||
228 | croak("Unable to check setuid/setgid permissions for $to: $!") | ||||
229 | unless @tostat; | ||||
230 | |||||
231 | if ($perm & 04000 and # setuid | ||||
232 | $fromstat[4] != $tostat[4]) { # owner must match | ||||
233 | $perm &= ~06000; | ||||
234 | } | ||||
235 | |||||
236 | if ($perm & 02000 && $> != 0) { # if not root, setgid | ||||
237 | my $ok = $fromstat[5] == $tostat[5]; # group must match | ||||
238 | if ($ok) { # and we must be in group | ||||
239 | $ok = grep { $_ == $fromstat[5] } split /\s+/, $) | ||||
240 | } | ||||
241 | $perm &= ~06000 unless $ok; | ||||
242 | } | ||||
243 | } | ||||
244 | return 0 unless @tostat; | ||||
245 | return 1 if $perm == ($tostat[2] & 07777); | ||||
246 | return eval { chmod $perm, $to; } ? 1 : 0; | ||||
247 | } | ||||
248 | |||||
249 | # spent 3.87ms (558µs+3.31) within File::Copy::_move which was called 18 times, avg 215µs/call:
# 18 times (558µs+3.31ms) by File::Copy::move at line 312, avg 215µs/call | ||||
250 | 18 | 5µs | croak("Usage: move(FROM, TO) ") unless @_ == 3; | ||
251 | |||||
252 | 18 | 38µs | my($from,$to,$fallback) = @_; | ||
253 | |||||
254 | 18 | 17µs | my($fromsz,$tosz1,$tomt1,$tosz2,$tomt2,$sts,$ossts); | ||
255 | |||||
256 | 18 | 353µs | 18 | 276µs | if (-d $to && ! -d $from) { # spent 276µs making 18 calls to File::Copy::CORE:ftdir, avg 15µs/call |
257 | $to = _catname($from, $to); | ||||
258 | } | ||||
259 | |||||
260 | 18 | 119µs | 18 | 63µs | ($tosz1,$tomt1) = (stat($to))[7,9]; # spent 63µs making 18 calls to File::Copy::CORE:stat, avg 4µs/call |
261 | 18 | 285µs | 18 | 222µs | $fromsz = -s $from; # spent 222µs making 18 calls to File::Copy::CORE:ftsize, avg 12µs/call |
262 | 18 | 45µs | if ($^O eq 'os2' and defined $tosz1 and defined $fromsz) { | ||
263 | # will not rename with overwrite | ||||
264 | unlink $to; | ||||
265 | } | ||||
266 | |||||
267 | 18 | 26µs | if ($^O eq 'VMS' && -e $from | ||
268 | && ! -d $to && ! -d $from) { | ||||
269 | |||||
270 | # VMS natively inherits path components from the source of a | ||||
271 | # copy, but we want the Unixy behavior of inheriting from | ||||
272 | # the current working directory. Also, default in a trailing | ||||
273 | # dot for null file types. | ||||
274 | |||||
275 | $to = VMS::Filespec::rmsexpand(VMS::Filespec::vmsify($to), '.'); | ||||
276 | |||||
277 | # Get rid of the old versions to be like UNIX | ||||
278 | 1 while unlink $to; | ||||
279 | } | ||||
280 | |||||
281 | 18 | 2.99ms | 18 | 2.75ms | return 1 if rename $from, $to; # spent 2.75ms making 18 calls to File::Copy::CORE:rename, avg 153µs/call |
282 | |||||
283 | # Did rename return an error even though it succeeded, because $to | ||||
284 | # is on a remote NFS file system, and NFS lost the server's ack? | ||||
285 | return 1 if defined($fromsz) && !-e $from && # $from disappeared | ||||
286 | (($tosz2,$tomt2) = (stat($to))[7,9]) && # $to's there | ||||
287 | ((!defined $tosz1) || # not before or | ||||
288 | ($tosz1 != $tosz2 or $tomt1 != $tomt2)) && # was changed | ||||
289 | $tosz2 == $fromsz; # it's all there | ||||
290 | |||||
291 | ($tosz1,$tomt1) = (stat($to))[7,9]; # just in case rename did something | ||||
292 | |||||
293 | { | ||||
294 | local $@; | ||||
295 | eval { | ||||
296 | local $SIG{__DIE__}; | ||||
297 | $fallback->($from,$to) or die; | ||||
298 | my($atime, $mtime) = (stat($from))[8,9]; | ||||
299 | utime($atime, $mtime, $to); | ||||
300 | unlink($from) or die; | ||||
301 | }; | ||||
302 | return 1 unless $@; | ||||
303 | } | ||||
304 | ($sts,$ossts) = ($! + 0, $^E + 0); | ||||
305 | |||||
306 | ($tosz2,$tomt2) = ((stat($to))[7,9],0,0) if defined $tomt1; | ||||
307 | unlink($to) if !defined($tomt1) or $tomt1 != $tomt2 or $tosz1 != $tosz2; | ||||
308 | ($!,$^E) = ($sts,$ossts); | ||||
309 | return 0; | ||||
310 | } | ||||
311 | |||||
312 | 18 | 155µs | 18 | 3.87ms | # spent 4.04ms (175µs+3.87) within File::Copy::move which was called 18 times, avg 225µs/call:
# 18 times (175µs+3.87ms) by CPAN::Distribution::run_preps_on_packagedir at line 575 of CPAN/Distribution.pm, avg 225µs/call # spent 3.87ms making 18 calls to File::Copy::_move, avg 215µs/call |
313 | sub mv { _move(@_,\&cp); } | ||||
314 | |||||
315 | # &syscopy is an XSUB under OS/2 | ||||
316 | unless (defined &syscopy) { | ||||
317 | if ($^O eq 'VMS') { | ||||
318 | *syscopy = \&rmscopy; | ||||
319 | } elsif ($^O eq 'MSWin32' && defined &DynaLoader::boot_DynaLoader) { | ||||
320 | # Win32::CopyFile() fill only work if we can load Win32.xs | ||||
321 | *syscopy = sub { | ||||
322 | return 0 unless @_ == 2; | ||||
323 | return Win32::CopyFile(@_, 1); | ||||
324 | }; | ||||
325 | } else { | ||||
326 | $Syscopy_is_copy = 1; | ||||
327 | *syscopy = \© | ||||
328 | } | ||||
329 | } | ||||
330 | |||||
331 | 1; | ||||
332 | |||||
333 | __END__ | ||||
# spent 276µs within File::Copy::CORE:ftdir which was called 18 times, avg 15µs/call:
# 18 times (276µs+0s) by File::Copy::_move at line 256, avg 15µs/call | |||||
# spent 222µs within File::Copy::CORE:ftsize which was called 18 times, avg 12µs/call:
# 18 times (222µs+0s) by File::Copy::_move at line 261, avg 12µs/call | |||||
# spent 2.75ms within File::Copy::CORE:rename which was called 18 times, avg 153µs/call:
# 18 times (2.75ms+0s) by File::Copy::_move at line 281, avg 153µs/call | |||||
# spent 63µs within File::Copy::CORE:stat which was called 18 times, avg 4µs/call:
# 18 times (63µs+0s) by File::Copy::_move at line 260, avg 4µs/call |