← Index
NYTProf Performance Profile   « block view • line view • sub view »
For /usr/share/koha/opac/cgi-bin/opac/opac-search.pl
  Run on Tue Oct 15 17:10:45 2013
Reported on Tue Oct 15 17:11:41 2013

Filename/usr/share/perl/5.10/File/Path.pm
StatementsExecuted 34 statements in 2.86ms
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
1113.38ms3.87msFile::Path::::BEGIN@6File::Path::BEGIN@6
11166µs66µsFile::Path::::BEGIN@3File::Path::BEGIN@3
11116µs20µsFile::Path::::BEGIN@4File::Path::BEGIN@4
11113µs73µsFile::Path::::BEGIN@19File::Path::BEGIN@19
11111µs26µsFile::Path::::BEGIN@295File::Path::BEGIN@295
1118µs8µsFile::Path::::BEGIN@8File::Path::BEGIN@8
1115µs5µsFile::Path::::BEGIN@7File::Path::BEGIN@7
1115µs5µsFile::Path::::BEGIN@10File::Path::BEGIN@10
1114µs4µsFile::Path::::BEGIN@18File::Path::BEGIN@18
0000s0sFile::Path::::_carpFile::Path::_carp
0000s0sFile::Path::::_croakFile::Path::_croak
0000s0sFile::Path::::_errorFile::Path::_error
0000s0sFile::Path::::_is_subdirFile::Path::_is_subdir
0000s0sFile::Path::::_mkpathFile::Path::_mkpath
0000s0sFile::Path::::_rmtreeFile::Path::_rmtree
0000s0sFile::Path::::_slash_lcFile::Path::_slash_lc
0000s0sFile::Path::::make_pathFile::Path::make_path
0000s0sFile::Path::::mkpathFile::Path::mkpath
0000s0sFile::Path::::remove_treeFile::Path::remove_tree
0000s0sFile::Path::::rmtreeFile::Path::rmtree
Call graph for these subroutines as a Graphviz dot language file.
Line State
ments
Time
on line
Calls Time
in subs
Code
1package File::Path;
2
3382µs166µs
# spent 66µs within File::Path::BEGIN@3 which was called: # once (66µs+0s) by Template::BEGIN@32 at line 3
use 5.005_04;
# spent 66µs making 1 call to File::Path::BEGIN@3
4329µs224µs
# spent 20µs (16+4) within File::Path::BEGIN@4 which was called: # once (16µs+4µs) by Template::BEGIN@32 at line 4
use strict;
# spent 20µs making 1 call to File::Path::BEGIN@4 # spent 4µs making 1 call to strict::import
5
63127µs23.93ms
# spent 3.87ms (3.38+489µs) within File::Path::BEGIN@6 which was called: # once (3.38ms+489µs) by Template::BEGIN@32 at line 6
use Cwd 'getcwd';
# spent 3.87ms making 1 call to File::Path::BEGIN@6 # spent 60µs making 1 call to Exporter::import
7322µs15µs
# spent 5µs within File::Path::BEGIN@7 which was called: # once (5µs+0s) by Template::BEGIN@32 at line 7
use File::Basename ();
# spent 5µs making 1 call to File::Path::BEGIN@7
8344µs18µs
# spent 8µs within File::Path::BEGIN@8 which was called: # once (8µs+0s) by Template::BEGIN@32 at line 8
use File::Spec ();
# spent 8µs making 1 call to File::Path::BEGIN@8
9
10
# spent 5µs within File::Path::BEGIN@10 which was called: # once (5µs+0s) by Template::BEGIN@32 at line 16
BEGIN {
1115µs if ($] < 5.006) {
12 # can't say 'opendir my $dh, $dirname'
13 # need to initialise $dh
14 eval "use Symbol";
15 }
16118µs15µs}
# spent 5µs making 1 call to File::Path::BEGIN@10
17
18386µs14µs
# spent 4µs within File::Path::BEGIN@18 which was called: # once (4µs+0s) by Template::BEGIN@32 at line 18
use Exporter ();
# spent 4µs making 1 call to File::Path::BEGIN@18
1931.57ms2133µs
# spent 73µs (13+60) within File::Path::BEGIN@19 which was called: # once (13µs+60µs) by Template::BEGIN@32 at line 19
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
# spent 73µs making 1 call to File::Path::BEGIN@19 # spent 60µs making 1 call to vars::import
201700ns$VERSION = '2.07_03';
2119µs@ISA = qw(Exporter);
221800ns@EXPORT = qw(mkpath rmtree);
231800ns@EXPORT_OK = qw(make_path remove_tree);
24
2512µsmy $Is_VMS = $^O eq 'VMS';
261600nsmy $Is_MacOS = $^O eq 'MacOS';
27
28# These OSes complain if you want to remove a file that you have no
29# write permission to:
3012µsmy $Force_Writeable = grep {$^O eq $_} qw(amigaos dos epoc MSWin32 MacOS os2);
31
32# Unix-like systems need to stat each directory in order to detect
33# race condition. MS-Windows is immune to this particular attack.
341600nsmy $Need_Stat_Check = !($^O eq 'MSWin32');
35
36sub _carp {
37 require Carp;
38 goto &Carp::carp;
39}
40
41sub _croak {
42 require Carp;
43 goto &Carp::croak;
44}
45
46sub _error {
47 my $arg = shift;
48 my $message = shift;
49 my $object = shift;
50
51 if ($arg->{error}) {
52 $object = '' unless defined $object;
53 $message .= ": $!" if $!;
54 push @{${$arg->{error}}}, {$object => $message};
55 }
56 else {
57 _carp(defined($object) ? "$message for $object: $!" : "$message: $!");
58 }
59}
60
61sub make_path {
62 push @_, {} unless @_ and UNIVERSAL::isa($_[-1],'HASH');
63 goto &mkpath;
64}
65
66sub mkpath {
67 my $old_style = !(@_ and UNIVERSAL::isa($_[-1],'HASH'));
68
69 my $arg;
70 my $paths;
71
72 if ($old_style) {
73 my ($verbose, $mode);
74 ($paths, $verbose, $mode) = @_;
75 $paths = [$paths] unless UNIVERSAL::isa($paths,'ARRAY');
76 $arg->{verbose} = $verbose;
77 $arg->{mode} = defined $mode ? $mode : 0777;
78 }
79 else {
80 $arg = pop @_;
81 $arg->{mode} = delete $arg->{mask} if exists $arg->{mask};
82 $arg->{mode} = 0777 unless exists $arg->{mode};
83 ${$arg->{error}} = [] if exists $arg->{error};
84 $paths = [@_];
85 }
86 return _mkpath($arg, $paths);
87}
88
89sub _mkpath {
90 my $arg = shift;
91 my $paths = shift;
92
93 my(@created,$path);
94 foreach $path (@$paths) {
95 next unless defined($path) and length($path);
96 $path .= '/' if $^O eq 'os2' and $path =~ /^\w:\z/s; # feature of CRT
97 # Logic wants Unix paths, so go with the flow.
98 if ($Is_VMS) {
99 next if $path eq '/';
100 $path = VMS::Filespec::unixify($path);
101 }
102 next if -d $path;
103 my $parent = File::Basename::dirname($path);
104 unless (-d $parent or $path eq $parent) {
105 push(@created,_mkpath($arg, [$parent]));
106 }
107 print "mkdir $path\n" if $arg->{verbose};
108 if (mkdir($path,$arg->{mode})) {
109 push(@created, $path);
110 }
111 else {
112 my $save_bang = $!;
113 my ($e, $e1) = ($save_bang, $^E);
114 $e .= "; $e1" if $e ne $e1;
115 # allow for another process to have created it meanwhile
116 if (!-d $path) {
117 $! = $save_bang;
118 if ($arg->{error}) {
119 push @{${$arg->{error}}}, {$path => $e};
120 }
121 else {
122 _croak("mkdir $path: $e");
123 }
124 }
125 }
126 }
127 return @created;
128}
129
130sub remove_tree {
131 push @_, {} unless @_ and UNIVERSAL::isa($_[-1],'HASH');
132 goto &rmtree;
133}
134
135sub _is_subdir {
136 my($dir, $test) = @_;
137
138 my($dv, $dd) = File::Spec->splitpath($dir, 1);
139 my($tv, $td) = File::Spec->splitpath($test, 1);
140
141 # not on same volume
142 return 0 if $dv ne $tv;
143
144 my @d = File::Spec->splitdir($dd);
145 my @t = File::Spec->splitdir($td);
146
147 # @t can't be a subdir if it's shorter than @d
148 return 0 if @t < @d;
149
150 return join('/', @d) eq join('/', splice @t, 0, +@d);
151}
152
153sub rmtree {
154 my $old_style = !(@_ and UNIVERSAL::isa($_[-1],'HASH'));
155
156 my $arg;
157 my $paths;
158
159 if ($old_style) {
160 my ($verbose, $safe);
161 ($paths, $verbose, $safe) = @_;
162 $arg->{verbose} = $verbose;
163 $arg->{safe} = defined $safe ? $safe : 0;
164
165 if (defined($paths) and length($paths)) {
166 $paths = [$paths] unless UNIVERSAL::isa($paths,'ARRAY');
167 }
168 else {
169 _carp ("No root path(s) specified\n");
170 return 0;
171 }
172 }
173 else {
174 $arg = pop @_;
175 ${$arg->{error}} = [] if exists $arg->{error};
176 ${$arg->{result}} = [] if exists $arg->{result};
177 $paths = [@_];
178 }
179
180 $arg->{prefix} = '';
181 $arg->{depth} = 0;
182
183 my @clean_path;
184 $arg->{cwd} = getcwd() or do {
185 _error($arg, "cannot fetch initial working directory");
186 return 0;
187 };
188 for ($arg->{cwd}) { /\A(.*)\Z/; $_ = $1 } # untaint
189
190 for my $p (@$paths) {
191 # need to fixup case and map \ to / on Windows
192 my $ortho_root = $^O eq 'MSWin32' ? _slash_lc($p) : $p;
193 my $ortho_cwd = $^O eq 'MSWin32' ? _slash_lc($arg->{cwd}) : $arg->{cwd};
194 my $ortho_root_length = length($ortho_root);
195 $ortho_root_length-- if $^O eq 'VMS'; # don't compare '.' with ']'
196 if ($ortho_root_length && _is_subdir($ortho_root, $ortho_cwd)) {
197 local $! = 0;
198 _error($arg, "cannot remove path when cwd is $arg->{cwd}", $p);
199 next;
200 }
201
202 if ($Is_MacOS) {
203 $p = ":$p" unless $p =~ /:/;
204 $p .= ":" unless $p =~ /:\z/;
205 }
206 elsif ($^O eq 'MSWin32') {
207 $p =~ s{[/\\]\z}{};
208 }
209 else {
210 $p =~ s{/\z}{};
211 }
212 push @clean_path, $p;
213 }
214
215 @{$arg}{qw(device inode perm)} = (lstat $arg->{cwd})[0,1] or do {
216 _error($arg, "cannot stat initial working directory", $arg->{cwd});
217 return 0;
218 };
219
220 return _rmtree($arg, \@clean_path);
221}
222
223sub _rmtree {
224 my $arg = shift;
225 my $paths = shift;
226
227 my $count = 0;
228 my $curdir = File::Spec->curdir();
229 my $updir = File::Spec->updir();
230
231 my (@files, $root);
232 ROOT_DIR:
233 foreach $root (@$paths) {
234 # since we chdir into each directory, it may not be obvious
235 # to figure out where we are if we generate a message about
236 # a file name. We therefore construct a semi-canonical
237 # filename, anchored from the directory being unlinked (as
238 # opposed to being truly canonical, anchored from the root (/).
239
240 my $canon = $arg->{prefix}
241 ? File::Spec->catfile($arg->{prefix}, $root)
242 : $root
243 ;
244
245 my ($ldev, $lino, $perm) = (lstat $root)[0,1,2] or next ROOT_DIR;
246
247 if ( -d _ ) {
248 $root = VMS::Filespec::pathify($root) if $Is_VMS;
249
250 if (!chdir($root)) {
251 # see if we can escalate privileges to get in
252 # (e.g. funny protection mask such as -w- instead of rwx)
253 $perm &= 07777;
254 my $nperm = $perm | 0700;
255 if (!($arg->{safe} or $nperm == $perm or chmod($nperm, $root))) {
256 _error($arg, "cannot make child directory read-write-exec", $canon);
257 next ROOT_DIR;
258 }
259 elsif (!chdir($root)) {
260 _error($arg, "cannot chdir to child", $canon);
261 next ROOT_DIR;
262 }
263 }
264
265 my ($cur_dev, $cur_inode, $perm) = (stat $curdir)[0,1,2] or do {
266 _error($arg, "cannot stat current working directory", $canon);
267 next ROOT_DIR;
268 };
269
270 if ($Need_Stat_Check) {
271 ($ldev eq $cur_dev and $lino eq $cur_inode)
272 or _croak("directory $canon changed before chdir, expected dev=$ldev ino=$lino, actual dev=$cur_dev ino=$cur_inode, aborting.");
273 }
274
275 $perm &= 07777; # don't forget setuid, setgid, sticky bits
276 my $nperm = $perm | 0700;
277
278 # notabene: 0700 is for making readable in the first place,
279 # it's also intended to change it to writable in case we have
280 # to recurse in which case we are better than rm -rf for
281 # subtrees with strange permissions
282
283 if (!($arg->{safe} or $nperm == $perm or chmod($nperm, $curdir))) {
284 _error($arg, "cannot make directory read+writeable", $canon);
285 $nperm = $perm;
286 }
287
288 my $d;
289 $d = gensym() if $] < 5.006;
290 if (!opendir $d, $curdir) {
291 _error($arg, "cannot opendir", $canon);
292 @files = ();
293 }
294 else {
2953849µs242µs
# spent 26µs (11+16) within File::Path::BEGIN@295 which was called: # once (11µs+16µs) by Template::BEGIN@32 at line 295
no strict 'refs';
# spent 26µs making 1 call to File::Path::BEGIN@295 # spent 15µs making 1 call to strict::unimport
296 if (!defined ${"\cTAINT"} or ${"\cTAINT"}) {
297 # Blindly untaint dir names if taint mode is
298 # active, or any perl < 5.006
299 @files = map { /\A(.*)\z/s; $1 } readdir $d;
300 }
301 else {
302 @files = readdir $d;
303 }
304 closedir $d;
305 }
306
307 if ($Is_VMS) {
308 # Deleting large numbers of files from VMS Files-11
309 # filesystems is faster if done in reverse ASCIIbetical order.
310 # include '.' to '.;' from blead patch #31775
311 @files = map {$_ eq '.' ? '.;' : $_} reverse @files;
312 ($root = VMS::Filespec::unixify($root)) =~ s/\.dir\z//;
313 }
314
315 @files = grep {$_ ne $updir and $_ ne $curdir} @files;
316
317 if (@files) {
318 # remove the contained files before the directory itself
319 my $narg = {%$arg};
320 @{$narg}{qw(device inode cwd prefix depth)}
321 = ($cur_dev, $cur_inode, $updir, $canon, $arg->{depth}+1);
322 $count += _rmtree($narg, \@files);
323 }
324
325 # restore directory permissions of required now (in case the rmdir
326 # below fails), while we are still in the directory and may do so
327 # without a race via '.'
328 if ($nperm != $perm and not chmod($perm, $curdir)) {
329 _error($arg, "cannot reset chmod", $canon);
330 }
331
332 # don't leave the client code in an unexpected directory
333 chdir($arg->{cwd})
334 or _croak("cannot chdir to $arg->{cwd} from $canon: $!, aborting.");
335
336 # ensure that a chdir upwards didn't take us somewhere other
337 # than we expected (see CVE-2002-0435)
338 ($cur_dev, $cur_inode) = (stat $curdir)[0,1]
339 or _croak("cannot stat prior working directory $arg->{cwd}: $!, aborting.");
340
341 if ($Need_Stat_Check) {
342 ($arg->{device} eq $cur_dev and $arg->{inode} eq $cur_inode)
343 or _croak("previous directory $arg->{cwd} changed before entering $canon, expected dev=$ldev ino=$lino, actual dev=$cur_dev ino=$cur_inode, aborting.");
344 }
345
346 if ($arg->{depth} or !$arg->{keep_root}) {
347 if ($arg->{safe} &&
348 ($Is_VMS ? !&VMS::Filespec::candelete($root) : !-w $root)) {
349 print "skipped $root\n" if $arg->{verbose};
350 next ROOT_DIR;
351 }
352 if ($Force_Writeable and !chmod $perm | 0700, $root) {
353 _error($arg, "cannot make directory writeable", $canon);
354 }
355 print "rmdir $root\n" if $arg->{verbose};
356 if (rmdir $root) {
357 push @{${$arg->{result}}}, $root if $arg->{result};
358 ++$count;
359 }
360 else {
361 _error($arg, "cannot remove directory", $canon);
362 if ($Force_Writeable && !chmod($perm, ($Is_VMS ? VMS::Filespec::fileify($root) : $root))
363 ) {
364 _error($arg, sprintf("cannot restore permissions to 0%o",$perm), $canon);
365 }
366 }
367 }
368 }
369 else {
370 # not a directory
371 $root = VMS::Filespec::vmsify("./$root")
372 if $Is_VMS
373 && !File::Spec->file_name_is_absolute($root)
374 && ($root !~ m/(?<!\^)[\]>]+/); # not already in VMS syntax
375
376 if ($arg->{safe} &&
377 ($Is_VMS ? !&VMS::Filespec::candelete($root)
378 : !(-l $root || -w $root)))
379 {
380 print "skipped $root\n" if $arg->{verbose};
381 next ROOT_DIR;
382 }
383
384 my $nperm = $perm & 07777 | 0600;
385 if ($Force_Writeable and $nperm != $perm and not chmod $nperm, $root) {
386 _error($arg, "cannot make file writeable", $canon);
387 }
388 print "unlink $canon\n" if $arg->{verbose};
389 # delete all versions under VMS
390 for (;;) {
391 if (unlink $root) {
392 push @{${$arg->{result}}}, $root if $arg->{result};
393 }
394 else {
395 _error($arg, "cannot unlink file", $canon);
396 $Force_Writeable and chmod($perm, $root) or
397 _error($arg, sprintf("cannot restore permissions to 0%o",$perm), $canon);
398 last;
399 }
400 ++$count;
401 last unless $Is_VMS && lstat $root;
402 }
403 }
404 }
405 return $count;
406}
407
408sub _slash_lc {
409 # fix up slashes and case on MSWin32 so that we can determine that
410 # c:\path\to\dir is underneath C:/Path/To
411 my $path = shift;
412 $path =~ tr{\\}{/};
413 return lc($path);
414}
415
41618µs1;
417__END__