Subversion Repositories DevTools

Rev

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

Rev Author Line No. Line
407 dpurdie 1
########################################################################
3921 dpurdie 2
# Copyright (C) 1998-2013 Vix Technology, All rights reserved
407 dpurdie 3
#
3921 dpurdie 4
# Module name   : DebianPackager.pl
407 dpurdie 5
# Module type   : Makefile system
3921 dpurdie 6
# Compiler(s)   : Perl
407 dpurdie 7
# Environment(s): jats
8
#
9
# Description   : This program is invoked by the MakeDebianPackage
10
#                 directive, that is a part of this package
11
#
12
#                 The program will use a user-provided script in order
13
#                 to create a Debian Package.
14
#
15
#                 The user script may call a number of directives in order to
16
#                 construct an image of the package being installed.
17
#
18
#                 The script specifies Debian configuration scaripts that
19
#                 will be embedded in the package.
20
#
21
#                 This program will:
22
#                   Construct a filesystem image under control of the directives
23
#                   within the user script
24
#
25
#                   Massage the Debian control file
26
#
27
#                   Create a Debian Package
28
#
29
#                   Transfer it to the users 'BIN' directory, where it is
30
#                   available to be packaged.
31
#
32
#                 Summary of directives available to the user-script:
33
#                       AddInitScript           - Add an init script
34
#                       CatFile                 - Append to a file
4641 dpurdie 35
#                       ConvertFile             - Convert file(s) to Unix or Dos Text
407 dpurdie 36
#                       CopyDir                 - Copy directory tree
37
#                       CopyFile                - Copy a file
38
#                       CopyBinFile             - Copy an executable file
39
#                       CopyLibFile             - Copy a library file
40
#                       CreateDir               - Create a directory
41
#                       DebianFiles             - Specify control and script files
4636 dpurdie 42
#                       DebianControlFile       - Specify control and script files
43
#                       DebianDepends           - Add Depends entry to control file
407 dpurdie 44
#                       EchoFile                - Place text into a file
45
#                       MakeSymLink             - Create a symbolic link
46
#                       PackageDescription      - Specify the package description
4641 dpurdie 47
#                       ReplaceTags             - Replace Tags on target file
407 dpurdie 48
#                       SetFilePerms            - Set file permissions
49
#                       SetVerbose              - Control progress display
50
#                       IsProduct               - Flow control
51
#                       IsPlatform              - Flow control
52
#                       IsTarget                - Flow control
427 dpurdie 53
#                       IsVariant               - Flow control
407 dpurdie 54
#
55
#                 Thoughts for expansion:
56
#                       SrcDir                  - Extend path for resolving local files
57
#
58
#                   Less used:
59
#                        ExpandLinkFiles        - Expand .LINK files
60
#
61
#                   Internal Use:
62
#                        FindFiles              - Find a file
63
#                        ResolveFile            - Resolve a 'local' source file
4641 dpurdie 64
#                        chmodItem              - Set file or directory permissions
407 dpurdie 65
#                        
66
#......................................................................#
67
 
411 dpurdie 68
require 5.006_001;
407 dpurdie 69
use strict;
70
use warnings;
71
 
72
use Getopt::Long;
73
use File::Path;
74
use File::Copy;
75
use File::Find;
76
use JatsSystem;
77
use FileUtils;
78
use JatsError;
4636 dpurdie 79
use JatsLocateFiles;
407 dpurdie 80
use ReadBuildConfig;
423 dpurdie 81
use JatsCopy ();                            # Don't import anything
407 dpurdie 82
 
83
#
84
#   Globals
85
#
425 dpurdie 86
my $DebianWorkDirBase;                      # Workspace
407 dpurdie 87
my $DebianWorkDir;                          # Dir to create file system image within
88
 
89
#
90
#   Command line options
91
#
92
my $opt_debug   = $ENV{'GBE_DEBUG'};        # Allow global debug
93
my $opt_verbose = $ENV{'GBE_VERBOSE'};      # Allow global verbose
94
my $opt_vargs;                              # Verbose arg
95
my $opt_help = 0;
96
my $opt_manual = 0;
97
my $opt_clean = 0;
98
my $opt_platform;
99
my $opt_type;
100
my $opt_buildname;
101
my $opt_buildversion;
102
my $opt_interfacedir;
103
my $opt_target;
104
my $opt_product;
105
my $opt_package_script;
106
my $opt_interfaceincdir;
107
my $opt_interfacelibdir;
108
my $opt_interfacebindir;
109
my $opt_libdir;
110
my $opt_bindir;
111
my $opt_localincdir;
112
my $opt_locallibdir;
113
my $opt_localbindir;
114
my $opt_pkgdir;
115
my $opt_pkglibdir;
116
my $opt_pkgbindir;
117
my $opt_pkgpkgdir;
118
my $opt_output;
417 dpurdie 119
my $opt_name;
427 dpurdie 120
my $opt_variant;
3921 dpurdie 121
my $opt_pkgarch;
407 dpurdie 122
 
123
#
124
#   Options derived from script directives
125
#
126
my $opt_description;
127
 
415 dpurdie 128
#
129
#   Globals
130
#
131
my @ResolveFileList;                    # Cached Package File List
132
my @ResolveBinFileList;                 # Cached PackageBin File List
133
my @ResolveLibFileList;                 # Cached PackageLib File List
4635 dpurdie 134
my %DebianControlFiles;                 # Control Files
135
my %DebianControlFileNames;             # Control Files by name
136
my @DependencyList;                     # Package Dependencies
4666 dpurdie 137
my @ConfigList;                         # Config Files
407 dpurdie 138
 
139
#-------------------------------------------------------------------------------
140
# Function        : Main Entry point
141
#
142
# Description     : This function will be called when the package is initialised
143
#                   Extract arguments from the users environment
144
#
145
#                   Done here to greatly simplify the user script
146
#                   There should be no junk in the user script - keep it simple
147
#
148
# Inputs          :
149
#
150
# Returns         : 
151
#
152
main();
153
sub main
154
{
155
    my $result = GetOptions (
156
                "verbose:s"         => \$opt_vargs,
157
                "clean"             => \$opt_clean,
158
                "Type=s"            => \$opt_type,
4105 dpurdie 159
                "BuildName=s"       => \$opt_buildname,                     # Raw Jats Package Name (Do not use)
160
                "Name=s"            => \$opt_name,                          # Massaged Debian Package Name
407 dpurdie 161
                "BuildVersion=s"    => \$opt_buildversion,
162
                "Platform=s"        => \$opt_platform,
163
                "Target=s"          => \$opt_target,
164
                "Product=s"         => \$opt_product,
165
                "DebianPackage=s"   => \$opt_package_script,
166
                "InterfaceDir=s"    => \$opt_interfacedir,
167
                "InterfaceIncDir=s" => \$opt_interfaceincdir,
168
                "InterfaceLibDir=s" => \$opt_interfacelibdir,
169
                "InterfaceBinDir=s" => \$opt_interfacebindir,
170
                "LibDir=s"          => \$opt_libdir,
171
                "BinDir=s"          => \$opt_bindir,
172
                "LocalIncDir=s"     => \$opt_localincdir,
173
                "LocalLibDir=s"     => \$opt_locallibdir,
174
                "LocalBinDir=s"     => \$opt_localbindir,
175
                "PackageDir=s"      => \$opt_pkgdir,
176
                "PackageLibDir=s"   => \$opt_pkglibdir,
177
                "PackageBinDir=s"   => \$opt_pkgbindir,
178
                "PackagePkgDir=s"   => \$opt_pkgpkgdir,
179
                "Output=s"          => \$opt_output,
427 dpurdie 180
                "Variant:s"         => \$opt_variant,
3921 dpurdie 181
                "PkgArch:s"         => \$opt_pkgarch,
407 dpurdie 182
    );
183
    $opt_verbose++ unless ( $opt_vargs eq '@' );
184
 
185
    ErrorConfig( 'name'    => 'DebianUtils',
186
                 'verbose' => $opt_verbose,
187
                 'debug'   => $opt_debug );
188
 
189
    #
190
    #   Init the FileSystem Uiltity interface
191
    #
192
    InitFileUtils();
193
 
194
    #
195
    #   Ensure that we have all required options
196
    #
197
    Error ("Platform not set")                  unless ( $opt_platform );
198
    Error ("Type not set")                      unless ( $opt_type );
199
    Error ("BuildName not set")                 unless ( $opt_buildname );
4105 dpurdie 200
    Error ("Debian Package Name not set")       unless ( $opt_name );
407 dpurdie 201
    Error ("BuildVersion not set")              unless ( $opt_buildversion );
202
    Error ("InterfaceDir not set")              unless ( $opt_interfacedir );
203
    Error ("Target not set")                    unless ( $opt_target );
204
    Error ("Product not set")                   unless ( $opt_product );
205
    Error ("DebianPackage not set")             unless ( $opt_package_script );
206
    Error ("Ouput File not set")                unless ( $opt_output );
207
 
208
    #
209
    #   Read in relevent config information
210
    #
211
    ReadBuildConfig ($opt_interfacedir, $opt_platform, '--NoTest' );
212
 
213
    #
214
    #   Build the package image in a directory based on the target being created
215
    #
425 dpurdie 216
    $DebianWorkDirBase = "$opt_platform$opt_type.image";
217
    $DebianWorkDir = "$DebianWorkDirBase/$opt_name";
407 dpurdie 218
 
219
    #
220
    #   Configure the System command to fail on any error
221
    #
222
    SystemConfig ( ExitOnError => 1 );
223
 
224
    #
225
    #   Extract the 'name' of the package from the output path
226
    #   Display purposes only
227
    #
228
    my $DebianPkgName = StripDirExt($opt_output);
229
 
230
    #
231
    #   Display variables used
232
    #
233
    Message    "=Building Debian Package =============================================";
417 dpurdie 234
    Message    "Build $opt_name";
407 dpurdie 235
    Message    "       Package: $opt_buildname";
427 dpurdie 236
    Message    "       Variant: $opt_variant" if ($opt_variant);
407 dpurdie 237
    Message    "       Version: $opt_buildversion";
238
    Message    "  Building for: $opt_platform, $opt_target";
239
    Message    "       Product: $opt_product";
240
    Message    "          Type: $opt_type";
3921 dpurdie 241
    Message    "      Pkg Arch: $opt_pkgarch" if ($opt_pkgarch);
407 dpurdie 242
    Verbose    "       Verbose: $opt_verbose";
243
    Verbose    "  InterfaceDir: $opt_interfacedir";
244
    Message    "       Package: $DebianPkgName";
245
    Message    "======================================================================";
246
 
247
    #
3921 dpurdie 248
    #   Defaults
249
    #
250
    $opt_pkgarch = $opt_platform unless ( $opt_pkgarch );
251
 
252
    #
407 dpurdie 253
    #   Perform Clean up
254
    #   Invoked during "make clean" or "make clobber"
255
    #
256
    if ( $opt_clean )
257
    {
258
        Message ("Remove packaging directory: $DebianWorkDir");
425 dpurdie 259
 
260
        #
261
        #   Remove the directory for this package
262
        #   Remove the general work dir - if all packages have been cleaned
263
        #
407 dpurdie 264
        rmtree( $DebianWorkDir );
425 dpurdie 265
        rmdir( $DebianWorkDirBase );
407 dpurdie 266
        rmtree ($opt_output) if ( -f $opt_output );
267
        exit;
268
    }
269
 
270
    #
271
    #   Clean  out the WORK directory
272
    #   Always start with a clean slate
273
    #
274
    #   Ensure that the base of the directory tree does not have 'setgid'
275
    #       This will upset the debian packager
276
    #       This may be an artifact from the users directory and not expected
277
    #
278
    rmtree( $DebianWorkDir );
279
    mkpath( $DebianWorkDir );
280
 
281
    my $perm = (stat $DebianWorkDir)[2] & 0777;
282
    chmod ( $perm & 0777, $DebianWorkDir );
283
 
284
    #
285
    #   Invoke the user script to do the hard work
286
    #
4139 dpurdie 287
    unless (my $return = do $opt_package_script) {
288
            Error ("Couldn't parse $opt_package_script: $@") if $@;
289
            Error ("Couldn't do $opt_package_script: $!")    unless defined $return;
290
        }
407 dpurdie 291
 
292
    #
293
    #   Complete the building of the package
294
    #
295
    BuildDebianPackage ();
296
    Message ("Created Debian Package");
297
}
298
 
299
#-------------------------------------------------------------------------------
300
# Function        : BuildDebianPackage
301
#
302
# Description     : This function will create the Debian Package
303
#                   and transfer it to the target directory
304
#
305
# Inputs          : None
306
#
307
# Returns         : Nothing
308
#
309
sub BuildDebianPackage
310
{
311
    Error ("BuildDebianPackage: No Control File or Package Description")
4635 dpurdie 312
        unless ( exists($DebianControlFiles{'control'}) || $opt_description );
407 dpurdie 313
 
314
    #
315
    #   Convert the FileSystem Image into a Debian Package
316
    #       Insert Debian control files
317
    #
318
    Verbose ("Copy in the Debian Control Files");
319
    mkdir ( "$DebianWorkDir/DEBIAN" );
320
 
4635 dpurdie 321
    #
322
    #   Copy in all the named Debian Control files
323
    #       Ignore any control file. It will be done next
324
    #
325
    foreach my $key ( keys %DebianControlFiles )
326
    {
327
        next if ($key eq 'control');
4676 dpurdie 328
        CopyFile ( $DebianControlFiles{$key}, '/DEBIAN', $key  );
4635 dpurdie 329
    }
4666 dpurdie 330
 
331
    #
332
    #   Create 'conffiles'
333
    #       Append to any user provided file
334
    if ( @ConfigList )
335
    {
336
        my $conffiles = "$DebianWorkDir/DEBIAN/conffiles";
337
        Warning("Appending user specified entries to conffiles") if ( -f $conffiles);
338
        FileAppend( $conffiles, @ConfigList );
339
    }
4635 dpurdie 340
 
341
    #
342
    #   Massage the 'control' file
343
    #
344
    UpdateControlFile ($DebianControlFiles{'control'} );
407 dpurdie 345
 
4635 dpurdie 346
    #
347
    #   Mark all files in the debian folder as read-execute
348
    #
407 dpurdie 349
    System ( 'chmod', '-R', 'a+rx', "$DebianWorkDir/DEBIAN" );
350
    System ( 'build_dpkg.sh', '-b', $DebianWorkDir);
351
    System ( 'mv', '-f', "$DebianWorkDir.deb", $opt_output );
352
 
353
    System ("build_dpkg.sh", '-I', $opt_output) if (IsVerbose(1));
354
 
355
}
356
 
357
#-------------------------------------------------------------------------------
358
# Function        : UpdateControlFile
359
#
4188 dpurdie 360
# Description     : Update the Debian 'control' file to fix up various fields
407 dpurdie 361
#                   within the file.
362
#
363
#                   If the files has not been specified, then a basic control
364
#                   file will be provided.
365
#
366
#                   This routine knows where the control file will be placed
367
#                   within the output work space.
368
#
369
# Inputs          : $src            - Path to source file
370
#                   Uses global variables
371
#
372
# Returns         : Nothing
373
#
374
sub UpdateControlFile
375
{
376
    my($src) = @_;
377
    my $dst = "$DebianWorkDir/DEBIAN/control";
378
 
379
    unless ( $src )
380
    {
381
        CreateControlFile();
382
        return;
383
    }
384
 
4635 dpurdie 385
    #
386
    #   User has provided a control file
387
    #       Tweak the internals
388
    #
407 dpurdie 389
    Verbose ("UpdateControlFile: $dst" );
390
    $src = ResolveFile( 0, $src );
391
 
4635 dpurdie 392
    #   Calc depends line
4636 dpurdie 393
    my $depData = join (', ', @DependencyList );
4635 dpurdie 394
 
395
    open (SF, '<', $src) || Error ("UpdateControlFile: Cannot open:$src, $!");
396
    open (DF, '>', $dst) || Error ("UpdateControlFile: Cannot create:$dst, $!");
407 dpurdie 397
    while ( <SF> )
398
    {
399
        s~\s*$~~;
400
        if ( m~^Package:~ ) {
4105 dpurdie 401
            $_ = "Package: $opt_name";
407 dpurdie 402
 
403
        } elsif ( m~^Version:~ ) {
404
            $_ = "Version: $opt_buildversion";
405
 
406
        } elsif ( m~^Architecture:~ ) {
3921 dpurdie 407
            $_ = "Architecture: $opt_pkgarch";
407 dpurdie 408
 
409
        } elsif ( $opt_description && m~^Description:~ ) {
410
            $_ = "Description: $opt_description";
4635 dpurdie 411
 
412
        } elsif ( m~^Depends:~ ) {
413
            $_ = "Depends: $depData";
414
            $depData = '';
407 dpurdie 415
        }
416
        print DF $_ , "\n";
417
    }
4635 dpurdie 418
 
407 dpurdie 419
    close (SF);
420
    close (DF);
4635 dpurdie 421
 
422
    #
423
    #   Warn if Depends section is needed
424
    #
425
    Error ("No Depends section seen in user control file") 
426
        if ($depData);
407 dpurdie 427
}
428
 
429
#-------------------------------------------------------------------------------
430
# Function        : CreateControlFile
431
#
432
# Description     : Craete a basic debian control file
433
#
434
# Inputs          : Uses global variables
435
#
436
# Returns         : 
437
#
438
sub CreateControlFile
439
{
440
    my $dst = "$DebianWorkDir/DEBIAN/control";
441
 
442
    Verbose ("CreateControlFile: $dst" );
443
 
4636 dpurdie 444
    my $depData = join (', ', @DependencyList );
4635 dpurdie 445
 
407 dpurdie 446
    open (DF, '>', $dst) || Error ("CreateControlFile: Cannot create:$dst");
4105 dpurdie 447
    print DF "Package: $opt_name\n";
407 dpurdie 448
    print DF "Version: $opt_buildversion\n";
449
    print DF "Section: main\n";
450
    print DF "Priority: standard\n";
3921 dpurdie 451
    print DF "Architecture: $opt_pkgarch\n";
452
    print DF "Essential: No\n";
453
    print DF "Maintainer: Vix Technology\n";
407 dpurdie 454
    print DF "Description: $opt_description\n";
4635 dpurdie 455
    print DF "Depends: $depData\n" if ($depData);
456
 
407 dpurdie 457
    close (DF);
458
}
459
 
460
#-------------------------------------------------------------------------------
461
# Function        : SetVerbose
462
#
463
# Description     : Set the level of verbosity
464
#                   Display activity
465
#
466
# Inputs          : Verbosity level
467
#                       0 - Use makefile verbosity (Default)
468
#                       1..2
469
#
470
# Returns         : 
471
#
472
sub SetVerbose
473
{
474
    my ($level) = @_;
475
 
476
    $level = $opt_verbose unless ( $level );
477
    $opt_verbose = $level;
478
    ErrorConfig( 'verbose' => $level);
479
}
480
 
481
 
482
#-------------------------------------------------------------------------------
483
# Function        : DebianFiles
484
#
485
# Description     : Name Debian builder control files
486
#                   May be called multiple times
487
#
488
# Inputs          : Options
489
#                       --Control=file
490
#                       --PreRm=file
491
#                       --PostRm=file
492
#                       --PreInst=file
493
#                       --PostInst=file
4635 dpurdie 494
#                         
407 dpurdie 495
#
496
# Returns         : Nothing
497
#
498
sub DebianFiles
499
{
500
    #
4635 dpurdie 501
    #   Extract names
407 dpurdie 502
    #
503
    Verbose ("Specify Debian Control Files and Scripts");
504
    foreach  ( @_ )
505
    {
4635 dpurdie 506
        if ( m/^--Control=(.+)/i ) {
507
            DebianControlFile('control',$1)
407 dpurdie 508
 
4635 dpurdie 509
        } elsif ( m/^--PreRm=(.+)/i ) {
510
            DebianControlFile('prerm',$1)
407 dpurdie 511
 
4635 dpurdie 512
        } elsif ( m/^--PostRm=(.+)/i ) {
513
            DebianControlFile('postrm',$1)
407 dpurdie 514
 
4635 dpurdie 515
        } elsif ( m/^--PreInst=(.+)/i ) {
516
            DebianControlFile('preinst',$1)
407 dpurdie 517
 
4635 dpurdie 518
        } elsif ( m/^--PostInst=(.+)/i ) {
519
            DebianControlFile('postinst',$1)
407 dpurdie 520
 
521
        } else {
522
            Error ("DebianFiles: Unknown option: $_");
523
        }
524
    }
525
}
526
 
527
#-------------------------------------------------------------------------------
4635 dpurdie 528
# Function        : DebianControlFile 
529
#
530
# Description     : Add special control files to the Debian Installer 
531
#                   Not useful for embedded installers
532
#
533
#                   More general than DebianFiles()
534
#
535
# Inputs          : name            - Target Name
536
#                                     If the name starts with 'package.' then it will be replaced
537
#                                     with the name of the current package
538
#                   file            - Source File Name
4676 dpurdie 539
#                   options         - Options include
540
#                                       --FromPackage
4635 dpurdie 541
#
542
# Returns         : 
543
#
544
sub DebianControlFile
545
{
4676 dpurdie 546
    my ($name, $file, @options) = @_;
547
    my $fromPackage = 0;
4635 dpurdie 548
 
549
    #
4676 dpurdie 550
    #   Process options
551
    foreach ( @options)
552
    {
553
        if (m~^--FromPackage~) {
554
            $fromPackage = 1;
555
        }
556
        else  {
557
            ReportError(("DebianControlFile: Unknown argument: $_"));
558
        }
559
    }
560
    ErrorDoExit();
561
 
562
    #
4635 dpurdie 563
    #   Some control files need to have the package name prepended
564
    #
565
    $name =~ s~^package\.~$opt_name.~;
566
 
567
    #
568
    #   Only allow one file of each type
569
    #       Try to protect the user by testing for names by lowercase
570
    #
571
    my $simpleName = lc($name);
572
    Error("DebianControlFile: Multiple definitions for '$name' not allowed")
573
        if (exists $DebianControlFileNames{$simpleName});
574
 
4676 dpurdie 575
    my $filePath = ResolveFile($fromPackage, $file);
4635 dpurdie 576
 
577
    #
578
    #   Add info to data structures
579
    #
4676 dpurdie 580
    $DebianControlFiles{$name} = $filePath;
4635 dpurdie 581
    $DebianControlFileNames{$simpleName} = $name;
582
}
583
 
584
#-------------------------------------------------------------------------------
585
# Function        : DebianDepends 
586
#
587
# Description     : This directive allows simple dependency information to be  
588
#                   inserted into the control file
589
#
4636 dpurdie 590
#                   Not useful in embedded system
4635 dpurdie 591
#
592
# Inputs          : Entry             - A dependency entry
593
#                   ...               - More entries
594
#                   
595
#
596
# Returns         : Nothing
597
#
598
sub DebianDepends
599
{
600
    push @DependencyList, @_;
601
}
602
 
603
 
604
#-------------------------------------------------------------------------------
407 dpurdie 605
# Function        : PackageDescription
606
#
607
# Description     : Specify the Package Description
608
#                   Keep it short
609
#
610
# Inputs          : $description
611
#
612
# Returns         : 
613
#
614
sub PackageDescription
615
{
616
    ($opt_description) = @_;
617
}
618
 
619
#-------------------------------------------------------------------------------
620
# Function        : MakeSymLink
621
#
622
# Description     : Create a symlink - with error detection
623
#
624
# Inputs          : old_file    - Link Target
625
#                                 Path to the link target
626
#                                 If an ABS path is provided, the routine will
627
#                                 attempt to create a relative link.
628
#                   new_file    - Relative to the output work space
629
#                                 Path to where the 'link' file will be created
630
#                   Options     - Must be last
631
#                                 --NoClean         - Don't play with links
632
#                                 --NoDotDot        - Don't create symlinks with ..
633
#
634
# Returns         : Nothing
635
#
636
sub MakeSymLink
637
{
638
    my $no_clean;
639
    my $no_dot;
640
    my @args;
641
 
642
    #
643
    #   Extract options
644
    #
645
    foreach ( @_ )
646
    {
647
        if ( m/^--NoClean/i ) {
648
            $no_clean = 1;
649
 
650
        } elsif ( m/^--NoDotDot/i ) {
651
            $no_dot = 1;
652
 
653
        } elsif ( m/^--/ ) {
654
            Error ("MakeSymLink: Unknown option: $_");
655
 
656
        } else {
657
            push @args, $_;
658
        }
659
    }
660
 
661
    my ($old_file, $new_file) = @args;
662
 
663
    my $tfile = $DebianWorkDir . '/' . $new_file;
664
    $tfile =~ s~//~/~;
665
    Verbose ("Symlink $old_file -> $new_file" );
666
 
667
    #
668
    #   Create the directory in which the link will be placed
669
    #   Remove any existing file of the same name
670
    #
671
    my $dir = StripFileExt( $tfile );
672
    mkpath( $dir) unless -d $dir;
673
    unlink $tfile;
674
 
675
    #
676
    #   Determine a good name of the link
677
    #   Convert to a relative link in an attempt to prune them
678
    #
679
    my $sfile = $old_file;
680
    unless ( $no_clean )
681
    {
682
        $sfile = CalcRelPath( StripFileExt( $new_file ), $old_file );
683
        $sfile = $old_file if ( $no_dot && $sfile =~ m~^../~ );
684
    }
685
 
686
    my $result = symlink $sfile, $tfile;
687
    Error ("Cannot create symlink. $old_file -> $new_file") unless ( $result );
688
}
689
 
690
#-------------------------------------------------------------------------------
691
# Function        : CopyFile
692
#
693
# Description     : Copy a file to a target dir
694
#                   Used for text files, or files with fixed names
695
#
696
# Inputs          : $src
697
#                   $dst_dir    - Within the output workspace
698
#                   $dst_name   - Output Name [Optional]
699
#                   Options     - Common Copy Options
700
#
701
# Returns         : Full path to destination file
702
#
703
sub CopyFile
704
{
705
    CopyFileCommon( \&ResolveFile, @_ );
706
}
707
 
708
#-------------------------------------------------------------------------------
709
# Function        : CopyBinFile
710
#
711
# Description     : Copy a file to a target dir
712
#                   Used for executable programs. Will look in places where
713
#                   programs are stored.
714
#
715
# Inputs          : $src
716
#                   $dst_dir    - Within the output workspace
717
#                   $dst_name   - Output Name [Optional]
718
#
719
#                   Options:
720
#                       --FromPackage
721
#                       --SoftLink=xxxx
722
#                       --LinkFile=xxxx
723
#
724
#
725
# Returns         : Full path to destination file
726
#
727
sub CopyBinFile
728
{
729
    CopyFileCommon( \&ResolveBinFile, @_ );
730
}
731
 
732
#-------------------------------------------------------------------------------
733
# Function        : CopyLibFile
734
#
735
# Description     : Copy a file to a target dir
736
#                   Used for shared programs. Will look in places where
737
#                   shared libraries are stored.
738
#
739
# Inputs          : $src        - Base for 'realname' (no lib, no extension)
740
#                   $dst_dir    - Within the output workspace
741
#                   $dst_name   - Output Name [Optional, but not suggested]
742
#
743
# Returns         : Full path to destination file
744
#
745
# Notes           : Copying 'lib' files
746
#                   These are 'shared libaries. There is no provision for copying
747
#                   static libraries.
748
#
749
#                   The tool will attempt to copy a well-formed 'realname' library
750
#                   The soname of the library should be constructed on the target
751
#                   platform using ldconfig.
752
#                   There is no provision to copy the 'linker' name
753
#
754
#                   Given a request to copy a library called 'fred', then the
755
#                   well formed 'realname' will be:
756
#                           libfred[P|D|]].so.nnnnn
757
#                   where:
758
#                           nnnn is the library version
759
#                           [P|D|] indicates Production, Debug or None
760
#
761
#                   The 'soname' is held within the realname form of the library
762
#                   and will be created by lsconfig.
763
#
764
#                   The 'linkername' would be libfred[P|D|].so. This is only
765
#                   needed when linking against the library.
766
#
767
#
768
#                   The routine will also recognize Windows DLLs
769
#                   These are of the form fred[P|D|].nnnnn.dll
770
#
771
sub CopyLibFile
772
{
773
    CopyFileCommon( \&ResolveLibFile, @_ );
774
}
775
 
776
#-------------------------------------------------------------------------------
777
# Function        : CopyFileCommon
778
#
779
# Description     : Common ( internal File Copy )
780
#
781
# Inputs          : $resolver           - Ref to function to resolve source file
782
#                   $src                - Source File Name
783
#                   $dst_dir            - Target Dir
784
#                   $dst_name           - Target Name (optional)
785
#                   Options
786
#                   Options:
787
#                       --FromPackage
788
#                       --SoftLink=xxxx
789
#                       --LinkFile=xxxx
4666 dpurdie 790
#                       --ConfigFile
407 dpurdie 791
#
792
# Returns         : 
793
#
794
sub CopyFileCommon
795
{
796
    my $from_package = 0;
797
    my $isa_linkfile = 0;
4666 dpurdie 798
    my $isa_configFile = 0;
407 dpurdie 799
    my @llist;
800
    my @args;
801
 
802
    #
803
    #   Parse options
804
    #
805
    foreach ( @_ )
806
    {
807
        if ( m/^--FromPackage/ ) {
808
            $from_package = 1;
809
 
810
        } elsif ( m/^--LinkFile/ ) {
811
            $isa_linkfile = 1;
812
 
4666 dpurdie 813
        } elsif ( m/^--ConfFile/i ) {
814
            $isa_configFile = 1;
815
 
407 dpurdie 816
        } elsif ( m/^--SoftLink=(.+)/ ) {
817
            push @llist, $1;
818
 
819
        } elsif ( m/^--/ ) {
820
            Error ("FileCopy: Unknown option: $_");
821
 
822
        } else {
823
            push @args, $_;
824
        }
825
    }
826
 
827
    #
828
    #   Extract non-options.
829
    #   These are the bits that are left over
830
    #
831
    my ($resolver, $src, $dst_dir, $dst_name ) = @args;
832
 
833
    #
834
    #   Clean up dest_dir. Must start with a / and not end with one
835
    #
836
    $dst_dir = "/$dst_dir/";
837
    $dst_dir =~ s~/+~/~g;
838
    $dst_dir =~ s~/$~~;
839
 
840
    Verbose ("CopyFile: $src, $dst_dir, " . ($dst_name || ''));
841
    foreach $src ( &$resolver( $from_package, $src ) )
842
    {
843
        my $dst_fname = $dst_name ? $dst_name : StripDir($src);
844
        my $dst_file = "$dst_dir/$dst_fname";
845
        Verbose ("CopyFile: Copy $src, $dst_file" );
846
 
847
 
848
        #
849
        #   LinkFiles are special
850
        #   They get concatenated to any existing LINKS File
851
        #
852
        if ( $isa_linkfile )
853
        {
854
            CatFile ( $src, "$dst_dir/.LINKS" );
855
        }
856
        else
857
        {
858
            mkpath( "$DebianWorkDir$dst_dir", 0, 0775);
859
            unlink ("$DebianWorkDir$dst_file");
860
            System ('cp','-f', $src, "$DebianWorkDir$dst_file" );
861
 
862
            foreach my $lname ( @llist )
863
            {
864
                $lname = $dst_dir . '/' . $lname unless ( $lname =~ m ~^/~ );
865
                MakeSymLink( $dst_file ,$lname);
866
            }
867
        }
4666 dpurdie 868
 
869
        #
870
        #   ConfigFiles are marked so that they can be handled by the debain installer
871
        #
872
        if ($isa_configFile)
873
        {
874
            push @ConfigList, $dst_file;
875
        }
407 dpurdie 876
    }
877
}
878
 
879
#-------------------------------------------------------------------------------
880
# Function        : CopyDir
881
#
882
# Description     : Copy a directory to a target dir
883
#
884
# Inputs          : $src_dir    - Local to the user
885
#                                 Symbolic Name
886
#                   $dst_dir    - Within the output workspace
887
#                   Options
4714 dpurdie 888
#                       --Merge                 - Don't delete first
889
#                       --Source=Name           - Source via Symbolic Name
890
#                       --FromPackage           - Source via package roots
891
#                       --NoIgnoreDbgFiles      - Do not ignore .dbg and .debug files in dir copy
892
#                       --IfPresent             - Not an error if the path cannot be found
893
#                       --ConfFile              - Mark transferred files as config files
894
#                       --Flatten               - Copy all to one directory
895
#                       --FilterOut=xxx         - Ignore files. DOS Wildcard
896
#                       --FilterOutRe=xxx       - Ignore files. Regular expression name
897
#                       --FilterOutDir=xxx      - Ignore directories. DOS Wilcard
898
#                       --FilterOutDirRe=xxx    - Ignore directories. Regular expression name
899
#                       --SkipTLF               - Ignore files in the Top Level Directory
900
#                       --NoRecurse             - Only process files in the Top Level Directory
901
#                       --FilterIn=xxx          - Include files. DOS Wildcard
902
#                       --FilterInRe=xxx        - Include files. Regular expression name
903
#                       --FilterInDir=xxx       - Include directories. DOS Wilcard
904
#                       --FilterInDirRe=xxx     - Include directories. Regular expression name
407 dpurdie 905
#
906
# Returns         :
907
#
908
sub CopyDir
909
{
910
    my ($src_dir, $dst_dir, @opts) = @_;
911
    my $opt_base;
411 dpurdie 912
    my $from_interface = 0;
4152 dpurdie 913
    my $ignoreDbg = 1;
914
    my $ignoreNoDir;
915
    my $user_src_dir = $src_dir;
916
    my $opt_source;
917
    my $opt_package;
4714 dpurdie 918
    my @fileList;
919
    my $isFiltered;
407 dpurdie 920
 
4714 dpurdie 921
    #
922
    #   Setup the basic copy options
923
    #       May be altered as we parse user options
924
    #
925
    my %copyOpts;
926
    $copyOpts{'IgnoreDirs'} = ['.svn', '.git', '.cvs', '.hg'];
927
    $copyOpts{'Ignore'} = ['.gbedir', '_gbedir'];
928
    $copyOpts{'Log'} = 1 if ( $opt_verbose > 1 );
929
 
407 dpurdie 930
    $dst_dir = $DebianWorkDir . '/' . $dst_dir;
931
    $dst_dir =~ s~//~/~;
932
 
933
    #
4152 dpurdie 934
    #   Scan and collect user options
407 dpurdie 935
    #
936
    foreach  ( @opts )
937
    {
4152 dpurdie 938
        Verbose2 ("CopyDir: $_");
407 dpurdie 939
        if ( m/^--Merge/ ) {
4714 dpurdie 940
            $copyOpts{'DeleteFirst'} = 1;
4152 dpurdie 941
 
407 dpurdie 942
        } elsif ( m/^--Source=(.+)/ ) {
425 dpurdie 943
            Error ("Source directory can only be specified once")
4152 dpurdie 944
                if ( defined $opt_source );
945
            $opt_source = $1;
425 dpurdie 946
 
4152 dpurdie 947
        } elsif ( m/^--FromPackage/ ) {
948
            Error ("FromPackage can only be specified once")
949
                if ( defined $opt_package );
950
            $opt_package = 1;
951
 
952
        } elsif ( m/^--NoIgnoreDbgFiles/ ) {
953
            $ignoreDbg = 0;
954
 
955
        } elsif ( m/^--IfPresent/ ) {
956
            $ignoreNoDir = 1;
407 dpurdie 957
 
4714 dpurdie 958
        } elsif ( m/^--ConfFile/i ) {
959
            $copyOpts{'FileList'} = \@fileList;
960
 
961
        } elsif ( m/^--Flatten/i ) {
962
            $copyOpts{'Flatten'} = 1;
963
 
964
        } elsif ( m/^--FilterOut=(.+)/i ) {
965
            push (@{$copyOpts{'Ignore'}}, $1);
966
            $isFiltered = 1;
967
 
968
        } elsif ( m/^--FilterOutRe=(.+)/i ) {
969
            push (@{$copyOpts{'IgnoreRE'}}, $1);
970
            $isFiltered = 1;
971
 
972
        } elsif ( m/^--FilterOutDir=(.+)/i ) {
973
            push (@{$copyOpts{'IgnoreDirs'}}, $1);
974
            $isFiltered = 1;
975
 
976
        } elsif ( m/^--FilterOutDirRe=(.+)/i ) {
977
            push (@{$copyOpts{'IgnoreDirsRE'}}, $1);
978
            $isFiltered = 1;
979
 
980
        } elsif ( m/^--FilterIn=(.+)/i ) {
981
            push (@{$copyOpts{'Match'}}, $1);
982
            $isFiltered = 1;
983
 
984
        } elsif ( m/^--FilterInRe=(.+)/i ) {
985
            push (@{$copyOpts{'MatchRE'}}, $1);
986
            $isFiltered = 1;
987
 
988
        } elsif ( m/^--FilterInDir=(.+)/i ) {
989
            push (@{$copyOpts{'MatchDirs'}}, $1);
990
            $isFiltered = 1;
991
 
992
        } elsif ( m/^--FilterInDirRe=(.+)/i ) {
993
            push (@{$copyOpts{'MatchDirsRE'}}, $1);
994
            $isFiltered = 1;
995
 
996
        } elsif ( m/^--SkipTLF$/i ) {
997
            $copyOpts{'SkipTLF'} = 1;
998
 
999
        } elsif ( m/^--NoRecurse$/i ) {
1000
            $copyOpts{'NoSubDirs'} = 1;
1001
 
4152 dpurdie 1002
        } else {
1003
            Error ("CopyDir: Unknown option: $_" );
1004
        }
1005
    }
411 dpurdie 1006
 
4152 dpurdie 1007
    #
1008
    #   All options have been gathered. Now process some of them
1009
    #
1010
    Error ("CopyDir: Cannot use both --Source and --FromPackage: $src_dir") if ($opt_source && $opt_package);
425 dpurdie 1011
 
4152 dpurdie 1012
    #
1013
    #   Convert a symbolic path into a physical path
1014
    #
1015
    if ($opt_source)
1016
    {
1017
        Verbose2 ("CopyDir: Determine Source: $opt_source");
425 dpurdie 1018
 
4152 dpurdie 1019
        $opt_source = lc($opt_source);
1020
        my %CopyDirSymbolic = (
1021
            'interfaceincdir'   => $opt_interfaceincdir,
1022
            'interfacelibdir'   => $opt_interfacelibdir,
1023
            'interfacebindir'   => $opt_interfacebindir,
1024
            'libdir'            => $opt_libdir,
1025
            'bindir'            => $opt_bindir,
1026
            'localincdir'       => $opt_localincdir,
1027
            'locallibdir'       => $opt_locallibdir,
1028
            'localbindir'       => $opt_localbindir,
1029
            'packagebindir'     => $opt_pkgbindir,
1030
            'packagelibdir'     => $opt_pkglibdir,
1031
            'packagepkgdir'     => $opt_pkgpkgdir,
1032
            'packagedir'        => $opt_pkgdir,
1033
        );
425 dpurdie 1034
 
4152 dpurdie 1035
        if ( exists $CopyDirSymbolic{$opt_source} )
1036
        {
1037
            $opt_base = $CopyDirSymbolic{$opt_source};
425 dpurdie 1038
 
1039
            #
4152 dpurdie 1040
            #   If sourceing from interface, then follow
1041
            #   symlinks in the copy. All files will be links anyway
425 dpurdie 1042
            #
1043
            $from_interface = 1
4152 dpurdie 1044
                if ( $opt_source =~ m~^interface~ );
1045
        }
1046
        else
1047
        {
1048
            DebugDumpData ("CopyDirSymbolic", \%CopyDirSymbolic);
1049
            Error ("CopyDir: Unknown Source Name: $opt_source" );
1050
        }
1051
    }
425 dpurdie 1052
 
4152 dpurdie 1053
    #
1054
    #   Locate the path within an external package
1055
    #
1056
    if ($opt_package)
1057
    {
1058
        Verbose2 ("CopyDir: FromPackage: $src_dir");
4147 dpurdie 1059
 
4152 dpurdie 1060
        my @path;
1061
        foreach my $entry ( getPackageList() )
1062
        {
1063
            my $base = $entry->getBase(3);
1064
            next unless ( defined $base );
1065
            if ( -d $base . '/' . $src_dir )
1066
            {
1067
                push @path, $base;
1068
                $from_interface = 1
1069
                    if ( $entry->{'TYPE'} eq 'interface' );
1070
            }
407 dpurdie 1071
        }
4152 dpurdie 1072
 
1073
        if ( $#path < 0 )
1074
        {
1075
            Error ("CopyDir: Cannot find source dir in any package: $user_src_dir") unless ($ignoreNoDir);
1076
            Message ("CopyDir: Optional path not found: $user_src_dir");
1077
            return;
1078
        }
1079
 
1080
        Error ("CopyDir: Requested path found in mutiple packages: $user_src_dir",
1081
                @path ) if ( $#path > 0 );
1082
        $opt_base = pop @path;
1083
 
1084
        #
1085
        #   If sourceing from interface, then follow symlinks in the copy.
1086
        #   All files will be links anyway
1087
        #
1088
        #   This is a very ugly test for 'interface'
1089
        #
1090
        $from_interface = 1
1091
            if ( $opt_base =~ m~/interface/~ );
1092
 
407 dpurdie 1093
    }
1094
 
4152 dpurdie 1095
    #
1096
    #   Create the full source path
4714 dpurdie 1097
    #   May be: from a package, from a known directory, from a local directory
4152 dpurdie 1098
    #
1099
 
407 dpurdie 1100
    $src_dir = $opt_base . '/' . $src_dir if ( $opt_base );
1101
    $src_dir =~ s~//~/~g;
1102
    $src_dir =~ s~/$~~;
1103
 
1104
    Verbose ("CopyDir: $src_dir, $dst_dir");
4152 dpurdie 1105
    unless ( -d $src_dir )
1106
    {
1107
        Error ("CopyDir: Directory not found: $user_src_dir") unless ($ignoreNoDir);
1108
        Message ("CopyDir: Optional path not found: $user_src_dir");
1109
        return;
1110
    }
407 dpurdie 1111
 
1112
    #
4714 dpurdie 1113
    #   Continue to configure the copy options
407 dpurdie 1114
    #
4147 dpurdie 1115
    push (@{$copyOpts{'Ignore'}}, '*.debug', '*.dbg') if $ignoreDbg;
423 dpurdie 1116
    $copyOpts{'DuplicateLinks'} = 1 unless ( $from_interface );
4714 dpurdie 1117
    $copyOpts{'EmptyDirs'} = 1 unless ($isFiltered);
407 dpurdie 1118
 
1119
    #
423 dpurdie 1120
    #   Transfer the directory
407 dpurdie 1121
    #
423 dpurdie 1122
    JatsCopy::CopyDir ( $src_dir, $dst_dir, \%copyOpts );
407 dpurdie 1123
 
1124
    #
4714 dpurdie 1125
    #   If requested, mark files as config files
1126
    #   Must remove the DebianWorkDir prefix
1127
    #
1128
    if(@fileList)
1129
    {
1130
        Verbose ("Mark all transfered files as ConfFiles");
1131
        my $removePrefix = length ($DebianWorkDir);
1132
        foreach my $file (@fileList)
1133
        {
1134
            push @ConfigList, substr($file, $removePrefix);
1135
        }
1136
    }
1137
 
1138
    #
407 dpurdie 1139
    #   Expand link files that may have been copied in
1140
    #
1141
    Verbose ("Locate LINKFILES in $DebianWorkDir");
1142
    ExpandLinkFiles();
1143
}
1144
 
1145
#-------------------------------------------------------------------------------
1146
# Function        : AddInitScript
1147
#
1148
# Description     : Add an Init Script to the target
1149
#                   Optionally create start and stop links
1150
#
1151
# Inputs          : $script     - Name of the init script
1152
#                   $start      - Start Number
1153
#                   $stop       - Stop Number
1154
#                   Options:
1155
#                       --NoCopy        - Don't copy the script, just add links
1156
#                       --Afc           - Place in AFC init area
1157
#                       --FromPackage   - Source is in a package
1158
#
1159
# Returns         : 
1160
#
1161
sub AddInitScript
1162
{
1163
    my $no_copy;
1164
    my $basedir = "";
1165
    my @args;
1166
    my $from_package = 0;
1167
 
4302 dpurdie 1168
    # This directive is only available on the VIX platforms
1169
    #   Kludgey test - at the moment
407 dpurdie 1170
    #
4302 dpurdie 1171
    if ($opt_pkgarch =~ m~i386~)
1172
    {
1173
        Error ("AddInitScript is not supported on this platform"); 
1174
    }
1175
 
1176
    #
407 dpurdie 1177
    #   Process and Remove options
1178
    #
1179
    foreach  ( @_ )
1180
    {
1181
        if ( m/^--NoCopy/ ) {
1182
            $no_copy = 1;
1183
 
1184
        } elsif ( m/^--Afc/ ) {
1185
            $basedir = "/afc";
1186
 
1187
        } elsif ( m/^--FromPackage/ ) {
1188
            $from_package = 1;
1189
 
1190
        } elsif ( m/^--/ ) {
1191
            Error ("AddInitScript: Unknown option: $_");
1192
 
1193
        } else {
1194
            push @args, $_;
1195
 
1196
        }
1197
    }
1198
 
1199
    my( $script, $start, $stop ) = @args;
1200
    Error ("No script file specified") unless ( $script );
1201
    Warning("AddInitScript: No start or stop index specified") unless ( $start || $stop );
1202
    Verbose ("AddInitScript: $script, " . ($start || 'No Start') . ", " . ($stop || 'No Stop'));
1203
    $script = ResolveFile($from_package, $script );
1204
 
1205
    my $tdir = $basedir . "/etc/init.d/init.d";
1206
    my $base = StripDir($script);
1207
 
1208
    CopyFile( $script, $tdir ) unless $no_copy;
1209
 
1210
    my $link;
1211
    if ( $start )
1212
    {
1213
        $link = sprintf ("${basedir}/etc/init.d/S%2.2d%s", $start, $base );
1214
        MakeSymLink( "$tdir/$base", $link);
1215
    }
1216
 
1217
    if ( $stop )
1218
    {
1219
        $link = sprintf ("${basedir}/etc/init.d/K%2.2d%s", $stop, $base );
1220
        MakeSymLink( "$tdir/$base", $link);
1221
    }
1222
}
1223
 
1224
#-------------------------------------------------------------------------------
1225
# Function        : CatFile
1226
#
1227
# Description     : Copy a file to the end of a file
1228
#
1229
# Inputs          : $src
1230
#                   $dst    - Within the output workspace
1231
#
1232
# Returns         :
1233
#
1234
sub CatFile
1235
{
1236
    my ($src, $dst) = @_;
1237
 
1238
    $dst = $DebianWorkDir . '/' . $dst;
1239
    $dst =~ s~//~/~;
1240
    Verbose ("CatFile: $src, $dst");
1241
    $src = ResolveFile(0, $src );
1242
 
1243
    open (SF, '<', $src)  || Error ("CatFile: Cannot open $src");
1244
    open (DF, '>>', $dst) || Error ("CatFile: Cannot create:$dst");
1245
    while ( <SF> )
1246
    {
1247
        print DF $_;
1248
    }
1249
    close (SF);
1250
    close (DF);
1251
}
1252
 
1253
#-------------------------------------------------------------------------------
1254
# Function        : EchoFile
1255
#
1256
# Description     : Echo simple text to a file
1257
#
1258
# Inputs          : $file   - Within the output workspace
1259
#                   $text
1260
#
1261
# Returns         : 
1262
#
1263
sub EchoFile
1264
{
1265
    my ($file, $text) = @_;
1266
    Verbose ("EchoFile: $file");
1267
 
1268
    $file = $DebianWorkDir . '/' . $file;
1269
    $file =~ s~//~/~;
1270
 
1271
    unlink $file;
1272
    open (DT, ">", $file ) || Error ("Cannot create $file");
1273
    print DT  $text || Error ("Cannot print to $file");
1274
    close DT;
1275
}
1276
 
1277
#-------------------------------------------------------------------------------
4640 dpurdie 1278
# Function        : ConvertFiles
1279
#
1280
# Description     : This sub-routine is used to remove all carrage return\line
1281
#                   feeds from a line and replace them with the platform
1282
#                   specific equivalent chars.
1283
#
1284
#                   We let PERL determine what characters are written to the
1285
#                   file base on the  platform you are running on.
1286
#
1287
#                   i.e. LF    for unix
1288
#                        CR\LF for win32
1289
#
1290
# Inputs          : outPath                 - Output directory
1291
#                   flist                   - List of files in that directory
1292
#                   or
1293
#                   SearchOptions           - Search options to find files
1294
#                                           --Recurse
1295
#                                           --NoRecurse
1296
#                                           --FilterIn=xxx
1297
#                                           --FilterInRe=xxx
1298
#                                           --FilterOut=xxx
1299
#                                           --FilterOutRe=xxx
1300
#                   Common options
1301
#                                           --Dos
1302
#                                           --Unix
1303
#
1304
#
1305
# Returns         : 1
1306
#
1307
sub ConvertFiles
1308
{
1309
    my @uargs;
1310
    my $lineEnding = "\n";
1311
    my ($dosSet, $unixSet);
1312
    my $search =  JatsLocateFiles->new( '--NoRecurse' );
1313
 
1314
    #
1315
    #   Process user arguments extracting options
1316
    #
1317
    foreach  ( @_ )
1318
    {
1319
        if ( m~^--Recurse~ ) {
1320
            $search->recurse(1);
1321
 
1322
        } elsif ( m~^--NoRecurse~) {
1323
            $search->recurse(0);
1324
 
1325
        } elsif ( /^--FilterOut=(.*)/ ) {
1326
            $search->filter_out($1);
1327
 
1328
        } elsif ( /^--FilterOutRe=(.*)/ ) {
1329
            $search->filter_out_re($1);
1330
 
1331
        } elsif ( /^--FilterIn=(.*)/ ) {
1332
            $search->filter_in($1);
1333
 
1334
        } elsif ( /^--FilterInRe=(.*)/ ) {
1335
            $search->filter_in_re($1);
1336
 
1337
        } elsif ( m~^--Dos~) {
1338
            $lineEnding = "\r\n";
1339
            $dosSet = 1;
1340
 
1341
        } elsif ( m~^--Unix~) {
1342
            $lineEnding = "\n";
1343
            $unixSet = 1;
1344
 
1345
        } elsif ( m~^--~) {
4641 dpurdie 1346
            Error ("ConvertFiles: Unknown option: $_");
4640 dpurdie 1347
 
1348
        } else {
1349
            push @uargs, $_;
1350
        }
1351
    }
1352
 
1353
    #
1354
    #   Process non-option arguments
1355
    #       - Base dir
1356
    #       - List of files
1357
    #
1358
    my ($outPath, @flist) = @uargs;
1359
    Error ("ConvertFiles: Target Dir must be specified" ) unless ( $outPath );
1360
 
1361
    #
1362
    #   Sanity Tests
1363
    #
1364
    Error ("ConvertFiles: --Dos and --Unix are mutually exclusive" ) if ( $dosSet && $unixSet );
1365
 
1366
 
1367
    #
1368
    # Convert output path to physical path
1369
    #
1370
    my $topDir = catdir($DebianWorkDir, $outPath);
1371
    Verbose("ConvertFiles: topDir: $topDir");
1372
    Error ("ConvertFiles: Path does not exist", $topDir) unless ( -e $topDir );
1373
    Error ("ConvertFiles: Path is not a directory", $topDir) unless ( -d $topDir );
1374
 
1375
    #
1376
    #   Need to determine if we are searching or simply using a file list
1377
    #   There are two forms of the functions. If any of the search options have
1378
    #   been used then we assume that we are searchine
1379
    #
1380
    if ( $search->has_filter() )
1381
    {
1382
        Error ("ConvertFiles: Cannot mix search options with named files") if ( @flist );
1383
        @flist = $search->search($topDir);
1384
    }
1385
    Error ("ConvertFiles: No files specified") unless ( @flist );
1386
 
1387
    #
1388
    #   Process all named files
1389
    #
1390
    foreach my $file ( @flist )
1391
    {
1392
 
1393
        # this is our file that we want to clean.
1394
        my ($ifileLoc) = "$topDir/$file";
1395
        my ($tfileLoc) = "$topDir/$file\.tmp";
4641 dpurdie 1396
        Verbose("ConvertFiles: $file");
4640 dpurdie 1397
 
1398
        # we will check to see if the file exists.
1399
        #
1400
        my $ifile;
1401
        my $tfile;
1402
        if ( -f "$ifileLoc" )
1403
        {
1404
            open ($ifile, "< $ifileLoc" ) or
1405
                Error("Failed to open file [$ifileLoc] : $!");
1406
 
1407
            open ($tfile, "> $tfileLoc" ) or
1408
                Error("Failed to open file [$tfileLoc] : $!");
1409
            binmode $tfile;
1410
 
1411
            while ( <$ifile> ) 
1412
            {
1413
                s~[\n\r]+$~~;               # Chomp
1414
                print $tfile "$_" . $lineEnding;
1415
            }
1416
        }
1417
        else
1418
        {
1419
            Error("ConvertFiles [$ifileLoc] does not exist.");
1420
        }
1421
 
1422
        close $ifile;
1423
        close $tfile;
1424
 
1425
 
1426
        # lets replace our original file with the new one
1427
        #
1428
        if(File::Copy::move("$tfileLoc", "$ifileLoc"))
1429
        {
1430
            Verbose2("ConvertFiles: Renamed [$tfileLoc] to [$ifileLoc] ...");
1431
        }
1432
        else
1433
        {
1434
            Error("ConvertFiles: Failed to rename file [$tfileLoc] to [$ifileLoc]: $!");
1435
        }
1436
    }
1437
 
1438
    return 1;
1439
}
1440
 
4641 dpurdie 1441
#----------------------------------------------------------------------------
1442
# Function        : ReplaceTags
1443
#
1444
# Description     : This sub-routine is used to replace Tags in one or more files
1445
#
1446
# Inputs          : outPath                 - Output directory
1447
#                   flist                   - List of files in that directory
1448
#                   or
1449
#                   SearchOptions           - Search options to find files
1450
#                                           --Recurse
1451
#                                           --NoRecurse
1452
#                                           --FilterIn=xxx
1453
#                                           --FilterInRe=xxx
1454
#                                           --FilterOut=xxx
1455
#                                           --FilterOutRe=xxx
1456
#                   Common options
1457
#                                           --Tag=Tag,Replace
1458
#                                           
1459
#
1460
# Returns         : 1
1461
#
1462
sub ReplaceTags
1463
{
1464
    my @uargs;
1465
    my $search =  JatsLocateFiles->new( '--NoRecurse' );
1466
    my @tagsList;
1467
    my $tagSep = ',';
1468
    my @tagOrder;
1469
    my %tagData;
1470
 
1471
    #
1472
    #   Process user arguments extracting options
1473
    #
1474
    foreach  ( @_ )
1475
    {
1476
        if ( m~^--Recurse~ ) {
1477
            $search->recurse(1);
1478
 
1479
        } elsif ( m~^--NoRecurse~) {
1480
            $search->recurse(0);
1481
 
1482
        } elsif ( /^--FilterOut=(.*)/ ) {
1483
            $search->filter_out($1);
1484
 
1485
        } elsif ( /^--FilterOutRe=(.*)/ ) {
1486
            $search->filter_out_re($1);
1487
 
1488
        } elsif ( /^--FilterIn=(.*)/ ) {
1489
            $search->filter_in($1);
1490
 
1491
        } elsif ( /^--FilterInRe=(.*)/ ) {
1492
            $search->filter_in_re($1);
1493
 
1494
        } elsif ( m~^--Tag=(.*)~) {
1495
            push @tagsList, $1;
1496
 
1497
        } elsif ( m~^--~) {
1498
            Error ("ReplaceTags: Unknown option: $_");
1499
 
1500
        } else {
1501
            push @uargs, $_;
1502
        }
1503
    }
1504
 
1505
    #
1506
    #   Process non-option arguments
1507
    #       - Base dir
1508
    #       - List of files
1509
    #
1510
    my ($outPath, @flist) = @uargs;
1511
    Error ("ReplaceTags: Target Dir must be specified" ) unless ( $outPath );
1512
 
1513
    #
1514
    #   Sanity Tests
1515
    #
1516
    Error ("ReplaceTags: No tags specified" ) unless ( @tagsList );
1517
 
1518
    #
1519
    # Convert output path to physical path
1520
    #
1521
    my $topDir = catdir($DebianWorkDir, $outPath);
1522
    Verbose("ReplaceTags: topDir: $topDir");
1523
    Error ("ReplaceTags: Path does not exist", $topDir) unless ( -e $topDir );
1524
    Error ("ReplaceTags: Path is not a directory", $topDir) unless ( -d $topDir );
1525
 
1526
    #
1527
    #   Convert Tags into pairs for latter use
1528
    #
1529
    my $sep = quotemeta ($tagSep );
1530
    foreach my $tag ( @tagsList )
1531
    {
4714 dpurdie 1532
        my ($tname,$tvalue) = split ( $sep, $tag, 2 );
4641 dpurdie 1533
        Error ("No tag value in: $tag" ) unless ( defined $tvalue );
1534
        Error ("Duplicate Tag: $tname" ) if ( exists $tagData{$tname} );
1535
        Verbose ("Tag: $tname :: $tvalue");
1536
        push @tagOrder, $tname;
1537
        $tagData{$tname} = $tvalue;
1538
    }
1539
 
1540
    #
1541
    #   Need to determine if we are searching or simply using a file list
1542
    #   There are two forms of the functions. If any of the search options have
1543
    #   been used then we assume that we are searchine
1544
    #
1545
    if ( $search->has_filter() )
1546
    {
1547
        Error ("ReplaceTags: Cannot mix search options with named files") if ( @flist );
1548
        @flist = $search->search($topDir);
1549
    }
1550
    Error ("ReplaceTags: No files specified") unless ( @flist );
1551
 
1552
    #
1553
    #   Process all named files
1554
    #
1555
    foreach my $file ( @flist )
1556
    {
1557
 
1558
        # this is our file that we want to clean.
1559
        my ($ifileLoc) = "$topDir/$file";
1560
        my ($tfileLoc) = "$topDir/$file\.tmp";
1561
        Verbose("ReplaceTags: $file");
1562
 
1563
        # we will check to see if the file exists.
1564
        #
1565
        my $ifile;
1566
        my $tfile;
1567
        if ( -f "$ifileLoc" )
1568
        {
1569
            open ($ifile, "< $ifileLoc" ) or
1570
                Error("Failed to open file [$ifileLoc] : $!");
1571
 
1572
            open ($tfile, "> $tfileLoc" ) or
1573
                Error("Failed to open file [$tfileLoc] : $!");
1574
 
1575
            while ( <$ifile> ) 
1576
            {
1577
                s~[\n\r]+$~~;               # Chomp
1578
 
1579
                #
1580
                #   Perform tag replacement
1581
                #
1582
                foreach my $tag ( @tagOrder )
1583
                {
1584
                    my $value = $tagData{$tag};
1585
                    if ( s~$tag~$value~g )
1586
                    {
1587
                        Verbose2("Replaced: $tag with $value");
1588
                    }
1589
                }
1590
 
1591
                print $tfile "$_\n";
1592
            }
1593
        }
1594
        else
1595
        {
1596
            Error("ReplaceTags [$ifileLoc] does not exist.");
1597
        }
1598
 
1599
        close $ifile;
1600
        close $tfile;
1601
 
1602
 
1603
        # lets replace our original file with the new one
1604
        #
1605
        if(File::Copy::move("$tfileLoc", "$ifileLoc"))
1606
        {
1607
            Verbose2("ReplaceTags: Renamed [$tfileLoc] to [$ifileLoc] ...");
1608
        }
1609
        else
1610
        {
1611
            Error("ReplaceTags: Failed to rename file [$tfileLoc] to [$ifileLoc]: $!");
1612
        }
1613
    }
1614
 
1615
    return 1;
1616
}
1617
 
4640 dpurdie 1618
#-------------------------------------------------------------------------------
407 dpurdie 1619
# Function        : SetFilePerms
1620
#
1621
# Description     : Set file permissions on one or more files or directories
1622
#
1623
# Inputs          : $perm           - Perm Mask
1624
#                   @paths          - List of paths/files to process
1625
#                   Options
1626
#                       --Recurse   - Recurse subdirs
1627
#
1628
# Returns         : 
1629
#
1630
sub SetFilePerms
1631
{
1632
 
1633
    my @args;
1634
    my $perms;
1635
    my $recurse = 0;
1636
 
1637
    #
1638
    #   Process and Remove options
1639
    #
1640
    foreach  ( @_ )
1641
    {
1642
        if ( m/^--Recurse/ ) {
1643
            $recurse = 1;
1644
 
1645
        } elsif ( m/^--/ ) {
1646
            Error ("SetFilePerms: Unknown option: $_");
1647
 
1648
        } else {
1649
            push @args, $_;
1650
 
1651
        }
1652
    }
1653
 
1654
    $perms = shift @args;
1655
    Error ("SetFilePerms: No Permissions" ) unless ( $perms );
1656
 
1657
    foreach my $path ( @args )
1658
    {
1659
        Verbose ("Set permissions; $perms, $path");
1660
        my $full_path = $DebianWorkDir . '/' . $path;
1661
        if ( -f $full_path )
1662
        {
1663
            System ('chmod', $perms, $full_path );
1664
        }
1665
        elsif ( -d $full_path )
1666
        {
1667
            System ('chmod', '-R', $perms, $full_path ) if ($recurse);
1668
            System ('chmod', $perms, $full_path ) unless ($recurse);
1669
        }
1670
        else
1671
        {
1672
            Warning("SetFilePerms: Path not found: $path");
1673
        }
1674
    }
1675
}
1676
 
1677
#-------------------------------------------------------------------------------
4636 dpurdie 1678
# Function        : SetPermissions 
1679
#
1680
# Description     : Called to set permissions of files/dirs in a directory structure.
1681
#                   With no options sets DirTag and all files/dirs in it to perms
1682
#   
1683
# Inputs          : path        - The directory tag to start setting permissions on
1684
#                   Options     - See below
1685
#       
1686
#   Required Options:
1687
#       One or both of
1688
#               --FilePerms=    Sets the permissions of files to this permission.
1689
#                               If not supplied then no files have their permissions changed
1690
#               --DirPerms=     Sets the permissions of directories to this permission
1691
#                               If not supplied then no directories have their permissions changed
1692
#       OR
1693
#               --Perms=        Sets the permissions of both files and directories to this permissions
1694
#                               Equivalent to supplying both --FilePerms=X && --DirPerms=X
1695
#               
1696
#   Options:                    
1697
#               --RootOnly      Only sets the permissions on the 'path' directory/file, 
1698
#                               all other options ignored
1699
#               --SkipRoot      Does not set permissions on the 'path' directory/file, 
1700
#                               obviously mutually exlusive with --RootOnly
1701
#   
1702
#       Any option supported by JatsLocateFiles. 
1703
#       Some of these include:
1704
#               
1705
#               --Recurse       Recurse the directory tree.  Does a depth first recurse so that all 
1706
#                               dir entries are processed before the dir itself (default)
1707
#               --NoRecurse     Dont recurse
1708
#               --FilterIn=     Apply permissions to files/directories that matches this value.
1709
#               --FilterInRe=   Perl RE's can be used (Not Shell wildcards) and this option
1710
#                               can be supplied mulitple times
1711
#               --FilterOut=    Dont apply permissions to any files/directories matching this value
1712
#               --FilterOutRe=  Perl RE's can be used (Not Shell wildcards) and this option
1713
#                               can be supplied mulitple times
1714
#               
1715
#                               FilterIn is applied before FilterOut.  If Recurse is specified 
1716
#                               the directory will be recursed regardless of these filters, however
1717
#                               the filter will be applied when it comes time to chmod the dir 
1718
#
1719
#------------------------------------------------------------------------------
1720
sub SetPermissions
1721
{
1722
    my ( $path, $filePerms, $dirPerms, $someDone );
1723
    my ( $rootOnly, $skipRoot ) = ( 0, 0 );
1724
 
1725
    my $search =  JatsLocateFiles->new( '--Recurse', '--DirsToo' );
1726
 
1727
    foreach ( @_ )
1728
    {
1729
        if ( m/^--Perms=(.*)/ ) {
1730
            $filePerms = $1;
1731
            $dirPerms = $1;
1732
 
1733
        } elsif (m/^--FilePerms=(.*)/ )  {
1734
            $filePerms = $1;
1735
 
1736
        } elsif ( m/^--DirPerms=(.*)/ )  {
1737
            $dirPerms = $1;
1738
 
1739
        }  elsif ( m/^--RootOnly/ ) {
1740
            $rootOnly = 1;
1741
 
1742
        } elsif ( m/^--SkipRoot/ )  {
1743
            $skipRoot = 1;
1744
 
1745
        } elsif ( m/^--Filter/ && $search->option( $_ ) ) {
1746
            Verbose2 ("Search Option: $_" );
1747
 
1748
        } elsif ( m/^--Recurse|--NoRecurse/ && $search->option( $_ ) ) {
1749
            Verbose2 ("Search Option: $_" );
1750
 
1751
        } elsif (m/^--/ ) {
1752
            Error ("SetPermissions: Unknown option: $_");
1753
 
1754
        } else  {
1755
            Error("SetPermissions 'path' already set", "Path: $_") if ( $path );
1756
            $path = $_;
1757
        }
1758
    }
1759
 
1760
    #
1761
    #   Sanity test
1762
    #
1763
    Error("SetPermissions called with out a 'path' parameter") if ( !defined($path) );
1764
    Error("SetPermissions called with out any Permissions specified") if ( !defined($filePerms) && !defined($dirPerms) );
1765
    Error("SetPermissions: Options --RootOnly & --SkipRoot are mutually exclusive" ) if ( $rootOnly && $skipRoot );
1766
 
1767
 
1768
    #   Convert the target directory name into a physical path
1769
    #   User specifies '/' as the root of the image
1770
    #   User specifies 'name' as relateve to the root of the image
1771
    #
1772
    my $topDir = $DebianWorkDir . '/' . $path;
1773
    $topDir =~ s~/+$~~;
1774
 
1775
    Verbose("SetPermissions: Called with options " . join(", ", @_));
1776
 
1777
    #
1778
    #   Only set perms on the root directory
1779
    #       This is a trivial operation
1780
    #
1781
    if ( $rootOnly )
1782
    {
1783
        $someDone += chmodItem( $topDir, $filePerms, $dirPerms );
1784
    }
1785
    else
1786
    {
1787
        #
1788
        #   Create a list of files/dirs to process
1789
        #
1790
        my @elements = $search->search( $topDir );
1791
 
1792
        foreach my $dirEntry ( @elements )
1793
        {
1794
            my $fullPath = "$topDir/$dirEntry";
1795
 
1796
            # A dir and we dont have dirperms, so skip
1797
            if ( -d $fullPath && !defined($dirPerms) )
1798
            {
1799
                Verbose2("SetPermissions: Skipping dir $fullPath as we have no dir permissions");
1800
                next;
1801
            }
1802
 
1803
            # A file and we dont have fileperms, so skip
1804
            if ( -f $fullPath && !defined($filePerms) )
1805
            {
1806
                Verbose2("SetPermissions: Skipping file $fullPath as we have no file permissions");
1807
                next;
1808
            }
1809
 
1810
            # a file or a dir and have the right permissions and we are not recursing
1811
            if ( -f $fullPath || -d $fullPath )
1812
            {
1813
                $someDone += chmodItem( $fullPath, $filePerms, $dirPerms );
1814
            }
1815
            else
1816
            {
1817
                Warning("SetPermissions: Skipping $fullPath as its not a file or directory");
1818
            }
1819
        }
1820
 
1821
        #
1822
        #   Process the topDir
1823
        #   May not be modified if --SkipRoot has been requested
1824
        #
1825
        if ( !$skipRoot && -e $topDir )
1826
        {
1827
            $someDone += chmodItem( $topDir, $filePerms, $dirPerms );
1828
        }
1829
    }
1830
 
1831
    #   Final warning
1832
    #
1833
    Warning ("SetPermissions: No files located", "Args: @_") unless ( $someDone );
1834
}
1835
 
4676 dpurdie 1836
#************ INTERNAL USE ONLY  **********************************************
4636 dpurdie 1837
# Function        : chmodItem 
1838
#
1839
# Description     : Internal
1840
#                   chmod a file or a folder
1841
#
1842
# Inputs          : item                        - Item to mod
1843
#                   filePerms                   - File perms
1844
#                   dirPerms                    - dire perms
1845
#
1846
# Returns         : 1   - Item modified
1847
#                   0   - Item not modified
1848
#
4676 dpurdie 1849
#************ INTERNAL USE ONLY  **********************************************
4636 dpurdie 1850
sub chmodItem
1851
{
1852
    my ($item, $filePerms, $dirPerms) = @_;
1853
 
1854
    if ( -d $item && defined $dirPerms)
1855
    {
1856
        Verbose("SetPermissions: $dirPerms : $item");
1857
        System ('chmod', $dirPerms, $item );
1858
        return 1;
1859
    }
1860
 
1861
    if ( -f $item  && defined $filePerms)
1862
    {
1863
        Verbose("SetPermissions: $filePerms : $item");
1864
        System ('chmod', $filePerms, $item );
1865
        return 1;
1866
    }
1867
 
1868
    return 0;
1869
}
1870
 
1871
 
1872
#-------------------------------------------------------------------------------
407 dpurdie 1873
# Function        : CreateDir
1874
#
1875
# Description     : Create a directory within the target workspace
1876
#
1877
# Inputs          : $path           - Name of the target directory
1878
#
1879
# Returns         : Nothing
1880
#
1881
sub CreateDir
1882
{
1883
    my ($path) = @_;
1884
 
1885
    Verbose ("Create Dir: $path");
1886
    mkpath( $DebianWorkDir . '/' . $path );
1887
}
1888
 
1889
#-------------------------------------------------------------------------------
1890
# Function        : IsProduct
1891
#                   IsPlatform
1892
#                   IsTarget
427 dpurdie 1893
#                   IsVariant
407 dpurdie 1894
#
1895
# Description     : This function allows some level of control in the
1896
#                   packaging scripts. It will return true if the current
1897
#                   product is listed.
1898
#
1899
#                   Ugly after thought
1900
#
1901
#                   Intended use:
1902
#                       Xxxxxx(...) if (IsProduct( 'aaa',bbb' );
1903
#
1904
# Inputs          : products    - a list of products to compare against
1905
#
1906
# Returns         : True if the current build is for one of the listed products
1907
#
1908
sub IsProduct
1909
{
1910
    foreach ( @_ )
1911
    {
1912
        return 1 if ( $opt_product eq $_ );
1913
    }
1914
    return 0;
1915
}
1916
 
1917
sub IsPlatform
1918
{
1919
    foreach ( @_ )
1920
    {
1921
        return 1 if ( $opt_platform eq $_ );
1922
    }
1923
    return 0;
1924
}
1925
 
1926
sub IsTarget
1927
{
1928
    foreach ( @_ )
1929
    {
1930
        return 1 if ( $opt_target eq $_ );
1931
    }
1932
    return 0;
1933
}
1934
 
427 dpurdie 1935
sub IsVariant
1936
{
1937
    foreach ( @_ )
1938
    {
1939
        return 1 if ( $opt_variant eq $_ );
1940
    }
1941
    return 0;
1942
}
407 dpurdie 1943
 
4676 dpurdie 1944
#************ INTERNAL USE ONLY  **********************************************
407 dpurdie 1945
# Function        : FindFiles
1946
#
1947
# Description     : Locate files within a given dir tree
1948
#
1949
# Inputs          : $root           - Base of the search
1950
#                   $match          - Re to match
1951
#
1952
# Returns         : A list of files that match
1953
#
4676 dpurdie 1954
#************ INTERNAL USE ONLY  **********************************************
407 dpurdie 1955
my @FIND_LIST;
1956
my $FIND_NAME;
1957
 
1958
sub FindFiles
1959
{
1960
    my ($root, $match ) = @_;
1961
    Verbose2("FindFiles: Root: $root, Match: $match");
1962
 
1963
    #
1964
    #   Becareful of closure, Must use globals
1965
    #
1966
    @FIND_LIST = ();
1967
    $FIND_NAME = $match;
1968
    File::Find::find( \&find_files, $root);
1969
 
1970
    #
1971
    #   Find callback program
1972
    #
1973
    sub find_files
1974
    {
1975
        my $item =  $File::Find::name;
1976
 
1977
        return if ( -d $File::Find::name );
1978
        return unless ( $_ =~ m~$FIND_NAME~ );
1979
        push @FIND_LIST, $item;
1980
    }
1981
    return @FIND_LIST;
1982
}
1983
 
1984
#-------------------------------------------------------------------------------
1985
# Function        : CalcRelPath
1986
#
1987
# Description     : Return the relative path to the current working directory
1988
#                   as provided in $Cwd
1989
#
1990
# Inputs          : $Cwd - Base dir
1991
#                   $base - Path to convert
1992
#
1993
# Returns         : Relative path from the $Cwd
1994
#
1995
sub CalcRelPath
1996
{
1997
    my ($Cwd, $base) = @_;
1998
 
1999
    my @base = split ('/', $base );
2000
    my @here = split ('/', $Cwd );
2001
    my $result;
2002
 
2003
    Debug("RelPath: Source: $base");
2004
 
2005
    return $base unless ( $base =~ m~^/~ );
2006
 
2007
    #
2008
    #   Remove common bits from the head of both lists
2009
    #
2010
    while ( $#base >= 0 && $#here >= 0 && $base[0] eq $here[0] )
2011
    {
2012
        shift @base;
2013
        shift @here;
2014
    }
2015
 
2016
    #
2017
    #   Need to go up some directories from here and then down into base
2018
    #
2019
    $result = '../' x ($#here + 1);
2020
    $result .= join ( '/', @base);
2021
    $result = '.' unless ( $result );
2022
    $result =~ s~//~/~g;
2023
    $result =~ s~/$~~;
2024
 
2025
    Debug("RelPath: Result: $result");
2026
    return $result;
2027
}
2028
 
2029
#-------------------------------------------------------------------------------
2030
# Function        : ExpandLinkFiles
2031
#
2032
# Description     : Look for .LINK files in the output image and expand
2033
#                   the links into softlinks
2034
#
2035
# Inputs          : None
2036
#                   The rouine works on the $DebianWorkDir directory tree
2037
#
2038
# Returns         : Nothing
2039
#                   Will remove .LINKS files that are processed
2040
#
2041
sub ExpandLinkFiles
2042
{
2043
    foreach my $linkfile ( FindFiles( $DebianWorkDir, ".LINKS" ))
2044
    {
2045
        next if ( $linkfile =~ m~/\.svn/~ );
2046
        my $BASEDIR = StripFileExt( $linkfile );
2047
        $BASEDIR =~ s~^$DebianWorkDir/~~;
2048
        Verbose "Expand links: $BASEDIR";
2049
 
2050
        open (LF, "<", $linkfile ) || Error ("Cannot open link file: $linkfile" );
2051
        while ( <LF> )
2052
        {
2053
            chomp;
2054
            next if ( m~^#~ );
2055
            next unless ( $_ );
2056
            my ($link, $file) = split;
2057
 
2058
            MakeSymLink($file ,"$BASEDIR/$link", '--NoDotDot' );
2059
        }
2060
        close (LF);
2061
        unlink $linkfile;
2062
    }
2063
}
2064
 
4676 dpurdie 2065
#************ INTERNAL USE ONLY  **********************************************
407 dpurdie 2066
# Function        : ResolveFile
2067
#
2068
# Description     : Determine where the source for a file is
415 dpurdie 2069
#                   Will look in (default):
407 dpurdie 2070
#                       Local directory
2071
#                       Local Include
415 dpurdie 2072
#                   Or  (FromPackage)
2073
#                       Our Package directory
2074
#                       Interface directory (BuildPkgArchives)
2075
#                       Packages (LinkPkgArchive)
2076
#
407 dpurdie 2077
#                   Will scan 'parts' subdirs
2078
#
2079
# Inputs          : $from_package       - 0 - Local File
2080
#                   $file
2081
#
2082
# Returns         : Path
2083
#
4676 dpurdie 2084
#************ INTERNAL USE ONLY  **********************************************
407 dpurdie 2085
sub ResolveFile
2086
{
2087
    my ($from_package, $file) = @_;
2088
    my $wildcard = ($file =~ /[*?]/);
415 dpurdie 2089
    my @path;
407 dpurdie 2090
 
2091
    #
415 dpurdie 2092
    #   Determine the paths to search
2093
    #
2094
    if ( $from_package )
2095
    {
2096
        unless ( @ResolveFileList )
2097
        {
2098
            push @ResolveFileList, $opt_pkgdir;
2099
            foreach my $entry ( getPackageList() )
2100
            {
2101
                push @ResolveFileList, $entry->getBase(3);
2102
            }
2103
        }
2104
        @path = @ResolveFileList;
2105
    }
2106
    else
2107
    {
2108
        @path = ('.', $opt_localincdir);
2109
    }
2110
 
2111
    #
407 dpurdie 2112
    #   Determine a full list of 'parts' to search
2113
    #   This is provided within the build information
2114
    #
2115
    my @parts = getPlatformParts ();
2116
    push @parts, '';
2117
 
2118
    my @done;
2119
    foreach my $root (  @path )
2120
    {
2121
        foreach my $subdir ( @parts )
2122
        {
2123
            my $sfile;
415 dpurdie 2124
            $sfile = "$root/$subdir/$file";
2125
            $sfile =~ s~//~/~g;
2126
            $sfile =~ s~^./~~g;
2127
            Verbose2("LocateFile: $sfile, $root, $subdir");
2128
            if ( $wildcard )
2129
            {
2130
                push @done, glob ( $sfile );
2131
            }
2132
            else
2133
            {
2134
                push @done, $sfile if ( -f $sfile || -l $sfile )
2135
            }
407 dpurdie 2136
        }
2137
    }
2138
 
415 dpurdie 2139
    Error ("ResolveFile: File not found: $file", "Search Path:", @path)
407 dpurdie 2140
        unless ( @done );
2141
 
2142
    Warning ("ResolveFile: Multiple instances of file found. Only first is used", @done)
2143
        if ( $#done > 0 && ! $wildcard && !wantarray );
2144
 
2145
    return wantarray ? @done : $done[0];
2146
}
2147
 
2148
#-------------------------------------------------------------------------------
2149
# Function        : ResolveBinFile
2150
#
415 dpurdie 2151
# Description     : Determine where the source for a BIN file is
2152
#                   Will look in (default):
2153
#                       Local directory
2154
#                       Local Include
2155
#                   Or  (FromPackage)
2156
#                       Our Package directory
2157
#                       Interface directory (BuildPkgArchives)
2158
#                       Packages (LinkPkgArchive)
407 dpurdie 2159
#                   Will scan 'parts' subdirs
2160
#
2161
# Inputs          : $from_package       - 0 - Local File
415 dpurdie 2162
#                   $file
407 dpurdie 2163
#
2164
# Returns         : Path
2165
#
2166
sub ResolveBinFile
2167
{
2168
    my ($from_package, $file) = @_;
2169
    my @path;
2170
    my @types;
2171
    my $wildcard = ($file =~ /[*?]/);
2172
 
415 dpurdie 2173
    #
2174
    #   Determine the paths to search
2175
    #
407 dpurdie 2176
    if ( $from_package )
2177
    {
415 dpurdie 2178
        unless ( @ResolveBinFileList )
2179
        {
2180
            push @ResolveBinFileList, $opt_pkgdir . '/bin';
2181
            foreach my $entry ( getPackageList() )
2182
            {
2183
                if ( my $path = $entry->getBase(3) )
2184
                {
2185
                    $path .= '/bin';
2186
                    push @ResolveBinFileList, $path if ( -d $path );
2187
                }
2188
            }
2189
        }
2190
        @path = @ResolveBinFileList;
407 dpurdie 2191
        @types = ($opt_type, '');
2192
    }
2193
    else
2194
    {
2195
        @path = ($opt_bindir, $opt_localbindir);
2196
        @types = '';
2197
    }
2198
 
2199
    #
2200
    #   Determine a full list of 'parts' to search
2201
    #   This is provided within the build information
2202
    #
2203
    my @parts = getPlatformParts ();
2204
    push @parts, '';
2205
 
2206
    my @done;
2207
    foreach my $root (  @path )
2208
    {
2209
        foreach my $subdir ( @parts )
2210
        {
2211
            foreach my $type ( @types )
2212
            {
2213
                my $sfile;
2214
                $sfile = "$root/$subdir$type/$file";
2215
                $sfile =~ s~//~/~g;
2216
                Verbose2("LocateBinFile: $sfile");
2217
                if ( $wildcard )
2218
                {
429 dpurdie 2219
                    foreach  ( glob ( $sfile ) )
2220
                    {
4143 dpurdie 2221
                        # Ignore .dbg (vix) and .debug (qt) files.
429 dpurdie 2222
                        next if ( m~\.dbg$~ );
4143 dpurdie 2223
                        next if ( m~\.debug$~ );
429 dpurdie 2224
                        push @done, $_;
2225
                    }
407 dpurdie 2226
                }
2227
                else
2228
                {
415 dpurdie 2229
                    push @done, $sfile if ( -f $sfile || -l $sfile )
407 dpurdie 2230
                }
2231
            }
2232
        }
2233
    }
2234
 
415 dpurdie 2235
    Error ("ResolveBinFile: File not found: $file", "Search Path:", @path)
407 dpurdie 2236
        unless ( @done );
2237
 
2238
    Warning ("ResolveBinFile: Multiple instances of file found. Only first is used", @done)
2239
        if ( $#done > 0 && ! $wildcard && !wantarray );
2240
    return wantarray ? @done : $done[0];
2241
}
2242
 
2243
#-------------------------------------------------------------------------------
2244
# Function        : ResolveLibFile
2245
#
415 dpurdie 2246
# Description     : Determine where the source for a LIB file is
2247
#                   Will look in (default):
2248
#                       Local directory
2249
#                       Local Include
2250
#                   Or  (FromPackage)
2251
#                       Our Package directory
2252
#                       Interface directory (BuildPkgArchives)
2253
#                       Packages (LinkPkgArchive)
407 dpurdie 2254
#                   Will scan 'parts' subdirs
2255
#
4672 dpurdie 2256
# Inputs          : $from_package   - 0:Local File
2257
#                   $file           - Basename for a 'realname'
2258
#                                     Do not provide 'lib' or '.so' or version info
2259
#                                     May contain embedded options
2260
#                                       --Dll           - Use Windows style versioned DLL
2261
#                                       --VersionDll    - Use the versioned DLL
2262
#                                       --3rdParty      - Use exact name provided
407 dpurdie 2263
#
2264
# Returns         : Path
2265
#
2266
sub ResolveLibFile
2267
{
2268
    my ($from_package, $file) = @_;
2269
    my $wildcard = ($file =~ /[*?]/);
2270
    my @options;
2271
    my $num_dll;
415 dpurdie 2272
    my @path;
407 dpurdie 2273
    #
2274
    #   Extract options from file
2275
    #
409 alewis 2276
    $num_dll = 0;
407 dpurdie 2277
    ($file, @options) = split ( ',', $file);
2278
    foreach ( @options )
2279
    {
2280
        if ( m/^--Dll/ ) {
2281
            $num_dll = 1;
2282
        } elsif ( m/^--VersionDll/ ) {
2283
            $num_dll = 2;
4672 dpurdie 2284
        } elsif ( m/^--3rdParty/ ) {
2285
            $num_dll = 3;
407 dpurdie 2286
        } else {
2287
            Error ("Unknown suboption to ResolveLibFile: $_" );
2288
        }
2289
    }
2290
 
2291
    #
415 dpurdie 2292
    #   Determine the paths to search
2293
    #
2294
    if ( $from_package )
2295
    {
2296
        unless ( @ResolveLibFileList )
2297
        {
2298
            push @ResolveLibFileList, $opt_pkgdir . '/lib';
2299
            foreach my $entry ( getPackageList() )
2300
            {
2301
                push @ResolveLibFileList, $entry->getLibDirs(3);
2302
            }
2303
        }
2304
        @path = @ResolveLibFileList;
2305
    }
2306
    else
2307
    {
2308
        @path = ($opt_libdir, $opt_locallibdir);
2309
    }
2310
 
2311
    #
407 dpurdie 2312
    #   Determine a full list of 'parts' to search
2313
    #   This is provided within the build information
2314
    #
2315
    my @parts = getPlatformParts ();
2316
    push @parts, '';
2317
 
2318
    my @done;
2319
    foreach my $root (  @path )
2320
    {
2321
        foreach my $type ( $opt_type, '' )
2322
        {
2323
            foreach my $subdir ( @parts )
2324
            {
2325
                my $sfile;
2326
                my $exact;
2327
                if ( $num_dll == 2 ) {
2328
                    $sfile = $file . $type . '.*.dll' ;
2329
                } elsif ( $num_dll == 1 ) {
2330
                    $sfile = $file . $type . '.dll' ;
2331
                    $exact = 1;
4672 dpurdie 2332
                } elsif ( $num_dll == 3 ) {
2333
                    $sfile = $file;
2334
                    $exact = 1;
407 dpurdie 2335
                } else {
2336
                    $sfile = "lib" . $file . $type . '.so.*';
2337
                }
2338
 
2339
                $sfile = "$root/$subdir/$sfile";
2340
                $sfile =~ s~//~/~g;
2341
                Verbose2("LocateLibFile: $sfile");
2342
                if ( $exact )
2343
                {
415 dpurdie 2344
                    push @done, $sfile if ( -f $sfile || -l $sfile );
407 dpurdie 2345
                }
419 dpurdie 2346
                elsif ($num_dll)
407 dpurdie 2347
                {
2348
                    push @done, glob ( $sfile );
2349
                }
419 dpurdie 2350
                else
2351
                {
2352
                    #
2353
                    #   Looking for .so files
2354
                    #   Filter out the soname so files
2355
                    #   Assume that the soname is shorter than the realname
4143 dpurdie 2356
                    #       Ignore .dbg (vix) and .debug (qt) files.
419 dpurdie 2357
                    #
2358
                    my %sieve;
2359
                    foreach ( glob ( $sfile )  )
2360
                    {
429 dpurdie 2361
                        next if ( m~\.dbg$~ );
4143 dpurdie 2362
                        next if ( m~\.debug$~ );
421 alewis 2363
                        m~(.*\.so\.)([\d\.]*\d)$~;
2364
                        if ( $1 )
2365
                        {
2366
                            my $file = $1;
2367
                            my $len = exists $sieve{$file} ? length($sieve{$file}) : 0;
2368
                            $sieve{$file} = $_
2369
                                if ( $len == 0 || length($_) > $len );
2370
                        }                                
419 dpurdie 2371
                    }
2372
 
2373
                    push @done, values %sieve;
2374
                }
407 dpurdie 2375
            }
2376
        }
2377
    }
2378
 
415 dpurdie 2379
    Error ("ResolveLibFile: File not found: $file", "Search Path:", @path)
407 dpurdie 2380
        unless ( @done );
2381
 
2382
    Warning ("ResolveLibFile: Multiple instances of file found. Only first is used", @done)
2383
        if ( $#done > 0 && ! $wildcard && !wantarray );
2384
 
2385
    return wantarray ? @done : $done[0];
2386
}
2387
 
2388
 
2389
#-------------------------------------------------------------------------------
2390
# Function        : AUTOLOAD
2391
#
2392
# Description     : Intercept bad user directives and issue a nice error message
2393
#                   This is a simple routine to report unknown user directives
2394
#                   It does not attempt to distinguish between user errors and
2395
#                   programming errors. It assumes that the program has been
2396
#                   tested. The function simply report filename and line number
2397
#                   of the bad directive.
2398
#
2399
# Inputs          : Original function arguments ( not used )
2400
#
2401
# Returns         : This function does not return
2402
#
2403
our $AUTOLOAD;
2404
sub AUTOLOAD
2405
{
2406
    my $fname = $AUTOLOAD;
2407
    $fname =~ s~^main::~~;
2408
    my ($package, $filename, $line) = caller;
2409
 
2410
    Error ("Directive not known or not allowed in this context: $fname",
2411
           "Directive: $fname( @_ );",
2412
           "File: $filename, Line: $line" );
2413
}
2414
 
2415
 
2416
1;
2417