This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Upgrade Test-Simple from version 1.302045 to 1.302049
[perl5.git] / dist / PathTools / lib / File / Spec / VMS.pm
CommitLineData
270d1e39
GS
1package File::Spec::VMS;
2
cbc7acb0 3use strict;
ee8c7f54 4use vars qw(@ISA $VERSION);
cbc7acb0 5require File::Spec::Unix;
ee8c7f54 6
b13c68bf 7$VERSION = '3.65';
4f642d62 8$VERSION =~ tr/_//d;
ee8c7f54 9
270d1e39
GS
10@ISA = qw(File::Spec::Unix);
11
cbc7acb0
JD
12use File::Basename;
13use VMS::Filespec;
270d1e39
GS
14
15=head1 NAME
16
17File::Spec::VMS - methods for VMS file specs
18
19=head1 SYNOPSIS
20
cbc7acb0 21 require File::Spec::VMS; # Done internally by File::Spec if needed
270d1e39
GS
22
23=head1 DESCRIPTION
24
25See File::Spec::Unix for a documentation of the methods provided
26there. This package overrides the implementation of these methods, not
27the semantics.
28
385aae1c 29The default behavior is to allow either VMS or Unix syntax on input and to
2d3da5df 30return VMS syntax on output unless Unix syntax has been explicitly requested
13688ce5 31via the C<DECC$FILENAME_UNIX_REPORT> CRTL feature.
ae5a807c 32
bbc7dcd2 33=over 4
a45bd81d 34
ae5a807c
JM
35=cut
36
37# Need to look up the feature settings. The preferred way is to use the
38# VMS::Feature module, but that may not be available to dual life modules.
39
40my $use_feature;
41BEGIN {
8901ddee
TC
42 if (eval { local $SIG{__DIE__};
43 local @INC = @INC;
44 pop @INC if $INC[-1] eq '.';
45 require VMS::Feature; }) {
ae5a807c
JM
46 $use_feature = 1;
47 }
48}
49
50# Need to look up the UNIX report mode. This may become a dynamic mode
51# in the future.
52sub _unix_rpt {
53 my $unix_rpt;
54 if ($use_feature) {
55 $unix_rpt = VMS::Feature::current("filename_unix_report");
56 } else {
57 my $env_unix_rpt = $ENV{'DECC$FILENAME_UNIX_REPORT'} || '';
58 $unix_rpt = $env_unix_rpt =~ /^[ET1]/i;
59 }
60 return $unix_rpt;
61}
62
46726cbe
CB
63=item canonpath (override)
64
13688ce5
CB
65Removes redundant portions of file specifications and returns results
66in native syntax unless Unix filename reporting has been enabled.
46726cbe
CB
67
68=cut
69
ae5a807c 70
46726cbe 71sub canonpath {
fd7385b9 72 my($self,$path) = @_;
46726cbe 73
13fbb5b1
JM
74 return undef unless defined $path;
75
13688ce5 76 my $unix_rpt = $self->_unix_rpt;
ae5a807c 77
13688ce5 78 if ($path =~ m|/|) {
ee8c7f54 79 my $pathify = $path =~ m|/\Z(?!\n)|;
fd7385b9 80 $path = $self->SUPER::canonpath($path);
ae5a807c 81
13688ce5
CB
82 return $path if $unix_rpt;
83 $path = $pathify ? vmspath($path) : vmsify($path);
46726cbe 84 }
ae5a807c 85
13688ce5
CB
86 $path =~ s/(?<!\^)</[/; # < and > ==> [ and ]
87 $path =~ s/(?<!\^)>/]/;
88 $path =~ s/(?<!\^)\]\[\./\.\]\[/g; # ][. ==> .][
89 $path =~ s/(?<!\^)\[000000\.\]\[/\[/g; # [000000.][ ==> [
90 $path =~ s/(?<!\^)\[000000\./\[/g; # [000000. ==> [
91 $path =~ s/(?<!\^)\.\]\[000000\]/\]/g; # .][000000] ==> ]
92 $path =~ s/(?<!\^)\.\]\[/\./g; # foo.][bar ==> foo.bar
93 1 while ($path =~ s/(?<!\^)([\[\.])(-+)\.(-+)([\.\]])/$1$2$3$4/);
bdc74e5c
CB
94 # That loop does the following
95 # with any amount of dashes:
96 # .-.-. ==> .--.
97 # [-.-. ==> [--.
98 # .-.-] ==> .--]
99 # [-.-] ==> [--]
13688ce5 100 1 while ($path =~ s/(?<!\^)([\[\.])[^\]\.]+\.-(-+)([\]\.])/$1$2$3/);
bdc74e5c
CB
101 # That loop does the following
102 # with any amount (minimum 2)
103 # of dashes:
104 # .foo.--. ==> .-.
105 # .foo.--] ==> .-]
106 # [foo.--. ==> [-.
107 # [foo.--] ==> [-]
108 #
109 # And then, the remaining cases
13688ce5
CB
110 $path =~ s/(?<!\^)\[\.-/[-/; # [.- ==> [-
111 $path =~ s/(?<!\^)\.[^\]\.]+\.-\./\./g; # .foo.-. ==> .
112 $path =~ s/(?<!\^)\[[^\]\.]+\.-\./\[/g; # [foo.-. ==> [
113 $path =~ s/(?<!\^)\.[^\]\.]+\.-\]/\]/g; # .foo.-] ==> ]
114 # [foo.-] ==> [000000]
115 $path =~ s/(?<!\^)\[[^\]\.]+\.-\]/\[000000\]/g;
116 # [] ==>
117 $path =~ s/(?<!\^)\[\]// unless $path eq '[]';
118 return $unix_rpt ? unixify($path) : $path;
46726cbe
CB
119}
120
9596c75c 121=item catdir (override)
270d1e39
GS
122
123Concatenates a list of file specifications, and returns the result as a
13688ce5
CB
124native directory specification unless the Unix filename reporting feature
125has been enabled. No check is made for "impossible" cases (e.g. elements
126other than the first being absolute filespecs).
270d1e39
GS
127
128=cut
129
130sub catdir {
ff235dd6
SP
131 my $self = shift;
132 my $dir = pop;
ae5a807c 133
ae5a807c
JM
134 my $unix_rpt = $self->_unix_rpt;
135
ff235dd6
SP
136 my @dirs = grep {defined() && length()} @_;
137
cbc7acb0 138 my $rslt;
270d1e39 139 if (@dirs) {
cbc7acb0
JD
140 my $path = (@dirs == 1 ? $dirs[0] : $self->catdir(@dirs));
141 my ($spath,$sdir) = ($path,$dir);
13688ce5 142 $spath =~ s/\.dir\Z(?!\n)//i; $sdir =~ s/\.dir\Z(?!\n)//i;
ae5a807c 143
13688ce5
CB
144 if ($unix_rpt) {
145 $spath = unixify($spath) unless $spath =~ m#/#;
146 $sdir= unixify($sdir) unless $sdir =~ m#/#;
147 return $self->SUPER::catdir($spath, $sdir)
148 }
149
0a660800 150 $rslt = vmspath( unixify($spath) . '/' . unixify($sdir));
13688ce5
CB
151
152 # Special case for VMS absolute directory specs: these will have
153 # had device prepended during trip through Unix syntax in
154 # eliminate_macros(), since Unix syntax has no way to express
155 # "absolute from the top of this device's directory tree".
156 if ($spath =~ /^[\[<][^.\-]/s) { $rslt =~ s/^[^\[<]+//s; }
ae5a807c 157
ae5a807c 158 } else {
13688ce5
CB
159 # Single directory. Return an empty string on null input; otherwise
160 # just return a canonical path.
ae5a807c 161
13688ce5
CB
162 if (not defined $dir or not length $dir) {
163 $rslt = '';
ae5a807c 164 } else {
13688ce5 165 $rslt = $unix_rpt ? $dir : vmspath($dir);
ae5a807c 166 }
270d1e39 167 }
099f76bb 168 return $self->canonpath($rslt);
270d1e39
GS
169}
170
9596c75c 171=item catfile (override)
270d1e39 172
ae5a807c
JM
173Concatenates a list of directory specifications with a filename specification
174to build a path.
270d1e39
GS
175
176=cut
177
178sub catfile {
ff235dd6 179 my $self = shift;
ae5a807c
JM
180 my $tfile = pop();
181 my $file = $self->canonpath($tfile);
ff235dd6
SP
182 my @files = grep {defined() && length()} @_;
183
ae5a807c
JM
184 my $unix_rpt = $self->_unix_rpt;
185
cbc7acb0 186 my $rslt;
270d1e39 187 if (@files) {
13688ce5 188 my $path = (@files == 1 ? $files[0] : $self->catdir(@files));
cbc7acb0 189 my $spath = $path;
ae5a807c 190
13688ce5 191 # Something building a VMS path in pieces may try to pass a
ae5a807c
JM
192 # directory name in filename format, so normalize it.
193 $spath =~ s/\.dir\Z(?!\n)//i;
194
13688ce5
CB
195 # If the spath ends with a directory delimiter and the file is bare,
196 # then just concatenate them.
61196b43 197 if ($spath =~ /^(?<!\^)[^\)\]\/:>]+\)\Z(?!\n)/s && basename($file) eq $file) {
cbc7acb0 198 $rslt = "$spath$file";
ae5a807c 199 } else {
0a660800 200 $rslt = unixify($spath);
13688ce5
CB
201 $rslt .= (defined($rslt) && length($rslt) ? '/' : '') . unixify($file);
202 $rslt = vmsify($rslt) unless $unix_rpt;
cbc7acb0 203 }
270d1e39 204 }
ae5a807c
JM
205 else {
206 # Only passed a single file?
13688ce5 207 my $xfile = (defined($file) && length($file)) ? $file : '';
ae5a807c 208
44480951 209 $rslt = $unix_rpt ? $xfile : vmsify($xfile);
ae5a807c
JM
210 }
211 return $self->canonpath($rslt) unless $unix_rpt;
212
c4a6f826 213 # In Unix report mode, do not strip off redundant path information.
ae5a807c 214 return $rslt;
270d1e39
GS
215}
216
46726cbe 217
270d1e39
GS
218=item curdir (override)
219
ae5a807c 220Returns a string representation of the current directory: '[]' or '.'
270d1e39
GS
221
222=cut
223
224sub curdir {
ae5a807c
JM
225 my $self = shift @_;
226 return '.' if ($self->_unix_rpt);
270d1e39
GS
227 return '[]';
228}
229
99804bbb
GS
230=item devnull (override)
231
ae5a807c 232Returns a string representation of the null device: '_NLA0:' or '/dev/null'
99804bbb
GS
233
234=cut
235
236sub devnull {
ae5a807c
JM
237 my $self = shift @_;
238 return '/dev/null' if ($self->_unix_rpt);
cbc7acb0 239 return "_NLA0:";
99804bbb
GS
240}
241
270d1e39
GS
242=item rootdir (override)
243
cbc7acb0 244Returns a string representation of the root directory: 'SYS$DISK:[000000]'
ae5a807c 245or '/'
270d1e39
GS
246
247=cut
248
249sub rootdir {
ae5a807c
JM
250 my $self = shift @_;
251 if ($self->_unix_rpt) {
252 # Root may exist, try it first.
253 my $try = '/';
254 my ($dev1, $ino1) = stat('/');
255 my ($dev2, $ino2) = stat('.');
256
257 # Perl falls back to '.' if it can not determine '/'
258 if (($dev1 != $dev2) || ($ino1 != $ino2)) {
259 return $try;
260 }
261 # Fall back to UNIX format sys$disk.
262 return '/sys$disk/';
263 }
cbc7acb0
JD
264 return 'SYS$DISK:[000000]';
265}
266
267=item tmpdir (override)
268
269Returns a string representation of the first writable directory
270from the following list or '' if none are writable:
271
61196b43 272 /tmp if C<DECC$FILENAME_UNIX_REPORT> is enabled.
188ff3c1 273 sys$scratch:
cbc7acb0
JD
274 $ENV{TMPDIR}
275
1d0806cf 276If running under taint mode, and if $ENV{TMPDIR}
a384e9e1
RGS
277is tainted, it is not used.
278
cbc7acb0
JD
279=cut
280
cbc7acb0 281sub tmpdir {
ae5a807c 282 my $self = shift @_;
82730d4c 283 my $tmpdir = $self->_cached_tmpdir('TMPDIR');
cbc7acb0 284 return $tmpdir if defined $tmpdir;
ae5a807c
JM
285 if ($self->_unix_rpt) {
286 $tmpdir = $self->_tmpdir('/tmp', '/sys$scratch', $ENV{TMPDIR});
ae5a807c 287 }
82730d4c
FC
288 else {
289 $tmpdir = $self->_tmpdir( 'sys$scratch:', $ENV{TMPDIR} );
290 }
291 $self->_cache_tmpdir($tmpdir, 'TMPDIR');
270d1e39
GS
292}
293
294=item updir (override)
295
ae5a807c 296Returns a string representation of the parent directory: '[-]' or '..'
270d1e39
GS
297
298=cut
299
300sub updir {
ae5a807c
JM
301 my $self = shift @_;
302 return '..' if ($self->_unix_rpt);
270d1e39
GS
303 return '[-]';
304}
305
46726cbe
CB
306=item case_tolerant (override)
307
308VMS file specification syntax is case-tolerant.
309
310=cut
311
312sub case_tolerant {
313 return 1;
314}
315
270d1e39
GS
316=item path (override)
317
318Translate logical name DCL$PATH as a searchlist, rather than trying
319to C<split> string value of C<$ENV{'PATH'}>.
320
321=cut
322
323sub path {
cbc7acb0 324 my (@dirs,$dir,$i);
270d1e39 325 while ($dir = $ENV{'DCL$PATH;' . $i++}) { push(@dirs,$dir); }
cbc7acb0 326 return @dirs;
270d1e39
GS
327}
328
329=item file_name_is_absolute (override)
330
331Checks for VMS directory spec as well as Unix separators.
332
333=cut
334
335sub file_name_is_absolute {
cbc7acb0 336 my ($self,$file) = @_;
270d1e39 337 # If it's a logical name, expand it.
ee8c7f54 338 $file = $ENV{$file} while $file =~ /^[\w\$\-]+\Z(?!\n)/s && $ENV{$file};
1b1e14d3 339 return scalar($file =~ m!^/!s ||
cbc7acb0 340 $file =~ m![<\[][^.\-\]>]! ||
fc827b9c 341 $file =~ /^[A-Za-z0-9_\$\-\~]+(?<!\^):/);
270d1e39
GS
342}
343
46726cbe
CB
344=item splitpath (override)
345
555bd962
BG
346 ($volume,$directories,$file) = File::Spec->splitpath( $path );
347 ($volume,$directories,$file) = File::Spec->splitpath( $path,
348 $no_file );
486bcc50
NC
349
350Passing a true value for C<$no_file> indicates that the path being
351split only contains directory components, even on systems where you
352can usually (when not supporting a foreign syntax) tell the difference
353between directories and files at a glance.
46726cbe
CB
354
355=cut
356
357sub splitpath {
486bcc50
NC
358 my($self,$path, $nofile) = @_;
359 my($dev,$dir,$file) = ('','','');
ae5a807c 360 my $vmsify_path = vmsify($path);
ae5a807c
JM
361
362 if ( $nofile ) {
486bcc50
NC
363 #vmsify('d1/d2/d3') returns '[.d1.d2]d3'
364 #vmsify('/d1/d2/d3') returns 'd1:[d2]d3'
365 if( $vmsify_path =~ /(.*)\](.+)/ ){
366 $vmsify_path = $1.'.'.$2.']';
367 }
368 $vmsify_path =~ /(.+:)?(.*)/s;
369 $dir = defined $2 ? $2 : ''; # dir can be '0'
370 return ($1 || '',$dir,$file);
371 }
372 else {
373 $vmsify_path =~ /(.+:)?([\[<].*[\]>])?(.*)/s;
374 return ($1 || '',$2 || '',$3);
375 }
46726cbe
CB
376}
377
378=item splitdir (override)
379
ae5a807c 380Split a directory specification into the components.
46726cbe
CB
381
382=cut
383
384sub splitdir {
385 my($self,$dirspec) = @_;
13fbb5b1
JM
386 my @dirs = ();
387 return @dirs if ( (!defined $dirspec) || ('' eq $dirspec) );
ae5a807c 388
13688ce5
CB
389 $dirspec =~ s/(?<!\^)</[/; # < and > ==> [ and ]
390 $dirspec =~ s/(?<!\^)>/]/;
391 $dirspec =~ s/(?<!\^)\]\[\./\.\]\[/g; # ][. ==> .][
392 $dirspec =~ s/(?<!\^)\[000000\.\]\[/\[/g; # [000000.][ ==> [
393 $dirspec =~ s/(?<!\^)\[000000\./\[/g; # [000000. ==> [
394 $dirspec =~ s/(?<!\^)\.\]\[000000\]/\]/g; # .][000000] ==> ]
395 $dirspec =~ s/(?<!\^)\.\]\[/\./g; # foo.][bar ==> foo.bar
bdc74e5c
CB
396 while ($dirspec =~ s/(^|[\[\<\.])\-(\-+)($|[\]\>\.])/$1-.$2$3/g) {}
397 # That loop does the following
398 # with any amount of dashes:
399 # .--. ==> .-.-.
400 # [--. ==> [-.-.
401 # .--] ==> .-.-]
402 # [--] ==> [-.-]
61196b43 403 $dirspec = "[$dirspec]" unless $dirspec =~ /(?<!\^)[\[<]/; # make legal
2e74f398 404 $dirspec =~ s/^(\[|<)\./$1/;
13fbb5b1 405 @dirs = split /(?<!\^)\./, vmspath($dirspec);
ee8c7f54 406 $dirs[0] =~ s/^[\[<]//s; $dirs[-1] =~ s/[\]>]\Z(?!\n)//s;
46726cbe
CB
407 @dirs;
408}
409
410
411=item catpath (override)
412
ae5a807c 413Construct a complete filespec.
46726cbe
CB
414
415=cut
416
417sub catpath {
418 my($self,$dev,$dir,$file) = @_;
638113eb
JH
419
420 # We look for a volume in $dev, then in $dir, but not both
13688ce5
CB
421 my ($dir_volume, $dir_dir, $dir_file) = $self->splitpath($dir);
422 $dev = $dir_volume unless length $dev;
423 $dir = length $dir_file ? $self->catfile($dir_dir, $dir_file) : $dir_dir;
424
425 if ($dev =~ m|^(?<!\^)/+([^/]+)|) { $dev = "$1:"; }
ee8c7f54 426 else { $dev .= ':' unless $dev eq '' or $dev =~ /:\Z(?!\n)/; }
fd7385b9 427 if (length($dev) or length($dir)) {
13688ce5
CB
428 $dir = "[$dir]" unless $dir =~ /(?<!\^)[\[<\/]/;
429 $dir = vmspath($dir);
0994714a 430 }
385aae1c 431 $dir = '' if length($dev) && ($dir eq '[]' || $dir eq '<>');
fd7385b9 432 "$dev$dir$file";
0994714a
GS
433}
434
fd7385b9 435=item abs2rel (override)
0994714a 436
13688ce5 437Attempt to convert an absolute file specification to a relative specification.
0994714a
GS
438
439=cut
440
0994714a
GS
441sub abs2rel {
442 my $self = shift;
13688ce5 443 my($path,$base) = @_;
3420b9a3 444
13688ce5 445 $base = $self->_cwd() unless defined $base and length $base;
0994714a 446
40aa2760
CB
447 # If there is no device or directory syntax on $base, make sure it
448 # is treated as a directory.
3420b9a3 449 $base = vmspath($base) unless $base =~ m{(?<!\^)[\[<:]};
40aa2760 450
b4347c71 451 for ($path, $base) { $_ = $self->rel2abs($_) }
0994714a 452
d84c672d
JH
453 # Are we even starting $path on the same (node::)device as $base? Note that
454 # logical paths or nodename differences may be on the "same device"
455 # but the comparison that ignores device differences so as to concatenate
456 # [---] up directory specs is not even a good idea in cases where there is
457 # a logical path difference between $path and $base nodename and/or device.
458 # Hence we fall back to returning the absolute $path spec
459 # if there is a case blind device (or node) difference of any sort
460 # and we do not even try to call $parse() or consult %ENV for $trnlnm()
461 # (this module needs to run on non VMS platforms after all).
638113eb
JH
462
463 my ($path_volume, $path_directories, $path_file) = $self->splitpath($path);
464 my ($base_volume, $base_directories, $base_file) = $self->splitpath($base);
3420b9a3 465 return $self->canonpath( $path ) unless lc($path_volume) eq lc($base_volume);
d84c672d 466
0994714a
GS
467 # Now, remove all leading components that are the same
468 my @pathchunks = $self->splitdir( $path_directories );
fa52125f 469 my $pathchunks = @pathchunks;
737c380e 470 unshift(@pathchunks,'000000') unless $pathchunks[0] eq '000000';
0994714a 471 my @basechunks = $self->splitdir( $base_directories );
fa52125f 472 my $basechunks = @basechunks;
737c380e 473 unshift(@basechunks,'000000') unless $basechunks[0] eq '000000';
0994714a
GS
474
475 while ( @pathchunks &&
476 @basechunks &&
477 lc( $pathchunks[0] ) eq lc( $basechunks[0] )
478 ) {
479 shift @pathchunks ;
480 shift @basechunks ;
481 }
482
483 # @basechunks now contains the directories to climb out of,
484 # @pathchunks now has the directories to descend in to.
fa52125f
SP
485 if ((@basechunks > 0) || ($basechunks != $pathchunks)) {
486 $path_directories = join '.', ('-' x @basechunks, @pathchunks) ;
487 }
488 else {
489 $path_directories = join '.', @pathchunks;
490 }
491 $path_directories = '['.$path_directories.']';
fd7385b9 492 return $self->canonpath( $self->catpath( '', $path_directories, $path_file ) ) ;
0994714a
GS
493}
494
495
fd7385b9
CB
496=item rel2abs (override)
497
ae5a807c 498Return an absolute file specification from a relative one.
fd7385b9
CB
499
500=cut
501
786b702f 502sub rel2abs {
0994714a 503 my $self = shift ;
0994714a 504 my ($path,$base ) = @_;
bdc74e5c 505 return undef unless defined $path;
13688ce5
CB
506 if ($path =~ m/\//) {
507 $path = ( -d $path || $path =~ m/\/\z/ # educated guessing about
508 ? vmspath($path) # whether it's a directory
509 : vmsify($path) );
ae5a807c 510 }
13688ce5 511 $base = vmspath($base) if defined $base && $base =~ m/\//;
ae5a807c 512
0994714a
GS
513 # Clean up and split up $path
514 if ( ! $self->file_name_is_absolute( $path ) ) {
515 # Figure out the effective $base and clean it up.
516 if ( !defined( $base ) || $base eq '' ) {
0fab864c 517 $base = $self->_cwd;
0994714a
GS
518 }
519 elsif ( ! $self->file_name_is_absolute( $base ) ) {
520 $base = $self->rel2abs( $base ) ;
521 }
522 else {
523 $base = $self->canonpath( $base ) ;
524 }
525
526 # Split up paths
ee8c7f54
CB
527 my ( $path_directories, $path_file ) =
528 ($self->splitpath( $path ))[1,2] ;
0994714a 529
ee8c7f54 530 my ( $base_volume, $base_directories ) =
0994714a
GS
531 $self->splitpath( $base ) ;
532
fd7385b9
CB
533 $path_directories = '' if $path_directories eq '[]' ||
534 $path_directories eq '<>';
0994714a 535 my $sep = '' ;
13688ce5
CB
536 $sep = '.'
537 if ( $base_directories =~ m{[^.\]>]\Z(?!\n)} &&
538 $path_directories =~ m{^[^.\[<]}s
539 ) ;
540 $base_directories = "$base_directories$sep$path_directories";
541 $base_directories =~ s{\.?[\]>][\[<]\.?}{.};
0994714a
GS
542
543 $path = $self->catpath( $base_volume, $base_directories, $path_file );
544 }
545
546 return $self->canonpath( $path ) ;
547}
548
549
cbc7acb0 550=back
270d1e39 551
99f36a73
RGS
552=head1 COPYRIGHT
553
0a660800 554Copyright (c) 2004-14 by the Perl 5 Porters. All rights reserved.
99f36a73
RGS
555
556This program is free software; you can redistribute it and/or modify
557it under the same terms as Perl itself.
558
cbc7acb0
JD
559=head1 SEE ALSO
560
72f15715
T
561See L<File::Spec> and L<File::Spec::Unix>. This package overrides the
562implementation of these methods, not the semantics.
cbc7acb0 563
638113eb 564An explanation of VMS file specs can be found at
385aae1c 565L<http://h71000.www7.hp.com/doc/731FINAL/4506/4506pro_014.html#apps_locating_naming_files>.
638113eb 566
cbc7acb0
JD
567=cut
568
5691;