Subversion Repositories DevTools

Rev

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