Subversion Repositories DevTools

Rev

Rev 261 | Rev 285 | 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
#
366
# Inputs          : Base directory to convert
367
#
368
# Returns         : Relative path from the current directory to the base directory
369
#
370
sub RelPath
371
{
372
    my ($base) = @_;
373
 
374
    my @base = split ('/', $base );
375
    my @here = split ('/', $Cwd );
376
    my $result;
377
 
378
    Debug("RelPath: Source: $base");
379
 
380
    return $base unless ( $base =~ m~^/~ );
381
 
382
    #
383
    #   Remove common bits from the head of both lists
384
    #
385
    while ( $#base >= 0 && $#here >= 0 && $base[0] eq $here[0] )
386
    {
387
        shift @base;
388
        shift @here;
389
    }
390
 
391
    #
392
    #   Need to go up some directories from here and then down into base
393
    #
394
    $result = '../' x ($#here + 1);
395
    $result .= join ( '/', @base);
396
    $result = '.' unless ( $result );
397
    $result =~ s~/$~~;
398
 
399
    Debug("RelPath: Result: $result");
400
    return $result;
401
}
402
 
403
#-------------------------------------------------------------------------------
404
# Function        : AbsPath
405
#
406
# Description     : Return the absolute path to the file
407
#                   Add the current directory if the path is absolute
408
#                   Clean up xxx/.. constructs
409
#
410
#                   If an absolute path is provided then it will simply be
411
#                   cleaned up.
412
#
413
# Assumption      : Absolute paths start with a "/" and do not have a drive letter
414
#
415
# Inputs          : Source file path
416
#
417
# Returns         : Cleaned abs path
418
#
419
sub AbsPath
420
{
421
    my ($dpath) = @_;
422
    my @result;
423
 
424
    #
425
    #   If we have a relative path then prepend the current directory
426
    #   An absolute path is:
427
    #           /aaa/aa/aa
428
    #       or  c:/aaa/aa/aa
429
    #
430
    $dpath = $Cwd . '/' . $dpath
431
        unless ( $dpath =~ m~^/|\w:/~  );
432
    $dpath =~ s~//~/~g;
433
 
434
    #
435
    #   Walk the bits and remove ".." directories
436
    #       Done by pushing non-.. elements and poping last entry for .. elements.
437
    #   Have a leading "/" which is good.
438
    #
439
    foreach ( split ( '/', $dpath ) )
440
    {
441
        next if ( $_ eq '.' );
442
        unless ( $_ eq '..' )
443
        {
444
            push @result, $_;
445
        }
446
        else
447
        {
448
            Error ("Bad Pathname: $dpath")
449
                if ( $#result <= 0 );
450
            pop @result;
451
        }
452
    }
453
 
454
    #
455
    #   Create a nice directory name again.
456
    #
457
    return join ( '/', @result );
458
}
459
 
460
#-------------------------------------------------------------------------------
461
# Function        : FullPath
462
#
463
# Description     : Return the absolute path to the file - with driver letter
464
#                   Add the current directory if the path is absolute
465
#                   Clean up xxx/.. constructs
466
#
467
#                   If an absolute path is provided then it will simply be
468
#                   cleaned up.
469
#
470
# Inputs          : Source file path
471
#
472
# Returns         : Cleaned abs path
473
#
474
sub FullPath
475
{
476
    my $path = AbsPath (@_ );
229 dpurdie 477
    $path = $CwdDrive . $path unless ( $path =~ m~^\w:~  );
227 dpurdie 478
    return $path;
479
}
480
 
481
#-------------------------------------------------------------------------------
257 dpurdie 482
# Function        : TruePath
483
#
484
# Description     : Returns a case correct pathname
485
#                   Really only applicable to windows, under unix it returns
486
#                   its input path.
487
#
488
#                   Maintains a cache to speed up processing
489
#
490
# Inputs          : Confused path (Absolute with a driver letter)
491
#
492
# Returns         : Case Correct Path : Windows
493
#                   Input Path : Non Windows
494
#
495
my %TruePathCache;
496
my %DirRead;
497
sub TruePath
498
{
499
    my ($path) = @_;
500
    $path =~ tr~\\/~/~s;
501
 
502
    #
503
    #   On Unix systems the path is case sensitive to start with
504
    #   Can't get it wrong - can't do anything.
505
    #
506
    return $path if ( $isUnix );
507
 
508
    #
509
    #   If the path does not exist at all then return the user input
510
    #   Assume that the user will handle this later
511
    #
512
    unless ( -e $path )
513
    {
514
        Warning ("TruePath given invalid path: $path");
515
        return $path;
516
    }
517
 
518
    #
519
    #   Look in the cache - have we seen this before
520
    #
521
    if ( exists $TruePathCache{lc($path)} )
522
    {
523
        Verbose( "TruePath Cache Hit: $path");
524
        return $TruePathCache{lc($path)};
525
    }
526
 
527
    #
528
    #   Split the directory into components
529
    #
530
    my $TrueComponent = '';
531
    my @components = split ('/', $path );
532
    foreach my $elem ( @components )
533
    {
534
        Debug ("Process: $elem in $TrueComponent");
535
        my $tag;
536
        #
537
        #   Handle driver letter
538
        #
539
        if ( $elem =~ m~^[a-zA-Z]:$~ )
540
        {
541
            $elem = uc($elem);
542
            $TrueComponent = $elem;
543
 
544
            $tag = lc($TrueComponent);
545
            $TruePathCache{$tag} = $elem;
546
            Debug ("     Add: $elem");
547
            next;
548
        }
549
 
550
        #
551
        #   Ensure that we have read in containing directory
552
        #   Note: Append / to ensure we read root directories correctly
553
        #
554
        $TrueComponent .= '/';
555
        unless ( $DirRead{ $TrueComponent }  )
556
        {
557
            Debug ("Reading: $TrueComponent");
558
            opendir (TP, $TrueComponent ) or Error ("Cannot open $TrueComponent");
559
            my @dirlist = readdir TP;
560
            close TP;
561
            $DirRead {$TrueComponent } = 1;
562
 
563
            #
564
            #   Add cache entries for each path in the directory
565
            #
566
            foreach my $dir ( @dirlist )
567
            {
568
                next if ( $dir eq '.' );
569
                next if ( $dir eq '..' );
570
                my $fullpath = $TrueComponent . $dir;
571
                Debug ("     Add: $fullpath");
572
                $TruePathCache{lc($fullpath)} = $fullpath;
573
            }
574
        }
575
 
576
        #
577
        #   Now that we have populated the cache with data from the directory
578
        #   we can expect to find our desired entry in the cache.
579
        #
580
        $tag = lc($TrueComponent . $elem );
581
        if ( exists $TruePathCache{ $tag } )
582
        {
583
            $TrueComponent = $TruePathCache{ $tag };
584
        }
585
        else
586
        {
587
            DebugDumpData ("Cache", \%TruePathCache);
588
            Error ("TruePath Internal error. File may have been deleted: $tag");
589
        }
590
        Debug ("Have: $TrueComponent");
591
    }
592
 
593
    Verbose ("TruePath: $TrueComponent");
594
    return $TrueComponent;
595
}
596
 
597
#-------------------------------------------------------------------------------
227 dpurdie 598
# Function        : CleanPath
599
#
600
# Description     : Cleanup a path
601
#                   Remove xxx/.. constructs
602
#
603
# Note            : Will not perform error detection on badly formed
604
#                   absolute paths.
605
#
606
# Inputs          : Source file path
607
#
608
# Returns         : Clean absolute or relative path
609
#
610
#
611
sub CleanPath
612
{
613
    my ($dpath) = @_;
614
    my @result;
615
    Debug("CleanPath: Source: $dpath");
616
 
617
    #
618
    #   Cleanup the the user input. Remove double delimiters and ensure there
619
    #   is no trailing delemiter
620
    #
245 dpurdie 621
    $dpath =~ s~/+~/~g;
227 dpurdie 622
    $dpath =~ s~/$~~g;
623
 
624
    #
625
    #   Walk the bits and remove "xxx/.." directories
626
    #
627
    foreach ( split ( '/', $dpath ) )
628
    {
629
        if ( $_ ne '..' || $#result < 0 )
630
        {
631
            push @result, $_;
632
        }
633
        else
634
        {
635
            if ( $#result >= 0 )
636
            {
283 dpurdie 637
                my $last_dir = pop @result;
638
                push (@result, $last_dir, $_)
639
                    if ($last_dir eq '..' || $last_dir eq '');
227 dpurdie 640
            }
641
        }
642
    }
643
 
644
    my $result = join ( '/', @result );
645
    Debug("CleanPath: Result: $result");
646
    return $result;
647
}
648
 
649
#-------------------------------------------------------------------------------
650
# Function        : StripDrive
651
#
652
# Description     : Strip any leading drive speification
653
#
654
# Inputs          : $fname          - Path to process
655
#
656
# Returns         : Path, with drive letter stripped
657
#                   Will do nothing on Unix systems
658
#
659
sub StripDrive
660
{
661
    my( $fname ) = @_;                          # Full name
662
 
663
    $fname =~ s/^[A-Za-z]://g                  # leading drive spec
664
        if ( ! $isUnix );
665
    return $fname;
666
}
667
 
668
#-------------------------------------------------------------------------------
669
# Function        : StripDir
670
#
671
# Description     : Strip directory (returns file, including extension)
672
#
673
# Inputs          : $fname          - Path to process
674
#
675
# Returns         : filename + extension
676
#
677
sub StripDir
678
{
679
    my( $fname ) = @_;                          # Full name
680
    my( $idx );
681
 
682
    if (($idx = rindex($fname, "/")) == -1) {
683
        if (($idx = rindex($fname, "\\")) == -1) {
684
            return $fname;                      # No path ...
685
        }
686
    }
687
    return substr($fname, $idx+1, 512);
688
}
689
 
690
#-------------------------------------------------------------------------------
691
# Function        : StripExt
692
#
693
# Description     : Strip extension (return basename, plus any dir)
694
#
695
# Inputs          : $fname          - Path to process
696
#
697
# Returns         : basename, plus any dir
698
#                   Simply removes one extension
699
#
700
sub StripExt
701
{
702
    my( $fname ) = @_;
703
 
704
    $fname =~ s/(\S+)(\.\S+)/$1/;               # strip out trailing '.<ext>'
705
    return ($fname);
706
}
707
 
708
#-------------------------------------------------------------------------------
709
# Function        : StripFile
710
#
711
# Description     : Strip filename (returns extension)
712
#
713
# Inputs          : $fname          - Path to process
714
#
715
# Returns         : extension
716
#                   Will return an empty string if the input does not have an
717
#                   extension.
718
#
719
sub StripFile
720
{
721
    my( $fname ) = @_;
722
 
723
    $fname =~ s/(\S+)(\.\S+)/$2/;               # Strip out items before '.<ext>'
724
    return ("")                                 # No extension
725
        if ("$fname" eq "@_");
726
    return ($fname);
727
}
728
 
729
#-------------------------------------------------------------------------------
730
# Function        : StripFileExt
731
#
732
# Description     : Strip filename and ext (returns dir)
733
#
734
# Inputs          : $fname          - Path to process
735
#
736
# Returns         : Directory of a file path
737
#
738
 
739
 
740
#   StripFileExt( path ) ---
741
#       Strip filename and ext (returns dir)
742
#..
743
 
744
sub StripFileExt
745
{
746
    my( $fname ) = @_;                          # Full name
747
    my( $idx );
748
    my $dir;
749
 
750
    if (($idx = rindex($fname, "/")) == -1) {
751
        if (($idx = rindex($fname, "\\")) == -1) {
752
            return "";                          # No path ...
753
        }
754
    }
755
 
756
    return substr($fname, 0, $idx);
757
}
758
 
759
#-------------------------------------------------------------------------------
760
# Function        : StripDirExt
761
#
762
# Description     : Strip the directory and extension from a file
763
#                   Returning the base file. Optionally replace the extension
764
#                   with a user value
765
#
766
# Inputs          : Full path name
767
#                   Optional extension to be replaced
768
#
769
# Returns         :
770
#
771
sub StripDirExt
772
{
773
    my ($fname, $ext ) = (@_, '');
774
    $fname =~ s~.*[/\\]~~;                      # Strip directory
775
    $fname =~ s/\.[^.]+$/$ext/;
776
    return $fname;
777
}
778
 
779
 
780
#-------------------------------------------------------------------------------
781
# Function        : CleanDirName
782
#
783
# Description     : Clean up a directory path string
784
#                       1) Remove multiple //
785
#                       2) Remove multiple /./
786
#                       2) Remove leading ./
787
#                       3) Remove trailing /
788
#                       4) Remove /xxxx/../
789
#
790
# Inputs          : A dirty directory path
791
#
792
# Returns         : A clean directory path
793
#
794
sub CleanDirName
795
{
796
    my ( $dir ) = @_;
797
    $dir =~ s~//~/~g;                   # Kill multiple //
798
    $dir =~ s~/\./~/~g;                 # Kill multiple /./
799
    $dir =~ s~^\./~~;                   # Kill leading ./
800
    $dir = '.' unless ( $dir );         # Ensure we have a path
801
 
802
    #
803
    #   Remove /xxxxx/../ bits
804
    #
805
    unless ( $dir =~ m~^\.\./~  )
806
    {
807
        while ( $dir =~ s~
808
                        (^|/)               # Allow for stings that may not start with a /
809
                        [^/]+/\.\.          # xxxxx/.., where xxxx is anything other than a /
810
                        (/|$)               # Allow for strings ending with /..
811
                        ~$1~x               # Replace with the start character
812
              )
813
        {
814
            last if ( $dir =~ m~^\.\./~ );  # Too far. Stop now !
815
        }
816
    }
817
 
818
    $dir =~ s~/$~~;                     # No trailing /
819
    $dir =~ s~/\.$~~;                   # No trailing /.
820
    return $dir;
821
}
822
 
823
#-------------------------------------------------------------------------------
824
# Function        : DisplayPath
825
#
826
# Description     : Cleanup a path for display purposes
827
#                   Useful under windows to provide paths with \ that can be
828
#                   cut and pasted.
829
#
830
#                   If cygwin is located in the environment, then this function
831
#                   will not convert / to \.
832
#
833
# Inputs          : A path to modify
834
#
835
# Returns         : Modified path
836
#
837
sub DisplayPath
838
{
839
    my ($path) = @_;
840
    if ( ! $isUnix && ! $isCygWin )
841
    {
842
        $path =~ s~/~\\~g;
843
    }
844
    return $path;
845
}
846
 
847
1;
848
 
849