Subversion Repositories DevTools

Rev

Rev 283 | Rev 325 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
227 dpurdie 1
########################################################################
2
# Copyright ( C ) 2005 ERG Limited, All rights reserved
3
#
4
# Module name   : jats.sh
5
# Module type   : Perl Package
6
# Compiler(s)   : n/a
7
# Environment(s): jats
8
#
9
# Description   : This package contains functions to manipulate file paths
10
#                 directories and names.
11
#
12
#                    Getcwd                     - Get current directory
13
#                    Realpath                   - Get real path
14
#                    Realfile                   - Get real path ?
15
#                    RelPath                    - Convert to relative path
16
#                    AbsPath                    - Convert to Abs path
17
#                    FullPath                   - Convert to Abs path with driver letter
257 dpurdie 18
#                    TruePath                   - Case Corrected pathname
227 dpurdie 19
#                    CleanPath                  - Clean up a path
20
#                    StripDrive                 - Remove drive letter
21
#                    StripDir                   - Return file + extension
22
#                    StripExt                   - Return dir + file
23
#                    StripFile                  - Returns extension
24
#                    StripFileExt               - Returns directory
25
#                    StripDirExt                - Returns filename ( with optional ext)
26
#                    CleanDirName               - Clean up a path
261 dpurdie 27
#                    TouchFile                  - Touch a file
28
#                    FileIsNewer                - Test if newer
227 dpurdie 29
#                    DisplayPath                - Genate a Path that can be displayed
261 dpurdie 30
#                    FileCreate                 - Create a simple text file
31
#                    FileAppend                 - Append to a simple text file
227 dpurdie 32
#
33
#
34
#......................................................................#
35
 
255 dpurdie 36
use 5.006_001;
227 dpurdie 37
use strict;
38
use warnings;
39
 
40
################################################################################
41
#   Global variables used by functions in this package
42
#   For historical reasons many of these variabeles are global
43
#
44
 
45
package FileUtils;
283 dpurdie 46
use base qw(Exporter);
47
 
227 dpurdie 48
use JatsError;
49
use Cwd;
283 dpurdie 50
our (@EXPORT, @EXPORT_OK, %EXPORT_TAGS, $VERSION);
227 dpurdie 51
 
52
$VERSION = 1.00;
53
 
54
# Symbols to autoexport (:DEFAULT tag)
55
@EXPORT = qw(   InitFileUtils
56
                Getcwd
57
                Realpath
58
                RelPath
59
                AbsPath
60
                FullPath
61
                CleanPath
62
                StripDrive
63
                StripDir
64
                StripExt
65
                StripFile
66
                StripFileExt
67
                StripDirExt
68
                CleanDirName
69
                TouchFile
70
                FileIsNewer
71
                DisplayPath
257 dpurdie 72
                TruePath
261 dpurdie 73
                FileCreate
74
                FileAppend
227 dpurdie 75
 
76
                $ScmPathSep
261 dpurdie 77
                $ScmDirSep
227 dpurdie 78
                $Cwd
79
                $CwdDrive
80
                $ScmHost
81
            );
82
#
83
# exported package globals go here
84
#
85
our $ScmPathSep;                # Windows/Unix path seperator
261 dpurdie 86
our $ScmDirSep;                 # Windows/Unix dir sep
227 dpurdie 87
our $Cwd       ;                # Current directory ( no drive letter )
247 dpurdie 88
our $CwdFull   ;                # Current directory ( with drive letter )
227 dpurdie 89
our $CwdDrive  ;                # Current drive
90
our $ScmHost   ;                # Host Type. Unix, WIN
91
 
92
#
93
#   Internal variables
94
#
95
my  $isCygWin;                 # Running under CygWin
96
my  $isUnix;                   # Is Unix
97
 
98
#-------------------------------------------------------------------------------
99
# Function        : BEGIN
100
#
101
# Description     : Determine some values very early
102
#
103
#
104
BEGIN
105
{
106
    $ScmHost = "Unix";                                # UNIX, default
107
 
108
    Debug( "PerlHost:  $^O" );
109
    $ScmHost = "DOS"      if ($^O eq "win95");        # DOS Perl dependent
110
    $ScmHost = "WIN"      if ($^O eq "MSWin32");      # ActivePerl
111
    $ScmHost = "WIN"      if ($^O eq "cygwin");       # Cygwin
112
 
113
    $isUnix = 1 if ( $ScmHost eq "Unix"  );
255 dpurdie 114
    $isCygWin = 1 if ( $ENV{'SHELL'} || $ENV{'CYGWIN'} );
227 dpurdie 115
 
116
    $ScmPathSep = $isUnix ? ':' : ';';     # Unix / Windows
261 dpurdie 117
    $ScmDirSep = $isUnix ? '/' : '\\';     # Unix / Windows
227 dpurdie 118
}
119
 
120
#-------------------------------------------------------------------------------
121
# Function        : InitFileUtils
122
#
123
# Description     : Initialise this package
124
#                   This function should be called once the user has determined
125
#                   settled on a working directory
126
#
127
#                   The function may be called multiple times
128
#                   to allow various globals to be reset - when the user has
129
#                   changed directory
130
#
131
# Inputs          : Nothing
132
#
133
# Returns         : Nothing
134
#
135
sub InitFileUtils
136
{
137
    #
138
    #   Setup current directory and drive
139
    #
140
 
247 dpurdie 141
    $CwdFull = Getcwd();                    # Current working dir
227 dpurdie 142
 
143
    $CwdDrive = '';
247 dpurdie 144
    $CwdDrive = substr( $CwdFull, 0, 2 )    # Saved Drive letter
227 dpurdie 145
        if ( ! $isUnix );
146
 
247 dpurdie 147
    $Cwd = StripDrive( $CwdFull );          # With drive spec striped
227 dpurdie 148
 
149
    Debug ("InitFileUtils: ScmHost     : $ScmHost");
247 dpurdie 150
    Debug ("InitFileUtils: CwdFull     : $CwdFull");
227 dpurdie 151
    Debug ("InitFileUtils: Cwd         : $Cwd");
152
    Debug ("InitFileUtils: CwdDrive    : $CwdDrive");
153
    Debug ("InitFileUtils: ScmPathSep  : $ScmPathSep");
154
}
155
 
156
 
157
#-------------------------------------------------------------------------------
158
# Function        : Getcwd
159
#
160
# Description     : Retrieve current working directory
161
#
162
# Inputs          : None
163
#
164
# Returns         : The current working directory
165
#
166
# Notes           : Don't use 'pwd' program as it gets symbolic links wrong
167
#
168
sub Getcwd
169
{
170
    my $cwd = getcwd();
171
    return $cwd;
172
}
173
 
174
#-------------------------------------------------------------------------------
261 dpurdie 175
# Function        : TouchFile 
227 dpurdie 176
#
177
# Description     : touch a file
178
#                   Real use is to touch a marker file
179
#
180
# Inputs          : path        - path to the file
181
#
182
# Returns         : TRUE if an error occured in creating the file
183
#
184
sub TouchFile
185
{
186
    my ($path, $text) = @_;
187
    my $result = 0;
283 dpurdie 188
    my $tfh;
189
 
227 dpurdie 190
    Verbose ("Touching file: $path" );
191
    if ( ! -f $path )
192
    {
283 dpurdie 193
        open ($tfh, ">>", $path) || ($result = 1);
194
        close $tfh;
227 dpurdie 195
    }
196
    else
197
    {
198
 
199
        #
200
        #   Modify the file
201
        #
202
        #   Need to physically modify the file
203
        #   Need to change the 'change time' on the file. Simply setting the
204
        #   last-mod and last-access is not enough to get past WIN32
205
        #   OR 'utime()' does not work as expected
206
        #
207
        #   Read in the first character of the file, rewind and write it
208
        #   out again.
209
        #
210
        my $data;
283 dpurdie 211
        open ($tfh , "+<", $path ) || return 1;
212
        if ( read ( $tfh, $data, 1 ) )
213
        {
214
            seek  ( $tfh, 0, 0 );
215
            print $tfh $data;
227 dpurdie 216
        }
217
        else
218
        {
219
            #
220
            #   File must have been of zero length
221
            #   Delete the file and create it
222
            #
283 dpurdie 223
            close ($tfh);
227 dpurdie 224
            unlink ( $path );
283 dpurdie 225
            open ($tfh, ">>", $path) || ($result = 1);
227 dpurdie 226
        }
283 dpurdie 227
        close ($tfh);
227 dpurdie 228
    }
229
    return $result;
230
}
231
 
232
#-------------------------------------------------------------------------------
261 dpurdie 233
# Function        : FileCreate
234
#                   FileAppend
235
#                   _FileWrite
236
#
237
# Description     : Simple Text File Creation function
238
#                   Suited to the creation of small, simple text files.
239
#
240
# Inputs          : Name of the file
241
#                   Remainder are:
242
#                       Lines of data to output to the file
243
#                       Or a reference to an array of lines
244
#                       Or a mixture
245
#                   All lines will be terminated with a "\n"
246
#
247
# Returns         : Nothing
248
#
249
sub FileCreate
250
{
251
    _FileWrite ( '>', @_ );
252
}
253
 
254
sub FileAppend
255
{
256
    _FileWrite ( '>>', @_ );
257
}
258
 
259
sub _FileWrite
260
{
261
    my $mode = shift @_;
262
    my $name = shift @_;
283 dpurdie 263
    my $fh;
261 dpurdie 264
 
265
    Error ("FileCreate: No file specified") unless ( $name );
266
    Error ("FileCreate: Path is directory") if ( -d $name );
267
 
283 dpurdie 268
    open  ($fh, $mode, $name ) || Error( "Cannot create file: $name", "Reason: $!" );
261 dpurdie 269
 
270
    foreach my $entry ( @_ ) {
271
        if ( ref ($entry ) eq 'ARRAY'  ) {
283 dpurdie 272
            print $fh $_ . "\n" foreach  ( @$entry );
261 dpurdie 273
        } else {
283 dpurdie 274
            print $fh $entry . "\n"
261 dpurdie 275
        }
276
    }
283 dpurdie 277
    close $fh;
261 dpurdie 278
}
279
 
280
#-------------------------------------------------------------------------------
227 dpurdie 281
# Function        : FileIsNewer
282
#
283
# Description     : Test two files to see if the files are newer
284
#
285
# Inputs          : file1
286
#                   file2
287
#
288
# Returns         : Returns true if file1 is newer than file2 or file2 does not
289
#                   exist.
290
#
291
#                   If file 1 does not exist then it will return false
292
#
293
sub FileIsNewer
294
{
295
    my ($file1, $file2) = @_;
296
 
297
    my $f1_timestamp = (stat($file1))[9] || 0;
298
    my $f2_timestamp = (stat($file2))[9] || 0;
299
    my $result = $f1_timestamp > $f2_timestamp ? 1 : 0;
300
 
301
    Verbose2 ("FileIsNewer: TS: $f1_timestamp, File: $file1");
302
    Verbose2 ("FileIsNewer: TS: $f2_timestamp, File: $file2");
303
    Verbose2 ("FileIsNewer: $result" );
304
 
305
    return $result;
306
}
307
 
308
#-------------------------------------------------------------------------------
309
# Function        : Realpath
310
#
311
# Description     : Returns the 'real path'
312
#
313
# Inputs          : $path       - Path to process
314
#
315
# Returns         : The real path
316
#
317
sub Realpath
318
{
319
    my( $path ) = @_;
320
    my( $real, $cwd );
321
 
322
    $cwd = Getcwd();
323
    if (!chdir( $path )) {
324
        $real = "";
325
    } else {
326
        $real = Getcwd();
327
        Error ("FATAL: Realpath($path) could not restore directory ($cwd)." )
328
            unless (chdir( $cwd ));
329
    }
330
    Debug( "Realpath:   = $real ($path)" );
331
    return $real;
332
}
333
 
334
#-------------------------------------------------------------------------------
335
# Function        : Realfile
336
#
337
# Description     : Returns the 'real path'
338
#
339
# Inputs          : $path       - Path to process
340
#
341
# Returns         : The real path
342
#
343
#sub Realfile
344
#{
345
#    my( $path ) = @_;
346
#    my( $real, $cwd );
347
#
348
#    $cwd = Getcwd();
349
#    if (!chdir( $path )) {
350
#        $real = "";
351
#    } else {
352
#        $real = Getcwd();
353
#        Error ("FATAL: Realpath($path) could not restore directory ($cwd)." )
354
#            unless (chdir( $cwd ));
355
#    }
356
#    Debug( "Realpath:   = $real ($path)" );
357
#    return $real;
358
#}
359
 
360
#-------------------------------------------------------------------------------
361
# Function        : RelPath
362
#
363
# Description     : Return the relative path to the current working directory
364
#                   as provided in $Cwd
365
#
285 dpurdie 366
# Inputs          : $base       - Base directory to convert
367
#                   $here       - Optional current directory
368
#                                 $Cwd will be used if non provided
227 dpurdie 369
#
370
# Returns         : Relative path from the current directory to the base directory
371
#
372
sub RelPath
373
{
285 dpurdie 374
    my ($base, $here) = @_;
227 dpurdie 375
 
285 dpurdie 376
    $here = $Cwd unless ( defined $here );
377
 
227 dpurdie 378
    my @base = split ('/', $base );
285 dpurdie 379
    my @here = split ('/', $here );
227 dpurdie 380
    my $result;
381
 
382
    Debug("RelPath: Source: $base");
383
 
384
    return $base unless ( $base =~ m~^/~ );
385
 
386
    #
387
    #   Remove common bits from the head of both lists
388
    #
389
    while ( $#base >= 0 && $#here >= 0 && $base[0] eq $here[0] )
390
    {
391
        shift @base;
392
        shift @here;
393
    }
394
 
395
    #
396
    #   Need to go up some directories from here and then down into base
397
    #
398
    $result = '../' x ($#here + 1);
399
    $result .= join ( '/', @base);
400
    $result = '.' unless ( $result );
401
    $result =~ s~/$~~;
402
 
403
    Debug("RelPath: Result: $result");
404
    return $result;
405
}
406
 
407
#-------------------------------------------------------------------------------
408
# Function        : AbsPath
409
#
410
# Description     : Return the absolute path to the file
411
#                   Add the current directory if the path is absolute
412
#                   Clean up xxx/.. constructs
413
#
414
#                   If an absolute path is provided then it will simply be
415
#                   cleaned up.
416
#
417
# Assumption      : Absolute paths start with a "/" and do not have a drive letter
418
#
419
# Inputs          : Source file path
420
#
421
# Returns         : Cleaned abs path
422
#
423
sub AbsPath
424
{
425
    my ($dpath) = @_;
426
    my @result;
427
 
428
    #
429
    #   If we have a relative path then prepend the current directory
430
    #   An absolute path is:
431
    #           /aaa/aa/aa
432
    #       or  c:/aaa/aa/aa
433
    #
434
    $dpath = $Cwd . '/' . $dpath
435
        unless ( $dpath =~ m~^/|\w:/~  );
436
    $dpath =~ s~//~/~g;
437
 
438
    #
439
    #   Walk the bits and remove ".." directories
440
    #       Done by pushing non-.. elements and poping last entry for .. elements.
441
    #   Have a leading "/" which is good.
442
    #
443
    foreach ( split ( '/', $dpath ) )
444
    {
445
        next if ( $_ eq '.' );
446
        unless ( $_ eq '..' )
447
        {
448
            push @result, $_;
449
        }
450
        else
451
        {
452
            Error ("Bad Pathname: $dpath")
453
                if ( $#result <= 0 );
454
            pop @result;
455
        }
456
    }
457
 
458
    #
459
    #   Create a nice directory name again.
460
    #
461
    return join ( '/', @result );
462
}
463
 
464
#-------------------------------------------------------------------------------
465
# Function        : FullPath
466
#
467
# Description     : Return the absolute path to the file - with driver letter
468
#                   Add the current directory if the path is absolute
469
#                   Clean up xxx/.. constructs
470
#
471
#                   If an absolute path is provided then it will simply be
472
#                   cleaned up.
473
#
474
# Inputs          : Source file path
475
#
476
# Returns         : Cleaned abs path
477
#
478
sub FullPath
479
{
480
    my $path = AbsPath (@_ );
229 dpurdie 481
    $path = $CwdDrive . $path unless ( $path =~ m~^\w:~  );
227 dpurdie 482
    return $path;
483
}
484
 
485
#-------------------------------------------------------------------------------
257 dpurdie 486
# Function        : TruePath
487
#
488
# Description     : Returns a case correct pathname
489
#                   Really only applicable to windows, under unix it returns
490
#                   its input path.
491
#
492
#                   Maintains a cache to speed up processing
493
#
494
# Inputs          : Confused path (Absolute with a driver letter)
495
#
496
# Returns         : Case Correct Path : Windows
497
#                   Input Path : Non Windows
498
#
499
my %TruePathCache;
500
my %DirRead;
501
sub TruePath
502
{
503
    my ($path) = @_;
504
    $path =~ tr~\\/~/~s;
505
 
506
    #
507
    #   On Unix systems the path is case sensitive to start with
508
    #   Can't get it wrong - can't do anything.
509
    #
510
    return $path if ( $isUnix );
511
 
512
    #
513
    #   If the path does not exist at all then return the user input
514
    #   Assume that the user will handle this later
515
    #
516
    unless ( -e $path )
517
    {
518
        Warning ("TruePath given invalid path: $path");
519
        return $path;
520
    }
521
 
522
    #
523
    #   Look in the cache - have we seen this before
524
    #
525
    if ( exists $TruePathCache{lc($path)} )
526
    {
527
        Verbose( "TruePath Cache Hit: $path");
528
        return $TruePathCache{lc($path)};
529
    }
530
 
531
    #
532
    #   Split the directory into components
533
    #
534
    my $TrueComponent = '';
535
    my @components = split ('/', $path );
536
    foreach my $elem ( @components )
537
    {
538
        Debug ("Process: $elem in $TrueComponent");
539
        my $tag;
540
        #
541
        #   Handle driver letter
542
        #
543
        if ( $elem =~ m~^[a-zA-Z]:$~ )
544
        {
545
            $elem = uc($elem);
546
            $TrueComponent = $elem;
547
 
548
            $tag = lc($TrueComponent);
549
            $TruePathCache{$tag} = $elem;
550
            Debug ("     Add: $elem");
551
            next;
552
        }
553
 
554
        #
555
        #   Ensure that we have read in containing directory
556
        #   Note: Append / to ensure we read root directories correctly
557
        #
558
        $TrueComponent .= '/';
559
        unless ( $DirRead{ $TrueComponent }  )
560
        {
561
            Debug ("Reading: $TrueComponent");
285 dpurdie 562
            opendir (my $tp, $TrueComponent ) or Error ("Cannot open $TrueComponent");
563
            my @dirlist = readdir $tp;
564
            closedir $tp;
257 dpurdie 565
            $DirRead {$TrueComponent } = 1;
566
 
567
            #
568
            #   Add cache entries for each path in the directory
569
            #
570
            foreach my $dir ( @dirlist )
571
            {
572
                next if ( $dir eq '.' );
573
                next if ( $dir eq '..' );
574
                my $fullpath = $TrueComponent . $dir;
575
                Debug ("     Add: $fullpath");
576
                $TruePathCache{lc($fullpath)} = $fullpath;
577
            }
578
        }
579
 
580
        #
581
        #   Now that we have populated the cache with data from the directory
582
        #   we can expect to find our desired entry in the cache.
583
        #
584
        $tag = lc($TrueComponent . $elem );
585
        if ( exists $TruePathCache{ $tag } )
586
        {
587
            $TrueComponent = $TruePathCache{ $tag };
588
        }
589
        else
590
        {
591
            DebugDumpData ("Cache", \%TruePathCache);
592
            Error ("TruePath Internal error. File may have been deleted: $tag");
593
        }
594
        Debug ("Have: $TrueComponent");
595
    }
596
 
597
    Verbose ("TruePath: $TrueComponent");
598
    return $TrueComponent;
599
}
600
 
601
#-------------------------------------------------------------------------------
227 dpurdie 602
# Function        : CleanPath
603
#
604
# Description     : Cleanup a path
605
#                   Remove xxx/.. constructs
606
#
607
# Note            : Will not perform error detection on badly formed
608
#                   absolute paths.
609
#
610
# Inputs          : Source file path
611
#
612
# Returns         : Clean absolute or relative path
613
#
614
#
615
sub CleanPath
616
{
617
    my ($dpath) = @_;
618
    my @result;
619
    Debug("CleanPath: Source: $dpath");
620
 
621
    #
622
    #   Cleanup the the user input. Remove double delimiters and ensure there
623
    #   is no trailing delemiter
624
    #
245 dpurdie 625
    $dpath =~ s~/+~/~g;
227 dpurdie 626
    $dpath =~ s~/$~~g;
627
 
628
    #
629
    #   Walk the bits and remove "xxx/.." directories
630
    #
631
    foreach ( split ( '/', $dpath ) )
632
    {
633
        if ( $_ ne '..' || $#result < 0 )
634
        {
635
            push @result, $_;
636
        }
637
        else
638
        {
639
            if ( $#result >= 0 )
640
            {
283 dpurdie 641
                my $last_dir = pop @result;
642
                push (@result, $last_dir, $_)
643
                    if ($last_dir eq '..' || $last_dir eq '');
227 dpurdie 644
            }
645
        }
646
    }
647
 
648
    my $result = join ( '/', @result );
649
    Debug("CleanPath: Result: $result");
650
    return $result;
651
}
652
 
653
#-------------------------------------------------------------------------------
654
# Function        : StripDrive
655
#
656
# Description     : Strip any leading drive speification
657
#
658
# Inputs          : $fname          - Path to process
659
#
660
# Returns         : Path, with drive letter stripped
661
#                   Will do nothing on Unix systems
662
#
663
sub StripDrive
664
{
665
    my( $fname ) = @_;                          # Full name
666
 
667
    $fname =~ s/^[A-Za-z]://g                  # leading drive spec
668
        if ( ! $isUnix );
669
    return $fname;
670
}
671
 
672
#-------------------------------------------------------------------------------
673
# Function        : StripDir
674
#
675
# Description     : Strip directory (returns file, including extension)
676
#
677
# Inputs          : $fname          - Path to process
678
#
679
# Returns         : filename + extension
680
#
681
sub StripDir
682
{
683
    my( $fname ) = @_;                          # Full name
684
    my( $idx );
685
 
686
    if (($idx = rindex($fname, "/")) == -1) {
687
        if (($idx = rindex($fname, "\\")) == -1) {
688
            return $fname;                      # No path ...
689
        }
690
    }
691
    return substr($fname, $idx+1, 512);
692
}
693
 
694
#-------------------------------------------------------------------------------
695
# Function        : StripExt
696
#
697
# Description     : Strip extension (return basename, plus any dir)
698
#
699
# Inputs          : $fname          - Path to process
700
#
701
# Returns         : basename, plus any dir
702
#                   Simply removes one extension
703
#
704
sub StripExt
705
{
706
    my( $fname ) = @_;
707
 
708
    $fname =~ s/(\S+)(\.\S+)/$1/;               # strip out trailing '.<ext>'
709
    return ($fname);
710
}
711
 
712
#-------------------------------------------------------------------------------
713
# Function        : StripFile
714
#
715
# Description     : Strip filename (returns extension)
716
#
717
# Inputs          : $fname          - Path to process
718
#
719
# Returns         : extension
720
#                   Will return an empty string if the input does not have an
721
#                   extension.
722
#
723
sub StripFile
724
{
725
    my( $fname ) = @_;
726
 
727
    $fname =~ s/(\S+)(\.\S+)/$2/;               # Strip out items before '.<ext>'
728
    return ("")                                 # No extension
729
        if ("$fname" eq "@_");
730
    return ($fname);
731
}
732
 
733
#-------------------------------------------------------------------------------
734
# Function        : StripFileExt
735
#
736
# Description     : Strip filename and ext (returns dir)
737
#
738
# Inputs          : $fname          - Path to process
739
#
740
# Returns         : Directory of a file path
741
#
742
 
743
 
744
#   StripFileExt( path ) ---
745
#       Strip filename and ext (returns dir)
746
#..
747
 
748
sub StripFileExt
749
{
750
    my( $fname ) = @_;                          # Full name
751
    my( $idx );
752
    my $dir;
753
 
754
    if (($idx = rindex($fname, "/")) == -1) {
755
        if (($idx = rindex($fname, "\\")) == -1) {
756
            return "";                          # No path ...
757
        }
758
    }
759
 
760
    return substr($fname, 0, $idx);
761
}
762
 
763
#-------------------------------------------------------------------------------
764
# Function        : StripDirExt
765
#
766
# Description     : Strip the directory and extension from a file
767
#                   Returning the base file. Optionally replace the extension
768
#                   with a user value
769
#
770
# Inputs          : Full path name
771
#                   Optional extension to be replaced
772
#
773
# Returns         :
774
#
775
sub StripDirExt
776
{
777
    my ($fname, $ext ) = (@_, '');
778
    $fname =~ s~.*[/\\]~~;                      # Strip directory
779
    $fname =~ s/\.[^.]+$/$ext/;
780
    return $fname;
781
}
782
 
783
 
784
#-------------------------------------------------------------------------------
785
# Function        : CleanDirName
786
#
787
# Description     : Clean up a directory path string
788
#                       1) Remove multiple //
789
#                       2) Remove multiple /./
790
#                       2) Remove leading ./
791
#                       3) Remove trailing /
792
#                       4) Remove /xxxx/../
793
#
794
# Inputs          : A dirty directory path
795
#
796
# Returns         : A clean directory path
797
#
798
sub CleanDirName
799
{
800
    my ( $dir ) = @_;
801
    $dir =~ s~//~/~g;                   # Kill multiple //
802
    $dir =~ s~/\./~/~g;                 # Kill multiple /./
803
    $dir =~ s~^\./~~;                   # Kill leading ./
804
    $dir = '.' unless ( $dir );         # Ensure we have a path
805
 
806
    #
807
    #   Remove /xxxxx/../ bits
808
    #
809
    unless ( $dir =~ m~^\.\./~  )
810
    {
811
        while ( $dir =~ s~
812
                        (^|/)               # Allow for stings that may not start with a /
813
                        [^/]+/\.\.          # xxxxx/.., where xxxx is anything other than a /
814
                        (/|$)               # Allow for strings ending with /..
815
                        ~$1~x               # Replace with the start character
816
              )
817
        {
818
            last if ( $dir =~ m~^\.\./~ );  # Too far. Stop now !
819
        }
820
    }
821
 
822
    $dir =~ s~/$~~;                     # No trailing /
823
    $dir =~ s~/\.$~~;                   # No trailing /.
824
    return $dir;
825
}
826
 
827
#-------------------------------------------------------------------------------
828
# Function        : DisplayPath
829
#
830
# Description     : Cleanup a path for display purposes
831
#                   Useful under windows to provide paths with \ that can be
832
#                   cut and pasted.
833
#
834
#                   If cygwin is located in the environment, then this function
835
#                   will not convert / to \.
836
#
837
# Inputs          : A path to modify
838
#
839
# Returns         : Modified path
840
#
841
sub DisplayPath
842
{
843
    my ($path) = @_;
844
    if ( ! $isUnix && ! $isCygWin )
845
    {
846
        $path =~ s~/~\\~g;
847
    }
848
    return $path;
849
}
850
 
851
1;
852
 
853