Subversion Repositories DevTools

Rev

Rev 6863 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
6859 dpurdie 1
########################################################################
6861 dpurdie 2
# COPYRIGHT - VIX IP PTY LTD ("VIX"). ALL RIGHTS RESERVED.
6859 dpurdie 3
#
4
# Module name   : DebianPackager.pl
5
# Module type   : Makefile system
6
# Compiler(s)   : Perl
7
# Environment(s): jats
8
#
9
# Description   : This program is invoked by the MakeDebianPackage and MakeRpmPackage
10
#                 directive that is a part of this package
11
#
12
#                 The program will use a user-provided script in order
13
#                 to create the output 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/RPM configuration scripts 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
#                   Debian:
26
#                       Massage the Debian control file
27
#                       Create a Debian Package
28
#                       Transfer it to the users 'BIN' directory, where it is available to be packaged.
29
#                       
30
#                   RedHat Package:    
31
#                       Generate rpmBuilder control files
32
#                       Create the RPM image
33
#                       Transfer it to the users 'BIN' directory, where it is available to be packaged.
34
#                   
35
#                   TarFile:
36
#                       Tar Gzip the image
37
#                       Transfer it to the users 'BIN' directory, where it is available to be packaged.
38
#
39
#                 Summary of directives available to the user-script:
40
#                       Message                 - Display progress text
6861 dpurdie 41
#                       Verbose                 - Display progress text
6859 dpurdie 42
#                       AddInitScript           - Add an init script
43
#                       CatFile                 - Append to a file
44
#                       ConvertFile             - Convert file(s) to Unix or Dos Text
45
#                       CopyDir                 - Copy directory tree
46
#                       CopyFile                - Copy a file
47
#                       CopyBinFile             - Copy an executable file
48
#                       CopyLibFile             - Copy a library file
49
#                       CopyDebPackage          - Copy a Debian Package
50
#                       CreateDir               - Create a directory
6861 dpurdie 51
#                       AllFiles                - Specify control and script files 
6859 dpurdie 52
#                       DebianFiles             - Specify control and script files (Debian Only)
53
#                       RpmFiles                - Specify control and script files (RPM Only)
6861 dpurdie 54
#                       AllControlFile          - Specify control and script files
6859 dpurdie 55
#                       DebianControlFile       - Specify control and script files (Debian Only)
56
#                       RpmControlFile          - Specify control and script files (RPM Only)
6861 dpurdie 57
#                       AllDepends               - Add Depends entry to control file
6859 dpurdie 58
#                       DebianDepends           - Add Depends entry to control file (Debian Only)
59
#                       RpmDepends              - Add Depends entry to control file (RPM Only)
60
#                       EchoFile                - Place text into a file
61
#                       MakeSymLink             - Create a symbolic link
62
#                       PackageDescription      - Specify the package description
63
#                       ReplaceTags             - Replace Tags on target file
64
#                       SetFilePerms            - Set file permissions
65
#                       SetVerbose              - Control progress display
66
#                       IsProduct               - Flow control
67
#                       IsPlatform              - Flow control
68
#                       IsTarget                - Flow control
69
#                       IsVariant               - Flow control
70
#                       IsAlias                 - Flow control
71
#                       RpmSetDefAttr           - Specify default file properties (RPM Only)
72
#                       RpmSetAttr              - Specify file properties (RPM Only)    
73
#                       SetBaseDir              - Sets base for installed files (RPM Hint for directory ownership)
6861 dpurdie 74
#                       Section                 - Set current section
6865 dpurdie 75
#                       PackageVersion          - Return the version of a named package
6859 dpurdie 76
#
77
#                 Thoughts for expansion:
78
#                       SrcDir                  - Extend path for resolving local files
79
#
80
#                   Less used:
81
#                        ExpandLinkFiles        - Expand .LINK files
82
#
83
#                   Internal Use:
84
#                        FindFiles              - Find a file
85
#                        ResolveFile            - Resolve a 'local' source file
86
#                        chmodItem              - Set file or directory permissions
87
#                        
88
#......................................................................#
89
 
90
require 5.006_001;
91
use strict;
92
use warnings;
93
 
94
use Getopt::Long;
95
use File::Path;
96
use File::Copy;
97
use File::Find;
98
use JatsSystem;
99
use FileUtils;
100
use ArrayHashUtils;
101
use JatsError;
102
use JatsLocateFiles;
103
use ReadBuildConfig;
104
use JatsCopy ();                            # Don't import anything
6861 dpurdie 105
use PackagerUtils;
6859 dpurdie 106
 
107
#
108
#   Command line options
109
#
110
my $opt_debug   = $ENV{'GBE_DEBUG'};        # Allow global debug
111
my $opt_verbose = $ENV{'GBE_VERBOSE'};      # Allow global verbose
112
my $opt_vargs;                              # Verbose arg
113
my $opt_help = 0;
114
my $opt_manual = 0;
115
my $opt_clean = 0;
116
my $opt_interfacedir;
117
my $opt_package_script;
118
my $opt_interfaceincdir;
119
my $opt_interfacelibdir;
120
my $opt_interfacebindir;
121
my $opt_libdir;
122
my $opt_bindir;
123
my $opt_localincdir;
124
my $opt_locallibdir;
125
my $opt_localbindir;
126
my $opt_pkgdir;
127
my $opt_pkglibdir;
128
my $opt_pkgbindir;
129
my $opt_pkgpkgdir;
130
my $opt_noarch;
131
my $opt_tarFile;
6861 dpurdie 132
my $opt_tarOnly;
6859 dpurdie 133
my $opt_rpm = 0;
134
my $opt_debian = 0;
135
my $opt_output;
136
 
137
#
138
#   Options marked as 'our' so that they are visible within the users script
139
#   Don't give the user too much
140
#
141
our $opt_platform;
142
our $opt_type;
143
our $opt_buildname;
144
our $opt_buildversion;
145
our $opt_target;
146
our $opt_product;
147
our $opt_name;
148
our $opt_variant;
149
our $opt_pkgarch;
150
our $opt_rpmRelease = '';
151
 
152
#
153
#   Options derived from script directives
154
#
155
my $opt_description;
156
my $opt_specFile;
157
 
158
#
159
#   Globals
160
#
161
my $WorkDirBase;                            # Workspace
162
my $WorkDirInit;                            # Initial Dir to create file system image within
163
my $WorkDir;                                # Dir to create file system image within
164
my $WorkSubDir = '';                        # Diff between $WorkDirInit and $WorkDir
165
my @ResolveFileList;                        # Cached Package File List
166
my @ResolveBinFileList;                     # Cached PackageBin File List
167
my @ResolveDebFileList;                     # Cached PackageDeb File List
168
my @ResolveLibFileList;                     # Cached PackageLib File List
169
my %ControlFiles;                           # Control Files
170
my %ControlFileNames;                       # Control Files by name
171
my @DependencyList;                         # Package Dependencies
172
my @ConfigList;                             # Config Files
173
my %opt_aliases;                            # Cached Alias Names
174
my @RpmDefAttr = ('-','root','root','-');   # RPM: Default File Attributes
175
my @RpmAttrList;                            # RPM: File attributes
176
my %OwnedDirs;                              # RPM: Dirs marked as owned
6861 dpurdie 177
my $ActiveSection = 1;                      # Indicates if the section is active
6859 dpurdie 178
 
179
#-------------------------------------------------------------------------------
180
# Function        : Main Entry point
181
#
182
# Description     : This function will be called when the package is initialised
183
#                   Extract arguments from the users environment
184
#
185
#                   Done here to greatly simplify the user script
186
#                   There should be no junk in the user script - keep it simple
187
#
188
# Inputs          :
189
#
190
# Returns         : 
191
#
192
main();
193
sub main
194
{
195
    my $result = GetOptions (
196
                'verbose:s'         => \$opt_vargs,
197
                'clean'             => \$opt_clean,
198
                'Type=s'            => \$opt_type,
199
                'BuildName=s'       => \$opt_buildname,                     # Raw Jats Package Name (Do not use)
200
                'Name=s'            => \$opt_name,                          # Massaged Debian Package Name
201
                'BuildVersion=s'    => \$opt_buildversion,
202
                'Platform=s'        => \$opt_platform,
203
                'Target=s'          => \$opt_target,
204
                'Product=s'         => \$opt_product,
205
                'InterfaceDir=s'    => \$opt_interfacedir,
206
                'InterfaceIncDir=s' => \$opt_interfaceincdir,
207
                'InterfaceLibDir=s' => \$opt_interfacelibdir,
208
                'InterfaceBinDir=s' => \$opt_interfacebindir,
209
                'LibDir=s'          => \$opt_libdir,
210
                'BinDir=s'          => \$opt_bindir,
211
                'LocalIncDir=s'     => \$opt_localincdir,
212
                'LocalLibDir=s'     => \$opt_locallibdir,
213
                'LocalBinDir=s'     => \$opt_localbindir,
214
                'PackageDir=s'      => \$opt_pkgdir,
215
                'PackageLibDir=s'   => \$opt_pkglibdir,
216
                'PackageBinDir=s'   => \$opt_pkgbindir,
217
                'PackagePkgDir=s'   => \$opt_pkgpkgdir,
218
                'Variant:s'         => \$opt_variant,
219
                'PkgArch:s'         => \$opt_pkgarch,
220
                'NoArch'            => \$opt_noarch,
221
                'tarFile=s'         => \$opt_tarFile,
6861 dpurdie 222
                'tarOnly'           => \$opt_tarOnly,
6859 dpurdie 223
                'genRpm'            => \$opt_rpm,
224
                'genDeb'            => \$opt_debian,
225
                'output=s'          => \$opt_output,
226
                'script=s'          => \$opt_package_script,
227
                'rpmRelease=s'      => \$opt_rpmRelease,
228
    );
229
    $opt_verbose++ unless ( $opt_vargs eq '@' );
230
 
231
    ErrorConfig( 'name'    => 'PackagerUtils',
232
                 'verbose' => $opt_verbose,
233
                 'debug'   => $opt_debug );
234
 
235
    #
236
    #   Init the FileSystem Uiltity interface
237
    #
238
    InitFileUtils();
239
 
240
    #
241
    #   Ensure that we have all required options
242
    #
243
    Error ("Platform not set")                  unless ( $opt_platform );
244
    Error ("Type not set")                      unless ( $opt_type );
245
    Error ("BuildName not set")                 unless ( $opt_buildname );
246
    Error ("Package Name not set")              unless ( $opt_name );
247
    Error ("BuildVersion not set")              unless ( $opt_buildversion );
248
    Error ("InterfaceDir not set")              unless ( $opt_interfacedir );
249
    Error ("Target not set")                    unless ( $opt_target );
250
    Error ("Product not set")                   unless ( $opt_product );
251
    Error ("Packaging Script not set")          unless ( $opt_package_script );
252
 
253
    #
254
    #   Read in relevent config information
255
    #
256
    ReadBuildConfig ($opt_interfacedir, $opt_platform, '--NoTest' );
257
 
258
    #
259
    #   Build the package image in a directory based on the target being created
260
    #
261
    $WorkDirBase = uc("$opt_platform$opt_type.image");
262
    $WorkDirInit = "$WorkDirBase/$opt_name";
263
    $WorkDir = $WorkDirInit;
264
 
265
    #
266
    #   Configure the System command to fail on any error
267
    #
268
    SystemConfig ( ExitOnError => 1 );
269
 
270
    #
271
    #   Defaults
272
    #
273
    $opt_pkgarch = $opt_platform unless ( $opt_pkgarch );
274
 
275
    #
6861 dpurdie 276
    #   Determine build operations
277
    #   
278
    my $genDebian = $opt_debian;
279
    my $genRpm = $opt_rpm;
280
    if ($opt_tarOnly) {
281
        $genDebian = $genRpm = 0; 
282
    }
283
 
284
 
285
    #
6859 dpurdie 286
    #   Display variables used
287
    #
288
    Message    ("= Building Installer ================================================");
6861 dpurdie 289
    Message    ("        Format: Debian") if ($genDebian);
290
    Message    ("        Format: RPM") if ($genRpm);
6859 dpurdie 291
    Message    ("        Format: TGZ") if ($opt_tarFile);
292
    Message    ("          Name: $opt_name");
293
    Message    ("       Package: $opt_buildname");
294
    Message    ("       Variant: $opt_variant") if ($opt_variant);
295
    Message    ("       Version: $opt_buildversion");
296
    Message    ("  Building for: $opt_platform");
297
    Message    ("        Target: $opt_target") if ( $opt_platform ne $opt_target);
298
    Message    ("       Product: $opt_product") if ($opt_product ne $opt_platform);
299
    Message    ("          Type: $opt_type");
300
    Message    ("   RPM Release: $opt_rpmRelease") if ($opt_rpmRelease);
301
    Message    ("      Pkg Arch: $opt_pkgarch") if ($opt_pkgarch);
302
    Verbose    ("       Verbose: $opt_verbose");
303
    Verbose    ("  InterfaceDir: $opt_interfacedir");
6861 dpurdie 304
    Message    ("        Output: " . StripDir($opt_output))  if ($genDebian || $genRpm);
6859 dpurdie 305
    Message    ("        Output: " . StripDir($opt_tarFile)) if $opt_tarFile;
306
    Message    ("======================================================================");
307
 
308
    #
309
    #   Perform Clean up
310
    #   Invoked during "make clean" or "make clobber"
311
    #
312
    if ( $opt_clean )
313
    {
314
        Message ("Remove packaging directory: $WorkDirInit");
315
 
316
        #
317
        #   Remove the directory for this package
318
        #   Remove the general work dir - if all packages have been cleaned
319
        #
320
        rmtree( $WorkDirBase );
321
        rmtree ($opt_tarFile) if ( defined($opt_tarFile) && -f $opt_tarFile );
322
        rmtree ($opt_output) if ( -f $opt_output );
323
        exit;
324
    }
325
 
326
    #
327
    #   NoArch sanity test
328
    #       MUST only build no-arch for production
329
    #       User MUST do this in the build.pl file
330
    #
331
    if ($opt_noarch && $opt_type ne 'P')
332
    {
333
        Error ("Installer Packages marked as NoArch (all) must be built ONLY for production",
334
               "This must be configured in the build.pl" );
335
    }
336
 
337
    #
338
    #   Clean  out the WORK directory
339
    #   Always start with a clean slate
340
    #
341
    #   Ensure that the base of the directory tree does not have 'setgid'
342
    #       This will upset the debian packager
343
    #       This may be an artifact from the users directory and not expected
344
    #
345
    rmtree( $WorkDirInit );
346
    mkpath( $WorkDirInit );
347
 
348
    my $perm = (stat $WorkDirInit)[2] & 0777;
349
    chmod ( $perm & 0777, $WorkDirInit );
350
 
351
    #
352
    #   Invoke the user script to do the hard work
353
    #
354
    unless (my $return = do $opt_package_script) {
355
            Error ("Couldn't parse $opt_package_script: $@") if $@;
356
            Error ("Couldn't do $opt_package_script: $!") unless defined $return;
6861 dpurdie 357
        };
358
    $ActiveSection = 1;
6859 dpurdie 359
 
360
    #
361
    #   Now have an image of the directory that we wish to package
362
    #   Complete the building of the package
363
    #
6861 dpurdie 364
    if ($opt_tarFile) {
6859 dpurdie 365
        BuildTarFile();
366
        Message ("Created TGZ file");
367
    }
368
 
369
    #
370
    #   Create an RPM
371
    #
6861 dpurdie 372
    if ($genRpm) {
6859 dpurdie 373
        BuildRPM ();
374
        Message ("Created RPM");
375
    }
376
 
6861 dpurdie 377
    #
378
    #   Create a Debian Package
379
    #
380
    if ($genDebian) {
6859 dpurdie 381
        BuildDebianPackage ();
382
        Message ("Created Debian Package");
383
    }
384
}
385
 
386
#-------------------------------------------------------------------------------
387
# Function        : BuildRPM 
388
#
389
# Description     : This function will create the Debian Package
390
#                   and transfer it to the target directory
391
#
392
# Inputs          : None
393
#
394
# Returns         : Nothing
395
# 
396
sub BuildRPM
397
{
398
    #
399
    #   Sanity Checks
400
    #
401
    Error ("BuildRPM: Release")
402
        unless ( $opt_rpmRelease );
403
    Error ("BuildRPM: No Control File or Package Description")
404
        unless ( exists($ControlFiles{'control'}) || $opt_description );
405
 
406
    #
407
    #   Massage the 'control' file
408
    #   Generate or Massage
409
    #
410
    $opt_specFile = catfile($WorkDirBase, 'RPM.spec' );
411
    UpdateRedHatControlFile ($ControlFiles{'control'} );
412
 
413
    #   Generate a dummy rc file
414
    my $rcFile = catdir($WorkDirBase,'tmprc');
415
    TouchFile($rcFile);
416
 
417
    #
418
    #   Run the RPM builder
419
    #   Expect it to be installed on the build machine
420
    #
421
    my $prog = LocateProgInPath( 'rpmbuild', '--All');
422
    Error ("RPM Packager: The rpmbuild utility is not installed") unless $prog;
423
    System ($prog, '-bb', $opt_specFile, 
424
                   '--buildroot', AbsPath($WorkDirInit) ,
425
                   '--define', '_rpmdir ' . StripFileExt($opt_output),
426
                   '--define', '_rpmfilename ' .  StripDir($opt_output),
427
                   '--define', '_topdir ' . catfile($WorkDirBase, 'RPMBUILD' ),
428
                   '--noclean',
429
                   $opt_verbose ? '-v' : '--quiet',
6863 dpurdie 430
                   #$opt_noarch ?  '--target=noarch' : undef,
6859 dpurdie 431
                   '--rcfile', $rcFile ,
432
                   );
433
 
434
 
435
}
436
 
437
#-------------------------------------------------------------------------------
438
# Function        : BuildDebianPackage
439
#
440
# Description     : This function will create the Debian Package
441
#                   and transfer it to the target directory
442
#
443
# Inputs          : None
444
#
445
# Returns         : Nothing
446
#
447
sub BuildDebianPackage
448
{
449
    Error ("BuildDebianPackage: No Control File or Package Description")
450
        unless ( exists($ControlFiles{'control'}) || $opt_description );
451
 
452
    #
453
    #   Convert the FileSystem Image into a Debian Package
454
    #       Insert Debian control files
455
    #
456
    Verbose ("Copy in the Debian Control Files");
457
    mkdir ( "$WorkDirInit/DEBIAN" );
458
 
459
    #
460
    #   Copy in all the named Debian Control files
461
    #       Ignore any control file. It will be done next
462
    #
463
    foreach my $key ( keys %ControlFiles )
464
    {
465
        next if ($key eq 'control');
466
        CopyFile ( $ControlFiles{$key}, '/DEBIAN', $key  );
467
    }
468
 
469
    #
470
    #   Create 'conffiles'
471
    #       Append to any user provided file
472
    if ( @ConfigList )
473
    {
474
        my $conffiles = "$WorkDirInit/DEBIAN/conffiles";
475
        Warning("Appending user specified entries to conffiles") if ( -f $conffiles);
476
        FileAppend( $conffiles, @ConfigList );
477
    }
478
 
479
    #
480
    #   Massage the 'control' file
481
    #
482
    UpdateDebianControlFile ($ControlFiles{'control'} );
483
 
484
    #
485
    #   Mark all files in the debian folder as read-execute
486
    #
487
    System ( 'chmod', '-R', 'a+rx', "$WorkDirInit/DEBIAN" );
488
    System ( 'build_dpkg.sh', '-b', $WorkDirInit);
489
    System ( 'mv', '-f', "$WorkDirInit.deb", $opt_output );
490
 
491
    System ("build_dpkg.sh", '-I', $opt_output) if (IsVerbose(1));
492
 
493
}
494
 
495
#-------------------------------------------------------------------------------
496
# Function        : BuildTarFile 
497
#
498
# Description     : This function will create a TGZ file of the constructed package
499
#                   Not often used 
500
#
501
# Inputs          : None
502
#
503
# Returns         : Nothing
504
#
505
sub BuildTarFile
506
{
507
    Verbose ("Create TGZ file containing body of the package");
508
    System ('tar', 
509
            '--create',
510
            '--auto-compress',
511
            '--owner=0' ,
512
            '--group=0' ,
513
            '--one-file-system' ,
514
            '--exclude=./DEBIAN' ,
515
            '-C', $WorkDirInit,  
516
            '--file', $opt_tarFile,
517
            '.'
518
            );
519
}
520
 
6861 dpurdie 521
#-------------------------------------------------------------------------------
522
# Function        : Section 
523
#
524
# Description     : Allows the Package file to be split into section
525
#                   This direcive is always active.
526
#
527
# Inputs          : Selector
528
#                       ALL     - Active
529
#                       RPM     - Active section when building an RPM
530
#                       DEBIAN  - Active section if build a Debian package
531
#                       TAR     - Active section if building a TAR
532
#
533
# Returns         : Nothing
534
#                   Will fkag to indicate if directives are active. 
535
#
536
sub Section
537
{
538
    my $newActiveSection;
539
    my $flip = sub {
540
        my ($val, $mode) = @_;
541
        if ( defined $mode) {
542
            return $val ? 0 : 1;
543
        }
544
        return $val;
545
    };
6859 dpurdie 546
 
6861 dpurdie 547
    $newActiveSection = 1 unless (@_);
548
    foreach my $arg ( @_)
549
    {
550
        if ($arg =~ m/^(!)*DEBIAN/i) {
551
            $newActiveSection = 1 if  $flip->($opt_debian, $1);
552
 
553
        } elsif ($arg =~ m/^(!)*RPM/i) {
554
            $newActiveSection = 1 if  $flip->($opt_rpm, $1);
555
 
556
        } elsif ($arg =~ m/^(!)*TAR/i) {
557
            $newActiveSection = 1 if $flip->($opt_tarFile, $1);
558
 
559
        } elsif (uc($arg) eq 'ALL') {
560
            $newActiveSection = 1;
561
 
562
        } elsif ( $arg eq 1  ) {
563
                $newActiveSection = 1;
564
 
565
        } elsif ( $arg eq 0  ) {
566
 
567
        } else {
568
            Warning ("Section: Unknown argument $arg");
569
        }
570
    }
571
 
572
    $ActiveSection = $newActiveSection ? 1: 0;
573
    Verbose ("Section State: $ActiveSection");
574
 
575
}
576
 
6859 dpurdie 577
#-------------------------------------------------------------------------------
578
# Function        : UpdateDebianControlFile
579
#
580
# Description     : Update the Debian 'control' file to fix up various fields
581
#                   within the file.
582
#
583
#                   If the files has not been specified, then a basic control
584
#                   file will be provided.
585
#
586
#                   This routine knows where the control file will be placed
587
#                   within the output work space.
588
#
589
# Inputs          : $src            - Path to source file
590
#                   Uses global variables
591
#
592
# Returns         : Nothing
593
#
594
sub UpdateDebianControlFile
595
{
596
    my($src) = @_;
6861 dpurdie 597
    return 1 unless ($ActiveSection);
6859 dpurdie 598
    my $dst = "$WorkDirInit/DEBIAN/control";
599
 
600
    unless ( $src )
601
    {
602
        CreateDebianControlFile();
603
        return;
604
    }
605
 
606
    #
607
    #   User has provided a control file
608
    #       Tweak the internals
609
    #
610
    Verbose ("UpdateDebianControlFile: $dst" );
611
    $src = ResolveFile( 0, $src );
612
 
613
    #   Calc depends line
614
    my $depData = join (', ', @DependencyList );
615
 
616
    open (SF, '<', $src) || Error ("UpdateDebianControlFile: Cannot open:$src, $!");
617
    open (DF, '>', $dst) || Error ("UpdateDebianControlFile: Cannot create:$dst, $!");
618
    while ( <SF> )
619
    {
620
        s~\s*$~~;
621
        if ( m~^Package:~ ) {
622
            $_ = "Package: $opt_name";
623
 
624
        } elsif ( m~^Version:~ ) {
625
            $_ = "Version: $opt_buildversion";
626
 
627
        } elsif ( m~^Architecture:~ ) {
628
            $_ = "Architecture: $opt_pkgarch";
629
 
630
        } elsif ( $opt_description && m~^Description:~ ) {
631
            $_ = "Description: $opt_description";
632
 
633
        } elsif ( m~^Depends:~ ) {
634
            $_ = "Depends: $depData";
635
            $depData = '';
636
        }
637
        print DF $_ , "\n";
638
    }
639
 
640
    close (SF);
641
    close (DF);
642
 
643
    #
644
    #   Warn if Depends section is needed
645
    #
646
    Error ("No Depends section seen in user control file") 
647
        if ($depData);
648
}
649
 
650
#-------------------------------------------------------------------------------
651
# Function        : CreateDebianControlFile
652
#
653
# Description     : Create a basic debian control file
654
#
655
# Inputs          : Uses global variables
656
#
657
# Returns         : 
658
#
659
sub CreateDebianControlFile
660
{
6861 dpurdie 661
    return 1 unless ($ActiveSection);
6859 dpurdie 662
    my $dst = "$WorkDirInit/DEBIAN/control";
663
 
664
    Verbose ("CreateDebianControlFile: $dst" );
665
 
666
    my $depData = join (', ', @DependencyList );
667
 
668
    open (DF, '>', $dst) || Error ("CreateDebianControlFile: Cannot create:$dst");
669
    print DF "Package: $opt_name\n";
670
    print DF "Version: $opt_buildversion\n";
671
    print DF "Section: main\n";
672
    print DF "Priority: standard\n";
673
    print DF "Architecture: $opt_pkgarch\n";
674
    print DF "Essential: No\n";
675
    print DF "Maintainer: Vix Technology\n";
676
    print DF "Description: $opt_description\n";
677
    print DF "Depends: $depData\n" if ($depData);
678
 
679
    close (DF);
680
}
681
 
682
#-------------------------------------------------------------------------------
683
# Function        : UpdateRedHatControlFile 
684
#
685
# Description     : Update the Redhat 'control' file to fix up various fields
686
#                   within the file.
687
#
688
#                   If the files has not been specified, then a basic control
689
#                   (spec) file will be provided.
690
#                   Various tags will be replaced
691
#                       tag_name
692
#                       tag_version
693
#                       tag_buildarch
694
#                       tag_release
695
#                       tag_description
696
#                       tag_requires
697
#                       tag_filelist
698
#
699
# Inputs          : $src            - Path to source file
700
#                   Uses global variables
701
#
702
# Returns         : Nothing
703
#
704
sub UpdateRedHatControlFile
705
{
706
    my($src) = @_;
6861 dpurdie 707
    return 1 unless ($ActiveSection);
6859 dpurdie 708
    my $dst = $opt_specFile;
709
    unless ( $src )
710
    {
711
        CreateRedHatControlFile();
712
        return;
713
    }
714
 
715
    #
716
    #   User has provided a control file
717
    #       Tweak the internals
718
    #
719
    Verbose ("UpdateRedHatControlFile: $dst" );
720
    $src = ResolveFile( 0, $src );
721
 
722
    my @depList = @DependencyList;
723
    my $cleanSeen;
724
 
725
    open (my $sf, '<', $src) || Error ("UpdateRedHatControlFile: Cannot open:$src, $!");
726
    open (my $df, '>', $dst) || Error ("UpdateRedHatControlFile: Cannot create:$dst, $!");
727
    while ( <$sf> )
728
    {
729
        s~\s*$~~;
730
        if ( m~^tag_Name~i ) {
731
            $_ = "Name: $opt_name";
732
 
733
        } elsif ( m~^tag_Version~i ) {
734
            $_ = "Version: $opt_buildversion";
735
 
736
        } elsif ( m~^tag_BuildArch~i ) {
737
            $_ = "BuildArch: $opt_pkgarch";
738
 
739
        } elsif ( m~^tag_Release~i ) {
740
            $_ = "Release: $opt_rpmRelease";
741
 
742
        } elsif ( $opt_description && m~^tag_Description~i ) {
743
            print $df "%description\n";
744
            print $df "$opt_description\n";
745
            $_ = undef;
746
 
747
        } elsif ( m~^tag_Requires~i ) {
748
            foreach my $item (@depList) {
749
                print $df "Requires:       $item\n";
750
            }
751
            $_ = undef;
752
            @depList = ();
753
 
754
        } elsif ( m~^tag_filelist~i ) {
755
            GenerateRedHatFileList ($df);
756
            $_ = undef;
757
 
758
        } elsif ( m~^%clean~i ) {
759
            $cleanSeen  = 1;
760
        }
761
        print $df ($_ , "\n") if defined ($_);
762
    }
763
 
764
    close ($sf);
765
    close ($df);
766
 
767
    #
768
    #   Warn if Depends section is needed
769
    #
770
    Error ("No %clean section seen in user control file") unless $cleanSeen; 
771
    Error ("No Requires tag seen in user control file") if (@depList);
772
}
773
 
774
#-------------------------------------------------------------------------------
775
# Function        : CreateRedHatControlFile
776
#
777
# Description     : Create a binary RedHat spec file
778
#
779
# Inputs          : Uses global variables
780
#
781
# Returns         : 
782
#
783
sub CreateRedHatControlFile
784
{
785
    #
786
    #   Generate the RPM spec file
787
    #
788
    open (my $sf, '>', $opt_specFile) || Error ("RPM Spec File: Cannot create: $opt_specFile, $!");
789
 
790
    # Standard tags
791
    print $sf ("# Standard SPEC Tags\n");
792
    print $sf "Summary:        Installer for the $opt_name Package\n";
793
    print $sf "Name:           $opt_name\n";
794
    print $sf "Version:        $opt_buildversion\n";
795
    print $sf "Release:        $opt_rpmRelease\n";
6861 dpurdie 796
    print $sf "License:        COPYRIGHT - VIX IP PTY LTD (\"VIX\"). ALL RIGHTS RESERVED.\n";
6859 dpurdie 797
    print $sf "Source:         None\n";
798
    print $sf "BuildArch:      $opt_pkgarch\n";
799
    print $sf "Group:          VIX/System\n";
800
    print $sf "Vendor:         Vix Technology\n";
801
    print $sf "Autoreq:        No\n";
802
    #
803
    #   Requires tags
804
    #
805
    print $sf "\n# Dependencies\n" if @DependencyList;
806
    foreach my $item (@DependencyList) {
807
        print $sf "Requires:       $item\n";
808
    }
809
 
810
    print $sf "\n";
811
    print $sf "%description\n";
812
    print $sf "$opt_description\n";
813
 
814
    print $sf "\n";
815
    print $sf "%clean\n";
816
 
817
    #
818
    #   Insert various scripts
819
    #
820
    my $insertRpmControlFile = sub {
821
        my ($sname, $cname) = @_;
822
        if ( my $src = $ControlFiles{$cname} ) {
823
            print $sf "\n";
824
            print $sf '%' . $sname . "\n";
825
            open ( my $cf, '<', $src ) || Error ("BuildRPM: Cannot open:$src, $!");
826
            while ( <$cf> ) {
827
                $_ =~ s~\%~%%~g;
828
                print $sf $_;
829
            }
830
            close ($cf);
831
            print $sf "\n";
832
        }
833
    };
834
 
6861 dpurdie 835
    #   Run the PreInstall script as %pretrans
836
    #       %pretrans is the only script that can terminate the RPM installation
837
    &$insertRpmControlFile ('pretrans', 'preinst');
838
    &$insertRpmControlFile ('post',     'postinst');
839
    &$insertRpmControlFile ('preun',    'prerm');
840
    &$insertRpmControlFile ('postun',   'postrm');
6859 dpurdie 841
 
842
    #
843
    #   Insert the list of files to be processed
844
    #       Can't use /* as this will mess with permissions of the root directory. 
845
    #       Can list Top Level directories and then use *
846
    #
847
    print $sf "\n%files\n";
848
    print $sf "%defattr(",join (',', @RpmDefAttr),")\n";
849
    GenerateRedHatFileList ($sf);
850
    print $sf "\n";
851
    close ($sf);
852
}
853
 
854
#-------------------------------------------------------------------------------
855
# Function        : GenerateRedHatFileList 
856
#
857
# Description     : Internal function
858
#                   Generate a file list to be inserted into an RPM spec file
859
#
860
# Inputs          : $fd     - File descriptor.
861
#                             Function will write directly to the output
862
#
863
# Returns         : Nothing 
864
#
865
sub GenerateRedHatFileList
866
{
867
    my ($fd) = @_;
868
 
869
    #
870
    #   Sanity Test
871
    #
872
    Warning ("No directories has been marked as 'Owned'",
873
             "Under RedHat a directory must be 'owned' by a package so that it can be removed.",
874
             "This ownership may be in that package or a 'Required' package.",
875
             "This ownership may be shared or exclusive.",
876
             ) unless scalar keys %OwnedDirs;
877
 
878
    #
879
    #   Flag files and directories with attributes
880
    #
881
    my %Attrs;
882
    my %Dirs;
883
    foreach my $item ( @RpmAttrList ) {
884
        my $file =  $item->[0]; 
885
        my $full_path = $WorkDirInit . $file;
886
        $Attrs{$file} =  '%attr(' . join(',',@{$item}[1..3] ) . ')';
887
        $Dirs{$file} = '%dir' if (-d $full_path);
888
    }
889
 
890
    #
891
    #   Flag configuration files ( ConfFile )
892
    #
893
    my %Configs;
894
    foreach my $item (@ConfigList) {
895
        $Configs{$item} = '%config';
896
    }
897
 
898
    #
899
    #   Internal subroutine to pretty-print a file/dirname with attributes
900
    #       $path   - path element
901
    #       $isDir  - True if a directory
902
    #   
903
    my $printer = sub {
904
        my ($path, $isDir) = @_;
905
        my $attrText =  delete $Attrs{$path};
906
        my $confText =  delete $Configs{$path};
907
        my $dirText  =  delete $Dirs{$path};
908
        $dirText = '%dir' if $isDir;
909
 
910
        my $txt;
911
        my $joiner = '';
912
        $path = '"' . $path . '"';
913
        foreach ($attrText,$dirText,$confText, $path) {
914
            next unless $_;
915
            $txt .= $joiner . $_;
916
            $joiner = ' ';
917
        }
918
        print $fd ("$txt\n");
919
    };
920
 
921
    #
922
    #   List all files in the tree
923
    #       If we use wildcards we get interpackage dependency issues
924
    #       Process files and directories
925
    #
926
    my $search =  JatsLocateFiles->new( '--Recurse', '--NoFullPath', '--DirsToo' );
927
    my @flist = $search->search($WorkDirInit);
928
    foreach (@flist) {
929
        my $file = '/' . $_;
930
        my $full_path = $WorkDirInit . $file;
931
        my $isDir = (-d $full_path) || 0;
932
 
933
        #
934
        #   Determine if the element is within a known RootDir
935
        #
936
        my $inRoot = 0;
937
        my $isOwner = 0;
938
        foreach (keys %OwnedDirs) {
939
            if ($file =~ m~^$_~) {
940
                $inRoot = 1;
941
                $isOwner = $OwnedDirs {$_};
942
                last;
943
            }
944
        }
945
 
946
        #
947
        #   Ignore directories that are not within a RootDir
948
        #   
949
        unless ($inRoot) {
950
            next if $isDir;
951
        }
952
 
953
        #
954
        #   Ignore directories that are not within an 'owned' directory
955
        #
956
        if ( !$isOwner && $isDir ) {
957
            next;
958
        }
959
 
960
        &$printer($file, $isDir);
961
    }
962
 
963
    #
964
    #   Sanity tests
965
    #   We should have process all the Configs and Attributes
966
    #
967
    if ( (keys %Configs) || ( keys %Attrs))
968
    {
969
        Error ("Internal Error. Unprocessed Config or Attributes.",
970
               keys %Configs, keys %Attrs );
971
    }
972
 
973
}
974
 
975
#-------------------------------------------------------------------------------
976
# Function        : SetVerbose
977
#
978
# Description     : Set the level of verbosity
979
#                   Display activity
980
#
981
# Inputs          : Verbosity level
982
#                       0 - Use makefile verbosity (Default)
983
#                       1..2
984
#
985
# Returns         : 
986
#
987
sub SetVerbose
988
{
6861 dpurdie 989
    return 1 unless ($ActiveSection);
6859 dpurdie 990
    my ($level) = @_;
991
 
992
    $level = $opt_verbose unless ( $level );
993
    $opt_verbose = $level;
994
    ErrorConfig( 'verbose' => $level);
995
}
996
 
997
#-------------------------------------------------------------------------------
998
# Function        : SetBaseDir 
999
#
1000
# Description     : Sets the root directory for all directories
1001
#                   Used to simplify scripts
1002
#                   
1003
# Inputs          : $path           - Absolute path. Now within the RootDir
1004
#                   @options        - As for CreateDir
1005
#
1006
# Returns         : Nothing 
1007
#                   Sets $WorkDir
1008
#
1009
sub SetBaseDir
1010
{
1011
    my ($path, @opts) = @_;
6861 dpurdie 1012
    return 1 unless ($ActiveSection);
6859 dpurdie 1013
 
1014
    my $rootdir = $path || '/';
1015
    $rootdir = '/' . $rootdir;
1016
    $rootdir =~ s~/+~/~g; 
1017
    Verbose ("Setting RootDir: $rootdir");
1018
 
1019
    #
1020
    #   Create the directory
1021
    #
1022
    $WorkDir = $WorkDirInit;
1023
    CreateDir ($rootdir, @opts);
1024
    $WorkSubDir = $rootdir;
1025
    $WorkDir = $WorkDirInit . $rootdir;
1026
}
1027
 
1028
#-------------------------------------------------------------------------------
1029
# Function        : DebianFiles
1030
#                   RpmFiles
6861 dpurdie 1031
#                   AllFiles
6859 dpurdie 1032
#
1033
# Description     : Name Debian and RPM builder control files
1034
#                   May be called multiple times
1035
#
1036
# Inputs          :   $fName    - Name under which the function is being called
1037
#                     Options
1038
#                       --Control=file
1039
#                       --PreRm=file
1040
#                       --PostRm=file
1041
#                       --PreInst=file
1042
#                       --PostInst=file
6861 dpurdie 1043
#                       --SimpleSharedLibs
6859 dpurdie 1044
#                         
1045
#
1046
# Returns         : Nothing
1047
#
1048
sub MULTI_Files
1049
{
1050
    my $fName = shift;
6861 dpurdie 1051
    return 1 unless ($ActiveSection);
6859 dpurdie 1052
    Verbose ("Specify Installer Control Files and Scripts");
1053
    foreach  ( @_ )
1054
    {
1055
        if ( m/^--Control=(.+)/i ) {
1056
            MULTI_ControlFile($fName, 'control',$1)
1057
 
1058
        } elsif ( m/^--PreRm=(.+)/i ) {
1059
            MULTI_ControlFile($fName, 'prerm',$1)
1060
 
1061
        } elsif ( m/^--PostRm=(.+)/i ) {
1062
            MULTI_ControlFile($fName, 'postrm',$1)
1063
 
1064
        } elsif ( m/^--PreInst=(.+)/i ) {
1065
            MULTI_ControlFile($fName, 'preinst',$1)
1066
 
1067
        } elsif ( m/^--PostInst=(.+)/i ) {
1068
            MULTI_ControlFile($fName, 'postinst',$1)
1069
 
6861 dpurdie 1070
        } elsif ( m/^--SimpleSharedLibs/i ) {
1071
 
1072
            my $file = catfile($WorkDirBase, 'ldconfig.sh' );
1073
 
1074
            open (my $df, '>', $file) || Error ("$fName: Cannot create:$file");
1075
            print $df "#!/bin/sh\n";
1076
            print $df "/sbin/ldconfig\n";
1077
            print $df "exit 0\n";
1078
            close $df;
1079
 
1080
            MULTI_ControlFile($fName, 'postinst',$file);
1081
            MULTI_ControlFile($fName, 'postrm',$file);
1082
 
6859 dpurdie 1083
        } else {
1084
            Error ("$fName: Unknown option: $_");
1085
        }
1086
    }
1087
}
1088
 
1089
#-------------------------------------------------------------------------------
1090
# Function        : DebianControlFile
1091
#                   RpmControlFile 
6861 dpurdie 1092
#                   AllControlFile
6859 dpurdie 1093
#
1094
# Description     : Add special control files to the Debian/RedHat Installer 
1095
#                   Not useful for embedded installers
1096
#
1097
#                   More general than DebianFiles() or RpmFiles
1098
#
1099
# Inputs          : name            - Target Name
1100
#                                     If the name starts with 'package.' then it will be replaced
1101
#                                     with the name of the current package
1102
#                                     Ideally: prerm, postrm, preinst, postinst
1103
#                   file            - Source File Name
1104
#                   options         - Options include
1105
#                                       --FromPackage
1106
#
1107
# Returns         : 
1108
#
1109
sub MULTI_ControlFile
1110
{
1111
    my ($fName, $name, $file, @options) = @_;
6861 dpurdie 1112
    return 1 unless ($ActiveSection);
6859 dpurdie 1113
    my $fromPackage = 0;
1114
 
1115
    #
1116
    #   Process options
1117
    foreach ( @options)
1118
    {
1119
        if (m~^--FromPackage~) {
1120
            $fromPackage = 1;
1121
        }
1122
        else  {
1123
            ReportError(("$fName: Unknown argument: $_"));
1124
        }
1125
    }
1126
    ErrorDoExit();
1127
 
1128
    #
1129
    #   Some control files need to have the package name prepended
1130
    #
1131
    $name =~ s~^package\.~$opt_name.~;
1132
 
1133
    #
1134
    #   Only allow one file of each type
1135
    #       Try to protect the user by testing for names by lowercase
1136
    #
1137
    my $simpleName = lc($name);
1138
    Error("$fName: Multiple definitions for '$name' not allowed")
1139
        if (exists $ControlFileNames{$simpleName});
1140
 
1141
    my $filePath = ResolveFile($fromPackage, $file);
1142
 
1143
    #
1144
    #   Add info to data structures
1145
    #
1146
    $ControlFiles{$name} = $filePath;
1147
    $ControlFileNames{$simpleName} = $name;
1148
}
1149
 
1150
#-------------------------------------------------------------------------------
1151
# Function        : DebianDepends 
1152
#                   RpmDepends
6861 dpurdie 1153
#                   AllDepends
6859 dpurdie 1154
#
1155
# Description     : This directive allows simple dependency information to be  
1156
#                   inserted into the control file
6861 dpurdie 1157
#                   
1158
#                   Names will be massaged into conforming names.
6859 dpurdie 1159
#
1160
#                   Not useful in embedded system
1161
#
1162
# Inputs          : Entry             - A dependency entry
1163
#                   ...               - More entries
6861 dpurdie 1164
#                   Options
1165
#                       --Raw          - Prevent name modification
1166
#                       --NoRaw        - Enable name modification
6859 dpurdie 1167
#                   
1168
#
1169
# Returns         : Nothing
1170
#
1171
sub MULTI_Depends
1172
{
6861 dpurdie 1173
    return 1 unless ($ActiveSection);
6859 dpurdie 1174
    shift;
6861 dpurdie 1175
    my $raw = 0;
1176
 
1177
    #
1178
    #   Convert the provided name into a canonical name
1179
    #   Simplifies use when using both RPM and Debian
1180
    foreach ( @_)
1181
    {
1182
        if (m~^--(No)?Raw~i) {
1183
            $raw = ! defined($1);
1184
            next;
1185
        }
1186
        my $name = $_;
1187
        $name = canonicalName($_, $opt_rpm ? 'RPM' : 'DEBIAN' , 1) unless $raw;
1188
        push @DependencyList, $name;
1189
    }
1190
 
6859 dpurdie 1191
}
1192
 
1193
#-------------------------------------------------------------------------------
1194
# Function        : PackageDescription
1195
#
1196
# Description     : Specify the Package Description
1197
#                   Keep it short
1198
#
1199
# Inputs          : $description
1200
#
1201
# Returns         : 
1202
#
1203
sub PackageDescription
1204
{
6861 dpurdie 1205
    return 1 unless ($ActiveSection);
6859 dpurdie 1206
    ($opt_description) = @_;
1207
}
1208
 
1209
#-------------------------------------------------------------------------------
1210
# Function        : MakeSymLink
1211
#
1212
# Description     : Create a symlink - with error detection
1213
#
1214
# Inputs          : old_file    - Link Target
1215
#                                 Path to the link target
1216
#                                 If an ABS path is provided, the routine will
1217
#                                 attempt to create a relative link.
1218
#                   new_file    - Relative to the output work space
1219
#                                 Path to where the 'link' file will be created
1220
#                   Options     - Must be last
1221
#                                 --NoClean         - Don't play with links
1222
#                                 --NoDotDot        - Don't create symlinks with ..
1223
#
1224
# Returns         : Nothing
1225
#
1226
sub MakeSymLink
1227
{
1228
    my $no_clean;
1229
    my $no_dot;
1230
    my @args;
6861 dpurdie 1231
    return 1 unless ($ActiveSection);
6859 dpurdie 1232
 
1233
    #
1234
    #   Extract options
1235
    #
1236
    foreach ( @_ )
1237
    {
1238
        if ( m/^--NoClean/i ) {
1239
            $no_clean = 1;
1240
 
1241
        } elsif ( m/^--NoDotDot/i ) {
1242
            $no_dot = 1;
1243
 
1244
        } elsif ( m/^--/ ) {
1245
            Error ("MakeSymLink: Unknown option: $_");
1246
 
1247
        } else {
1248
            push @args, $_;
1249
        }
1250
    }
1251
 
1252
    my ($old_file, $new_file) = @args;
1253
 
1254
    my $tfile = $WorkDir . '/' . $new_file;
1255
    $tfile =~ s~//~/~;
1256
    Verbose ("Symlink $old_file -> $new_file" );
1257
 
1258
    #
1259
    #   Create the directory in which the link will be placed
1260
    #   Remove any existing file of the same name
1261
    #
1262
    my $dir = StripFileExt( $tfile );
1263
    mkpath( $dir) unless -d $dir;
1264
    unlink $tfile;
1265
 
1266
    #
1267
    #   Determine a good name of the link
1268
    #   Convert to a relative link in an attempt to prune them
1269
    #
1270
    my $sfile = $old_file;
1271
    unless ( $no_clean )
1272
    {
1273
        $sfile = CalcRelPath( StripFileExt( $new_file ), $old_file );
1274
        $sfile = $old_file if ( $no_dot && $sfile =~ m~^../~ );
1275
    }
1276
 
1277
    my $result = symlink $sfile, $tfile;
1278
    Error ("Cannot create symlink. $old_file -> $new_file") unless ( $result );
1279
}
1280
 
1281
#-------------------------------------------------------------------------------
1282
# Function        : CopyFile
1283
#
1284
# Description     : Copy a file to a target dir
1285
#                   Used for text files, or files with fixed names
1286
#
1287
# Inputs          : $src
1288
#                   $dst_dir    - Within the output workspace
1289
#                   $dst_name   - Output Name [Optional]
1290
#                   Options     - Common Copy Options
1291
#
1292
# Returns         : Full path to destination file
1293
#
1294
sub CopyFile
1295
{
6861 dpurdie 1296
    return 1 unless ($ActiveSection);
6859 dpurdie 1297
    CopyFileCommon( \&ResolveFile, @_ );
1298
}
1299
 
1300
#-------------------------------------------------------------------------------
1301
# Function        : CopyBinFile
1302
#
1303
# Description     : Copy a file to a target dir
1304
#                   Used for executable programs. Will look in places where
1305
#                   programs are stored.
1306
#
1307
# Inputs          : $src
1308
#                   $dst_dir    - Within the output workspace
1309
#                   $dst_name   - Output Name [Optional]
1310
#
1311
#                   Options:
1312
#                       --FromPackage
1313
#                       --SoftLink=xxxx
1314
#                       --LinkFile=xxxx
1315
#
1316
# Returns         : Full path to destination file
1317
#
1318
sub CopyBinFile
1319
{
6861 dpurdie 1320
    return 1 unless ($ActiveSection);
6859 dpurdie 1321
    CopyFileCommon( \&ResolveBinFile, @_ );
1322
}
1323
 
1324
#-------------------------------------------------------------------------------
1325
# Function        : CopyLibFile
1326
#
1327
# Description     : Copy a file to a target dir
1328
#                   Used for shared programs. Will look in places where
1329
#                   shared libraries are stored.
1330
#
1331
# Inputs          : $src        - Base for 'realname' (no lib, no extension)
1332
#                   $dst_dir    - Within the output workspace
1333
#                   $dst_name   - Output Name [Optional, but not suggested]
1334
#
1335
# Returns         : Full path to destination file
1336
#
1337
# Notes           : Copying 'lib' files
1338
#                   These are 'shared libaries. There is no provision for copying
1339
#                   static libraries.
1340
#
1341
#                   The tool will attempt to copy a well-formed 'realname' library
1342
#                   The soname of the library should be constructed on the target
1343
#                   platform using ldconfig.
1344
#                   There is no provision to copy the 'linker' name
1345
#
1346
#                   Given a request to copy a library called 'fred', then the
1347
#                   well formed 'realname' will be:
1348
#                           libfred[P|D|]].so.nnnnn
1349
#                   where:
1350
#                           nnnn is the library version
1351
#                           [P|D|] indicates Production, Debug or None
1352
#
1353
#                   The 'soname' is held within the realname form of the library
1354
#                   and will be created by lsconfig.
1355
#
1356
#                   The 'linkername' would be libfred[P|D|].so. This is only
1357
#                   needed when linking against the library.
1358
#
1359
#
1360
#                   The routine will also recognize Windows DLLs
1361
#                   These are of the form fred[P|D|].nnnnn.dll
1362
#
1363
sub CopyLibFile
1364
{
6861 dpurdie 1365
    return 1 unless ($ActiveSection);
6859 dpurdie 1366
    CopyFileCommon( \&ResolveLibFile, @_ );
1367
}
1368
 
1369
#-------------------------------------------------------------------------------
1370
# Function        : CopyDebianPackage
1371
#
1372
# Description     : Copy a Debian Package to a target dir
1373
#                   Will look in places where Debian Packages are stored.
1374
#
1375
# Inputs          : $src        - BaseName for 'Debian Package' (no version, no extension)
1376
#                   $dst_dir    - Within the output workspace
1377
#                   Optional arguments embedded into the BaseName
1378
#                   --Arch=XXXX         - Architecture - if not current
1379
#                   --Product=XXXX      - Product - if required
1380
#                   --Debug             - If not the current type
1381
#                   --Prod              - If not the current type
1382
#
1383
# Returns         : Full path to destination file
1384
#
1385
# Notes           : Copying Debian Packages from external packages
1386
#
1387
#                   The tool will attempt to copy a well-formed debian packages
1388
#                   These are:
1389
#                   
1390
#                       "BaseName_VersionString[_Product]_Arch${PkgType}.deb";
1391
#                   
1392
#                   Where 'Product' is optional (and rare)
1393
#                   Where 'PkgType' is P or D or nothing
1394
#                   Where 'Arch' may be 'all'
1395
#                   
1396
#                   The routine will locate Debian packages in
1397
#                       - The root of the package
1398
#                       - bin/TARGET[P|D/]
1399
#                       - bin/Arch[P|D]
1400
#
1401
#
1402
sub CopyDebianPackage
1403
{
6861 dpurdie 1404
    return 1 unless ($ActiveSection);
6859 dpurdie 1405
    CopyFileCommon( \&ResolveDebPackage, '--FromPackage', @_ );
1406
}
1407
 
1408
#-------------------------------------------------------------------------------
1409
# Function        : CopyFileCommon
1410
#
1411
# Description     : Common ( internal File Copy )
1412
#
1413
# Inputs          : $resolver           - Ref to function to resolve source file
1414
#                   $src                - Source File Name
1415
#                   $dst_dir            - Target Dir
1416
#                   $dst_name           - Target Name (optional)
1417
#                   Options
1418
#                   Options:
1419
#                       --FromPackage
1420
#                       --FromBuild
1421
#                       --SoftLink=xxxx
1422
#                       --LinkFile=xxxx
1423
#                       --ConfFile
6861 dpurdie 1424
#                       --Platform=xxxx[,yyyyy]
6859 dpurdie 1425
#
1426
# Returns         : 
1427
#
1428
sub CopyFileCommon
1429
{
1430
    my $from_package = 0;
1431
    my $isa_linkfile = 0;
1432
    my $isa_configFile = 0;
1433
    my @llist;
1434
    my @args;
6861 dpurdie 1435
    my @platforms;
6859 dpurdie 1436
 
1437
    #
1438
    #   Parse options
1439
    #
1440
    foreach ( @_ )
1441
    {
1442
        if ( m/^--FromPackage/ ) {
1443
            $from_package = 1;
1444
 
1445
        } elsif ( m/^--FromBuild/ ) {
1446
            $from_package = 0;
1447
 
1448
        } elsif ( m/^--LinkFile/ ) {
1449
            $isa_linkfile = 1;
1450
 
1451
        } elsif ( m/^--ConfFile/i ) {
1452
            $isa_configFile = 1;
1453
 
1454
        } elsif ( m/^--SoftLink=(.+)/ ) {
1455
            push @llist, $1;
1456
 
6861 dpurdie 1457
        } elsif ( m/^--Platform=(.+)/ ) {
1458
            push @platforms, split(',', $1 );
1459
 
6859 dpurdie 1460
        } elsif ( m/^--/ ) {
1461
            Error ("FileCopy: Unknown option: $_");
1462
 
1463
        } else {
1464
            push @args, $_;
1465
        }
1466
    }
1467
 
1468
    #
1469
    #   Extract non-options.
1470
    #   These are the bits that are left over
1471
    #
1472
    my ($resolver, $src, $dst_dir, $dst_name ) = @args;
1473
 
1474
    #
1475
    #   Clean up dest_dir. Must start with a / and not end with one
1476
    #
1477
    $dst_dir = "/$dst_dir/";
1478
    $dst_dir =~ s~/+~/~g;
1479
    $dst_dir =~ s~/$~~;
1480
 
1481
    Verbose ("CopyFile: $src, $dst_dir, " . ($dst_name || ''));
6861 dpurdie 1482
    foreach $src ( &$resolver( $from_package, $src, \@platforms ) )
6859 dpurdie 1483
    {
1484
        my $dst_fname = $dst_name ? $dst_name : StripDir($src);
1485
        my $dst_file = "$dst_dir/$dst_fname";
1486
        Verbose ("CopyFile: Copy $src, $dst_file" );
1487
 
1488
 
1489
        #
1490
        #   LinkFiles are special
1491
        #   They get concatenated to any existing LINKS File
1492
        #
1493
        if ( $isa_linkfile )
1494
        {
1495
            CatFile ( $src, "$dst_dir/.LINKS" );
1496
        }
1497
        else
1498
        {
1499
            mkpath( "$WorkDir$dst_dir", 0, 0775);
1500
            unlink ("$WorkDir$dst_file");
1501
            System ('cp','-f', $src, "$WorkDir$dst_file" );
1502
 
1503
            foreach my $lname ( @llist )
1504
            {
1505
                $lname = $dst_dir . '/' . $lname unless ( $lname =~ m ~^/~ );
1506
                MakeSymLink( $dst_file ,$lname);
1507
            }
1508
        }
1509
 
1510
        #
1511
        #   ConfigFiles are marked so that they can be handled by the debain installer
1512
        #
1513
        if ($isa_configFile)
1514
        {
1515
            push @ConfigList, $WorkSubDir . $dst_file;
1516
        }
1517
    }
1518
}
1519
 
1520
#-------------------------------------------------------------------------------
1521
# Function        : CopyDir
1522
#
1523
# Description     : Copy a directory to a target dir
1524
#
1525
# Inputs          : $src_dir    - Local to the user
1526
#                                 Symbolic Name
1527
#                   $dst_dir    - Within the output workspace
1528
#                   Options
1529
#                       --Merge                 - Don't delete first
1530
#                       --Source=Name           - Source via Symbolic Name
1531
#                       --FromPackage           - Source via package roots
1532
#                       --NoIgnoreDbgFiles      - Do not ignore .dbg and .debug files in dir copy
1533
#                       --IfPresent             - Not an error if the path cannot be found
1534
#                       --ConfFile              - Mark transferred files as config files
1535
#                       --Flatten               - Copy all to one directory
1536
#                       --FilterOut=xxx         - Ignore files. DOS Wildcard
1537
#                       --FilterOutRe=xxx       - Ignore files. Regular expression name
1538
#                       --FilterOutDir=xxx      - Ignore directories. DOS Wilcard
1539
#                       --FilterOutDirRe=xxx    - Ignore directories. Regular expression name
1540
#                       --SkipTLF               - Ignore files in the Top Level Directory
1541
#                       --NoRecurse             - Only process files in the Top Level Directory
1542
#                       --FilterIn=xxx          - Include files. DOS Wildcard
1543
#                       --FilterInRe=xxx        - Include files. Regular expression name
1544
#                       --FilterInDir=xxx       - Include directories. DOS Wilcard
1545
#                       --FilterInDirRe=xxx     - Include directories. Regular expression name
1546
#
1547
# Returns         :
1548
#
1549
sub CopyDir
1550
{
1551
    my ($src_dir, $dst_dir, @opts) = @_;
1552
    my $opt_base;
1553
    my $from_interface = 0;
1554
    my $ignoreDbg = 1;
1555
    my $ignoreNoDir;
1556
    my $user_src_dir = $src_dir;
1557
    my $opt_source;
1558
    my $opt_package;
1559
    my @fileList;
1560
    my $isFiltered;
6861 dpurdie 1561
    return 1 unless ($ActiveSection);
6859 dpurdie 1562
 
1563
    #
1564
    #   Setup the basic copy options
1565
    #       May be altered as we parse user options
1566
    #
1567
    my %copyOpts;
1568
    $copyOpts{'IgnoreDirs'} = ['.svn', '.git', '.cvs', '.hg'];
1569
    $copyOpts{'Ignore'} = ['.gbedir', '_gbedir'];
1570
    $copyOpts{'Log'} = 1 if ( $opt_verbose > 1 );
1571
    $copyOpts{'DeleteFirst'} = 1;
1572
 
1573
    $dst_dir = $WorkDir . '/' . $dst_dir;
1574
    $dst_dir =~ s~//~/~;
1575
 
1576
    #
1577
    #   Scan and collect user options
1578
    #
1579
    foreach  ( @opts )
1580
    {
1581
        Verbose2 ("CopyDir: $_");
1582
        if ( m/^--Merge/ ) {
1583
            $copyOpts{'DeleteFirst'} = 0;
1584
 
1585
        } elsif ( m/^--Source=(.+)/ ) {
1586
            Error ("Source directory can only be specified once")
1587
                if ( defined $opt_source );
1588
            $opt_source = $1;
1589
 
1590
        } elsif ( m/^--FromPackage/ ) {
1591
            Error ("FromPackage can only be specified once")
1592
                if ( defined $opt_package );
1593
            $opt_package = 1;
1594
 
1595
        } elsif ( m/^--NoIgnoreDbgFiles/ ) {
1596
            $ignoreDbg = 0;
1597
 
1598
        } elsif ( m/^--IfPresent/ ) {
1599
            $ignoreNoDir = 1;
1600
 
1601
        } elsif ( m/^--ConfFile/i ) {
1602
            $copyOpts{'FileList'} = \@fileList;
1603
 
1604
        } elsif ( m/^--Flatten/i ) {
1605
            $copyOpts{'Flatten'} = 1;
1606
 
1607
        } elsif ( m/^--FilterOut=(.+)/i ) {
1608
            push (@{$copyOpts{'Ignore'}}, $1);
1609
            $isFiltered = 1;
1610
 
1611
        } elsif ( m/^--FilterOutRe=(.+)/i ) {
1612
            push (@{$copyOpts{'IgnoreRE'}}, $1);
1613
            $isFiltered = 1;
1614
 
1615
        } elsif ( m/^--FilterOutDir=(.+)/i ) {
1616
            push (@{$copyOpts{'IgnoreDirs'}}, $1);
1617
            $isFiltered = 1;
1618
 
1619
        } elsif ( m/^--FilterOutDirRe=(.+)/i ) {
1620
            push (@{$copyOpts{'IgnoreDirsRE'}}, $1);
1621
            $isFiltered = 1;
1622
 
1623
        } elsif ( m/^--FilterIn=(.+)/i ) {
1624
            push (@{$copyOpts{'Match'}}, $1);
1625
            $isFiltered = 1;
1626
 
1627
        } elsif ( m/^--FilterInRe=(.+)/i ) {
1628
            push (@{$copyOpts{'MatchRE'}}, $1);
1629
            $isFiltered = 1;
1630
 
1631
        } elsif ( m/^--FilterInDir=(.+)/i ) {
1632
            push (@{$copyOpts{'MatchDirs'}}, $1);
1633
            $isFiltered = 1;
1634
 
1635
        } elsif ( m/^--FilterInDirRe=(.+)/i ) {
1636
            push (@{$copyOpts{'MatchDirsRE'}}, $1);
1637
            $isFiltered = 1;
1638
 
1639
        } elsif ( m/^--SkipTLF$/i ) {
1640
            $copyOpts{'SkipTLF'} = 1;
1641
 
1642
        } elsif ( m/^--NoRecurse$/i ) {
1643
            $copyOpts{'NoSubDirs'} = 1;
1644
 
1645
        } else {
1646
            Error ("CopyDir: Unknown option: $_" );
1647
        }
1648
    }
1649
 
1650
    #
1651
    #   All options have been gathered. Now process some of them
1652
    #
1653
    Error ("CopyDir: Cannot use both --Source and --FromPackage: $src_dir") if ($opt_source && $opt_package);
1654
 
1655
    #
1656
    #   Convert a symbolic path into a physical path
1657
    #
1658
    if ($opt_source)
1659
    {
1660
        Verbose2 ("CopyDir: Determine Source: $opt_source");
1661
 
1662
        $opt_source = lc($opt_source);
1663
        my %CopyDirSymbolic = (
1664
            'interfaceincdir'   => $opt_interfaceincdir,
1665
            'interfacelibdir'   => $opt_interfacelibdir,
1666
            'interfacebindir'   => $opt_interfacebindir,
1667
            'libdir'            => $opt_libdir,
1668
            'bindir'            => $opt_bindir,
1669
            'localincdir'       => $opt_localincdir,
1670
            'locallibdir'       => $opt_locallibdir,
1671
            'localbindir'       => $opt_localbindir,
1672
            'packagebindir'     => $opt_pkgbindir,
1673
            'packagelibdir'     => $opt_pkglibdir,
1674
            'packagepkgdir'     => $opt_pkgpkgdir,
1675
            'packagedir'        => $opt_pkgdir,
1676
        );
1677
 
1678
        if ( exists $CopyDirSymbolic{$opt_source} )
1679
        {
1680
            $opt_base = $CopyDirSymbolic{$opt_source};
1681
 
1682
            #
1683
            #   If sourceing from interface, then follow
1684
            #   symlinks in the copy. All files will be links anyway
1685
            #
1686
            $from_interface = 1
1687
                if ( $opt_source =~ m~^interface~ );
1688
        }
1689
        else
1690
        {
1691
            DebugDumpData ("CopyDirSymbolic", \%CopyDirSymbolic);
1692
            Error ("CopyDir: Unknown Source Name: $opt_source" );
1693
        }
1694
    }
1695
 
1696
    #
1697
    #   Locate the path within an external package
1698
    #
1699
    if ($opt_package)
1700
    {
1701
        Verbose2 ("CopyDir: FromPackage: $src_dir");
1702
 
1703
        my @path;
1704
        foreach my $entry ( getPackageList() )
1705
        {
1706
            my $base = $entry->getBase(3);
1707
            next unless ( defined $base );
1708
            if ( -d $base . '/' . $src_dir )
1709
            {
1710
                push @path, $base;
1711
                $from_interface = 1
1712
                    if ( $entry->{'TYPE'} eq 'interface' );
1713
            }
1714
        }
1715
 
1716
        if ( $#path < 0 )
1717
        {
1718
            Error ("CopyDir: Cannot find source dir in any package: $user_src_dir") unless ($ignoreNoDir);
1719
            Message ("CopyDir: Optional path not found: $user_src_dir");
1720
            return;
1721
        }
1722
 
1723
        Error ("CopyDir: Requested path found in mutiple packages: $user_src_dir",
1724
                @path ) if ( $#path > 0 );
1725
        $opt_base = pop @path;
1726
 
1727
        #
1728
        #   If sourceing from interface, then follow symlinks in the copy.
1729
        #   All files will be links anyway
1730
        #
1731
        #   This is a very ugly test for 'interface'
1732
        #
1733
        $from_interface = 1
1734
            if ( $opt_base =~ m~/interface/~ );
1735
 
1736
    }
1737
 
1738
    #
1739
    #   Create the full source path
1740
    #   May be: from a package, from a known directory, from a local directory
1741
    #
1742
 
1743
    $src_dir = $opt_base . '/' . $src_dir if ( $opt_base );
1744
    $src_dir =~ s~//~/~g;
1745
    $src_dir =~ s~/$~~;
1746
 
1747
    Verbose ("CopyDir: $src_dir, $dst_dir");
1748
    unless ( -d $src_dir )
1749
    {
1750
        Error ("CopyDir: Directory not found: $user_src_dir") unless ($ignoreNoDir);
1751
        Message ("CopyDir: Optional path not found: $user_src_dir");
1752
        return;
1753
    }
1754
 
1755
    #
1756
    #   Continue to configure the copy options
1757
    #
1758
    push (@{$copyOpts{'Ignore'}}, '*.debug', '*.dbg') if $ignoreDbg;
1759
    $copyOpts{'DuplicateLinks'} = 1 unless ( $from_interface );
1760
    $copyOpts{'EmptyDirs'} = 1 unless ($isFiltered);
1761
 
1762
    #
1763
    #   Transfer the directory
1764
    #
1765
    JatsCopy::CopyDir ( $src_dir, $dst_dir, \%copyOpts );
1766
 
1767
    #
1768
    #   If requested, mark files as config files
1769
    #   Must remove the DebianWorkDir prefix
1770
    #
1771
    if(@fileList)
1772
    {
1773
        Verbose ("Mark all transfered files as ConfFiles");
1774
        my $removePrefix = length ($WorkDir);
1775
        foreach my $file (@fileList)
1776
        {
1777
            push @ConfigList, substr($file, $removePrefix);
1778
        }
1779
    }
1780
 
1781
    #
1782
    #   Expand link files that may have been copied in
1783
    #
1784
    Verbose ("Locate LINKFILES in $WorkDir");
1785
    ExpandLinkFiles();
1786
}
1787
 
1788
#-------------------------------------------------------------------------------
1789
# Function        : AddInitScript
1790
#
1791
# Description     : Add an Init Script to the target
1792
#                   Optionally create start and stop links
1793
#
1794
# Inputs          : $script     - Name of the init script
1795
#                   $start      - Start Number
1796
#                   $stop       - Stop Number
1797
#                   Options:
1798
#                       --NoCopy        - Don't copy the script, just add links
1799
#                       --Afc           - Place in AFC init area
1800
#                       --FromPackage   - Source is in a package
1801
#
1802
# Returns         : 
1803
#
1804
sub AddInitScript
1805
{
1806
    my $no_copy;
1807
    my $basedir = "";
1808
    my @args;
1809
    my $from_package = 0;
6861 dpurdie 1810
    return 1 unless ($ActiveSection);
6859 dpurdie 1811
 
1812
    # This directive is only available on the VIX platforms
1813
    #   Kludgey test - at the moment
1814
    #
1815
    if ($opt_pkgarch =~ m~i386~)
1816
    {
1817
        Error ("AddInitScript is not supported on this platform"); 
1818
    }
1819
 
1820
    #
1821
    #   Process and Remove options
1822
    #
1823
    foreach  ( @_ )
1824
    {
1825
        if ( m/^--NoCopy/ ) {
1826
            $no_copy = 1;
1827
 
1828
        } elsif ( m/^--Afc/ ) {
1829
            $basedir = "/afc";
1830
 
1831
        } elsif ( m/^--FromPackage/ ) {
1832
            $from_package = 1;
1833
 
1834
        } elsif ( m/^--/ ) {
1835
            Error ("AddInitScript: Unknown option: $_");
1836
 
1837
        } else {
1838
            push @args, $_;
1839
 
1840
        }
1841
    }
1842
 
1843
    my( $script, $start, $stop ) = @args;
1844
    Error ("No script file specified") unless ( $script );
1845
    Warning("AddInitScript: No start or stop index specified") unless ( $start || $stop );
1846
    Verbose ("AddInitScript: $script, " . ($start || 'No Start') . ", " . ($stop || 'No Stop'));
1847
    $script = ResolveFile($from_package, $script );
1848
 
1849
    my $tdir = $basedir . "/etc/init.d/init.d";
1850
    my $base = StripDir($script);
1851
 
1852
    CopyFile( $script, $tdir ) unless $no_copy;
1853
 
1854
    my $link;
1855
    if ( $start )
1856
    {
1857
        $link = sprintf ("${basedir}/etc/init.d/S%2.2d%s", $start, $base );
1858
        MakeSymLink( "$tdir/$base", $link);
1859
    }
1860
 
1861
    if ( $stop )
1862
    {
1863
        $link = sprintf ("${basedir}/etc/init.d/K%2.2d%s", $stop, $base );
1864
        MakeSymLink( "$tdir/$base", $link);
1865
    }
1866
}
1867
 
1868
#-------------------------------------------------------------------------------
1869
# Function        : CatFile
1870
#
1871
# Description     : Copy a file to the end of a file
1872
#
1873
# Inputs          : $src
1874
#                   $dst    - Within the output workspace
1875
#
1876
# Returns         :
1877
#
1878
sub CatFile
1879
{
1880
    my ($src, $dst) = @_;
6861 dpurdie 1881
    return 1 unless ($ActiveSection);
6859 dpurdie 1882
 
1883
    $dst = $WorkDir . '/' . $dst;
1884
    $dst =~ s~//~/~;
1885
    Verbose ("CatFile: $src, $dst");
1886
    $src = ResolveFile(0, $src );
1887
 
1888
    open (SF, '<', $src)  || Error ("CatFile: Cannot open $src");
1889
    open (DF, '>>', $dst) || Error ("CatFile: Cannot create:$dst");
1890
    while ( <SF> )
1891
    {
1892
        print DF $_;
1893
    }
1894
    close (SF);
1895
    close (DF);
1896
}
1897
 
1898
#-------------------------------------------------------------------------------
1899
# Function        : EchoFile
1900
#
1901
# Description     : Echo simple text to a file
1902
#
1903
# Inputs          : $file   - Within the output workspace
1904
#                   $text
1905
#
1906
# Returns         : 
1907
#
1908
sub EchoFile
1909
{
1910
    my ($file, $text) = @_;
6861 dpurdie 1911
    return 1 unless ($ActiveSection);
6859 dpurdie 1912
    Verbose ("EchoFile: $file");
1913
 
1914
    $file = $WorkDir . '/' . $file;
1915
    $file =~ s~//~/~;
1916
 
1917
    unlink $file;
1918
    open (DT, ">", $file ) || Error ("Cannot create $file");
1919
    print DT  $text || Error ("Cannot print to $file");
1920
    close DT;
1921
}
1922
 
1923
#-------------------------------------------------------------------------------
1924
# Function        : ConvertFiles
1925
#
1926
# Description     : This sub-routine is used to remove all carrage return\line
1927
#                   feeds from a line and replace them with the platform
1928
#                   specific equivalent chars.
1929
#
1930
#                   We let PERL determine what characters are written to the
1931
#                   file base on the  platform you are running on.
1932
#
1933
#                   i.e. LF    for unix
1934
#                        CR\LF for win32
1935
#
1936
# Inputs          : outPath                 - Output directory
1937
#                   flist                   - List of files in that directory
1938
#                   or
1939
#                   SearchOptions           - Search options to find files
1940
#                                           --Recurse
1941
#                                           --NoRecurse
1942
#                                           --FilterIn=xxx
1943
#                                           --FilterInRe=xxx
1944
#                                           --FilterOut=xxx
1945
#                                           --FilterOutRe=xxx
1946
#                   Common options
1947
#                                           --Dos
1948
#                                           --Unix
1949
#
1950
#
1951
# Returns         : 1
1952
#
1953
sub ConvertFiles
1954
{
1955
    my @uargs;
6861 dpurdie 1956
    return 1 unless ($ActiveSection);
6859 dpurdie 1957
    my $lineEnding = "\n";
1958
    my ($dosSet, $unixSet);
1959
    my $search =  JatsLocateFiles->new( '--NoRecurse' );
1960
 
1961
    #
1962
    #   Process user arguments extracting options
1963
    #
1964
    foreach  ( @_ )
1965
    {
1966
        if ( m~^--Recurse~ ) {
1967
            $search->recurse(1);
1968
 
1969
        } elsif ( m~^--NoRecurse~) {
1970
            $search->recurse(0);
1971
 
1972
        } elsif ( /^--FilterOut=(.*)/ ) {
1973
            $search->filter_out($1);
1974
 
1975
        } elsif ( /^--FilterOutRe=(.*)/ ) {
1976
            $search->filter_out_re($1);
1977
 
1978
        } elsif ( /^--FilterIn=(.*)/ ) {
1979
            $search->filter_in($1);
1980
 
1981
        } elsif ( /^--FilterInRe=(.*)/ ) {
1982
            $search->filter_in_re($1);
1983
 
1984
        } elsif ( m~^--Dos~) {
1985
            $lineEnding = "\r\n";
1986
            $dosSet = 1;
1987
 
1988
        } elsif ( m~^--Unix~) {
1989
            $lineEnding = "\n";
1990
            $unixSet = 1;
1991
 
1992
        } elsif ( m~^--~) {
1993
            Error ("ConvertFiles: Unknown option: $_");
1994
 
1995
        } else {
1996
            push @uargs, $_;
1997
        }
1998
    }
1999
 
2000
    #
2001
    #   Process non-option arguments
2002
    #       - Base dir
2003
    #       - List of files
2004
    #
2005
    my ($outPath, @flist) = @uargs;
2006
    Error ("ConvertFiles: Target Dir must be specified" ) unless ( $outPath );
2007
 
2008
    #
2009
    #   Sanity Tests
2010
    #
2011
    Error ("ConvertFiles: --Dos and --Unix are mutually exclusive" ) if ( $dosSet && $unixSet );
2012
 
2013
 
2014
    #
2015
    # Convert output path to physical path
2016
    #
2017
    my $topDir = catdir($WorkDir, $outPath);
2018
    Verbose("ConvertFiles: topDir: $topDir");
2019
    Error ("ConvertFiles: Path does not exist", $topDir) unless ( -e $topDir );
2020
    Error ("ConvertFiles: Path is not a directory", $topDir) unless ( -d $topDir );
2021
 
2022
    #
2023
    #   Need to determine if we are searching or simply using a file list
2024
    #   There are two forms of the functions. If any of the search options have
2025
    #   been used then we assume that we are searchine
2026
    #
2027
    if ( $search->has_filter() )
2028
    {
2029
        Error ("ConvertFiles: Cannot mix search options with named files") if ( @flist );
2030
        @flist = $search->search($topDir);
2031
    }
2032
    Error ("ConvertFiles: No files specified") unless ( @flist );
2033
 
2034
    #
2035
    #   Process all named files
2036
    #
2037
    foreach my $file ( @flist )
2038
    {
2039
 
2040
        # this is our file that we want to clean.
2041
        my ($ifileLoc) = "$topDir/$file";
2042
        my ($tfileLoc) = "$topDir/$file\.tmp";
2043
        Verbose("ConvertFiles: $file");
2044
 
2045
        # we will check to see if the file exists.
2046
        #
2047
        my $ifile;
2048
        my $tfile;
2049
        if ( -f "$ifileLoc" )
2050
        {
2051
            open ($ifile, "< $ifileLoc" ) or
2052
                Error("Failed to open file [$ifileLoc] : $!");
2053
 
2054
            open ($tfile, "> $tfileLoc" ) or
2055
                Error("Failed to open file [$tfileLoc] : $!");
2056
            binmode $tfile;
2057
 
2058
            while ( <$ifile> ) 
2059
            {
2060
                s~[\n\r]+$~~;               # Chomp
2061
                print $tfile "$_" . $lineEnding;
2062
            }
2063
        }
2064
        else
2065
        {
2066
            Error("ConvertFiles [$ifileLoc] does not exist.");
2067
        }
2068
 
2069
        close $ifile;
2070
        close $tfile;
2071
 
2072
 
2073
        # lets replace our original file with the new one
2074
        #
2075
        if(File::Copy::move("$tfileLoc", "$ifileLoc"))
2076
        {
2077
            Verbose2("ConvertFiles: Renamed [$tfileLoc] to [$ifileLoc] ...");
2078
        }
2079
        else
2080
        {
2081
            Error("ConvertFiles: Failed to rename file [$tfileLoc] to [$ifileLoc]: $!");
2082
        }
2083
    }
2084
 
2085
    return 1;
2086
}
2087
 
2088
#----------------------------------------------------------------------------
2089
# Function        : ReplaceTags
2090
#
2091
# Description     : This sub-routine is used to replace Tags in one or more files
2092
#
2093
# Inputs          : outPath                 - Output directory
2094
#                   flist                   - List of files in that directory
2095
#                   or
2096
#                   SearchOptions           - Search options to find files
2097
#                                           --Recurse
2098
#                                           --NoRecurse
2099
#                                           --FilterIn=xxx
2100
#                                           --FilterInRe=xxx
2101
#                                           --FilterOut=xxx
2102
#                                           --FilterOutRe=xxx
2103
#                   Common options
2104
#                                           --Tag=Tag,Replace
2105
#                                           
2106
#
2107
# Returns         : 1
2108
#
2109
sub ReplaceTags
2110
{
6861 dpurdie 2111
    return 1 unless ($ActiveSection);
6859 dpurdie 2112
    my @uargs;
2113
    my $search =  JatsLocateFiles->new( '--NoRecurse' );
2114
    my @tagsList;
2115
    my $tagSep = ',';
2116
    my @tagOrder;
2117
    my %tagData;
2118
 
2119
    #
2120
    #   Process user arguments extracting options
2121
    #
2122
    foreach  ( @_ )
2123
    {
2124
        if ( m~^--Recurse~ ) {
2125
            $search->recurse(1);
2126
 
2127
        } elsif ( m~^--NoRecurse~) {
2128
            $search->recurse(0);
2129
 
2130
        } elsif ( /^--FilterOut=(.*)/ ) {
2131
            $search->filter_out($1);
2132
 
2133
        } elsif ( /^--FilterOutRe=(.*)/ ) {
2134
            $search->filter_out_re($1);
2135
 
2136
        } elsif ( /^--FilterIn=(.*)/ ) {
2137
            $search->filter_in($1);
2138
 
2139
        } elsif ( /^--FilterInRe=(.*)/ ) {
2140
            $search->filter_in_re($1);
2141
 
2142
        } elsif ( m~^--Tag=(.*)~) {
2143
            push @tagsList, $1;
2144
 
2145
        } elsif ( m~^--~) {
2146
            Error ("ReplaceTags: Unknown option: $_");
2147
 
2148
        } else {
2149
            push @uargs, $_;
2150
        }
2151
    }
2152
 
2153
    #
2154
    #   Process non-option arguments
2155
    #       - Base dir
2156
    #       - List of files
2157
    #
2158
    my ($outPath, @flist) = @uargs;
2159
    Error ("ReplaceTags: Target Dir must be specified" ) unless ( $outPath );
2160
 
2161
    #
2162
    #   Sanity Tests
2163
    #
2164
    Error ("ReplaceTags: No tags specified" ) unless ( @tagsList );
2165
 
2166
    #
2167
    # Convert output path to physical path
2168
    #
2169
    my $topDir = catdir($WorkDir, $outPath);
2170
    Verbose("ReplaceTags: topDir: $topDir");
2171
    Error ("ReplaceTags: Path does not exist", $topDir) unless ( -e $topDir );
2172
    Error ("ReplaceTags: Path is not a directory", $topDir) unless ( -d $topDir );
2173
 
2174
    #
2175
    #   Convert Tags into pairs for latter use
2176
    #
2177
    my $sep = quotemeta ($tagSep );
2178
    foreach my $tag ( @tagsList )
2179
    {
2180
        my ($tname,$tvalue) = split ( $sep, $tag, 2 );
2181
        Error ("No tag value in: $tag" ) unless ( defined $tvalue );
2182
        Error ("Duplicate Tag: $tname" ) if ( exists $tagData{$tname} );
2183
        Verbose ("Tag: $tname :: $tvalue");
2184
        push @tagOrder, $tname;
2185
        $tagData{$tname} = $tvalue;
2186
    }
2187
 
2188
    #
2189
    #   Need to determine if we are searching or simply using a file list
2190
    #   There are two forms of the functions. If any of the search options have
2191
    #   been used then we assume that we are searchine
2192
    #
2193
    if ( $search->has_filter() )
2194
    {
2195
        Error ("ReplaceTags: Cannot mix search options with named files") if ( @flist );
2196
        @flist = $search->search($topDir);
2197
    }
2198
    Error ("ReplaceTags: No files specified") unless ( @flist );
2199
 
2200
    #
2201
    #   Process all named files
2202
    #
2203
    foreach my $file ( @flist )
2204
    {
2205
 
2206
        # this is our file that we want to clean.
2207
        my ($ifileLoc) = "$topDir/$file";
2208
        my ($tfileLoc) = "$topDir/$file\.tmp";
2209
        Verbose("ReplaceTags: $file");
2210
 
2211
        # we will check to see if the file exists.
2212
        #
2213
        my $ifile;
2214
        my $tfile;
2215
        if ( -f "$ifileLoc" )
2216
        {
2217
            open ($ifile, "< $ifileLoc" ) or
2218
                Error("Failed to open file [$ifileLoc] : $!");
2219
 
2220
            open ($tfile, "> $tfileLoc" ) or
2221
                Error("Failed to open file [$tfileLoc] : $!");
2222
 
2223
            while ( <$ifile> ) 
2224
            {
2225
                s~[\n\r]+$~~;               # Chomp
2226
 
2227
                #
2228
                #   Perform tag replacement
2229
                #
2230
                foreach my $tag ( @tagOrder )
2231
                {
2232
                    my $value = $tagData{$tag};
2233
                    if ( s~$tag~$value~g )
2234
                    {
2235
                        Verbose2("Replaced: $tag with $value");
2236
                    }
2237
                }
2238
 
2239
                print $tfile "$_\n";
2240
            }
2241
        }
2242
        else
2243
        {
2244
            Error("ReplaceTags [$ifileLoc] does not exist.");
2245
        }
2246
 
2247
        close $ifile;
2248
        close $tfile;
2249
 
2250
 
2251
        # lets replace our original file with the new one
2252
        #
2253
        if(File::Copy::move("$tfileLoc", "$ifileLoc"))
2254
        {
2255
            Verbose2("ReplaceTags: Renamed [$tfileLoc] to [$ifileLoc] ...");
2256
        }
2257
        else
2258
        {
2259
            Error("ReplaceTags: Failed to rename file [$tfileLoc] to [$ifileLoc]: $!");
2260
        }
2261
    }
2262
 
2263
    return 1;
2264
}
2265
 
2266
#-------------------------------------------------------------------------------
2267
# Function        : SetFilePerms
2268
#
2269
# Description     : Set file permissions on one or more files or directories
2270
#                   Use SetPermissions
2271
#
2272
# Inputs          : $perm           - Perm Mask
2273
#                   @paths          - List of paths/files to process
2274
#                   Options
2275
#                       --Recurse   - Recurse subdirs
2276
#
2277
# Returns         : 
2278
#
2279
sub SetFilePerms
2280
{
2281
 
6861 dpurdie 2282
    return 1 unless ($ActiveSection);
6859 dpurdie 2283
    my @args;
2284
    my $perms;
2285
    my $recurse = 0;
2286
 
2287
    #
2288
    #   Process and Remove options
2289
    #
2290
    foreach  ( @_ )
2291
    {
2292
        if ( m/^--Recurse/ ) {
2293
            $recurse = 1;
2294
 
2295
        } elsif ( m/^--/ ) {
2296
            Error ("SetFilePerms: Unknown option: $_");
2297
 
2298
        } else {
2299
            push @args, $_;
2300
 
2301
        }
2302
    }
2303
 
2304
    $perms = shift @args;
2305
    Error ("SetFilePerms: No Permissions" ) unless ( $perms );
2306
 
2307
    foreach my $path ( @args )
2308
    {
2309
        Verbose ("Set permissions; $perms, $path");
2310
        my $full_path = $WorkDir . '/' . $path;
2311
        if ( -f $full_path )
2312
        {
2313
            System ('chmod', $perms, $full_path );
2314
        }
2315
        elsif ( -d $full_path )
2316
        {
2317
            System ('chmod', '-R', $perms, $full_path ) if ($recurse);
2318
            System ('chmod', $perms, $full_path ) unless ($recurse);
2319
        }
2320
        else
2321
        {
2322
            Warning("SetFilePerms: Path not found: $path");
2323
        }
2324
    }
2325
    return 1;
2326
}
2327
 
2328
#-------------------------------------------------------------------------------
2329
# Function        : SetPermissions 
2330
#
2331
# Description     : Called to set permissions of files/dirs in a directory structure.
2332
#                   With no options sets DirTag and all files/dirs in it to perms
2333
#   
2334
# Inputs          : path        - The directory tag to start setting permissions on
2335
#                   Options     - See below
2336
#       
2337
#   Required Options:
2338
#       One or both of
2339
#               --FilePerms=    Sets the permissions of files to this permission.
2340
#                               If not supplied then no files have their permissions changed
2341
#               --DirPerms=     Sets the permissions of directories to this permission
2342
#                               If not supplied then no directories have their permissions changed
2343
#       OR
2344
#               --Perms=        Sets the permissions of both files and directories to this permissions
2345
#                               Equivalent to supplying both --FilePerms=X && --DirPerms=X
2346
#               
2347
#   Options:                    
2348
#               --RootOnly      Only sets the permissions on the 'path' directory/file, 
2349
#                               all other options ignored
2350
#               --SkipRoot      Does not set permissions on the 'path' directory/file, 
2351
#                               obviously mutually exlusive with --RootOnly
2352
#   
2353
#       Any option supported by JatsLocateFiles. 
2354
#       Some of these include:
2355
#               
2356
#               --Recurse       Recurse the directory tree.  Does a depth first recurse so that all 
2357
#                               dir entries are processed before the dir itself (default)
2358
#               --NoRecurse     Dont recurse
2359
#               --FilterIn=     Apply permissions to files/directories that matches this value.
2360
#               --FilterInRe=   Perl RE's can be used (Not Shell wildcards) and this option
2361
#                               can be supplied mulitple times
2362
#               --FilterOut=    Dont apply permissions to any files/directories matching this value
2363
#               --FilterOutRe=  Perl RE's can be used (Not Shell wildcards) and this option
2364
#                               can be supplied mulitple times
2365
#               
2366
#                               FilterIn is applied before FilterOut.  If Recurse is specified 
2367
#                               the directory will be recursed regardless of these filters, however
2368
#                               the filter will be applied when it comes time to chmod the dir 
2369
#
2370
#------------------------------------------------------------------------------
2371
sub SetPermissions
2372
{
6861 dpurdie 2373
    return 1 unless ($ActiveSection);
6859 dpurdie 2374
    my ( $path, $filePerms, $dirPerms, $someDone );
2375
    my ( $rootOnly, $skipRoot ) = ( 0, 0 );
2376
 
2377
    my $search =  JatsLocateFiles->new( '--Recurse', '--DirsToo' );
2378
 
2379
    foreach ( @_ )
2380
    {
2381
        if ( m/^--Perms=(.*)/ ) {
2382
            $filePerms = $1;
2383
            $dirPerms = $1;
2384
 
2385
        } elsif (m/^--FilePerms=(.*)/ )  {
2386
            $filePerms = $1;
2387
 
2388
        } elsif ( m/^--DirPerms=(.*)/ )  {
2389
            $dirPerms = $1;
2390
 
2391
        }  elsif ( m/^--RootOnly/ ) {
2392
            $rootOnly = 1;
2393
 
2394
        } elsif ( m/^--SkipRoot/ )  {
2395
            $skipRoot = 1;
2396
 
2397
        } elsif ( m/^--Filter/ && $search->option( $_ ) ) {
2398
            Verbose2 ("Search Option: $_" );
2399
 
2400
        } elsif ( m/^--Recurse|--NoRecurse/ && $search->option( $_ ) ) {
2401
            Verbose2 ("Search Option: $_" );
2402
 
2403
        } elsif (m/^--/ ) {
2404
            Error ("SetPermissions: Unknown option: $_");
2405
 
2406
        } else  {
2407
            Error("SetPermissions 'path' already set", "Path: $_") if ( $path );
2408
            $path = $_;
2409
        }
2410
    }
2411
 
2412
    #
2413
    #   Sanity test
2414
    #
2415
    Error("SetPermissions called with out a 'path' parameter") if ( !defined($path) );
2416
    Error("SetPermissions called with out any Permissions specified") if ( !defined($filePerms) && !defined($dirPerms) );
2417
    Error("SetPermissions: Options --RootOnly & --SkipRoot are mutually exclusive" ) if ( $rootOnly && $skipRoot );
2418
 
2419
 
2420
    #   Convert the target directory name into a physical path
2421
    #   User specifies '/' as the root of the image
2422
    #   User specifies 'name' as relateve to the root of the image
2423
    #
2424
    my $topDir = $WorkDir . '/' . $path;
2425
    $topDir =~ s~/+$~~;
2426
 
2427
    Verbose("SetPermissions: Called with options " . join(", ", @_));
2428
 
2429
    #
2430
    #   Only set perms on the root directory
2431
    #       This is a trivial operation
2432
    #
2433
    if ( $rootOnly )
2434
    {
2435
        $someDone += chmodItem( $topDir, $filePerms, $dirPerms );
2436
    }
2437
    else
2438
    {
2439
        #
2440
        #   Create a list of files/dirs to process
2441
        #
2442
        my @elements = $search->search( $topDir );
2443
 
2444
        foreach my $dirEntry ( @elements )
2445
        {
2446
            my $fullPath = "$topDir/$dirEntry";
2447
 
2448
            # A dir and we dont have dirperms, so skip
2449
            if ( -d $fullPath && !defined($dirPerms) )
2450
            {
2451
                Verbose2("SetPermissions: Skipping dir $fullPath as we have no dir permissions");
2452
                next;
2453
            }
2454
 
2455
            # A file and we dont have fileperms, so skip
2456
            if ( -f $fullPath && !defined($filePerms) )
2457
            {
2458
                Verbose2("SetPermissions: Skipping file $fullPath as we have no file permissions");
2459
                next;
2460
            }
2461
 
2462
            # a file or a dir and have the right permissions and we are not recursing
2463
            if ( -f $fullPath || -d $fullPath )
2464
            {
2465
                $someDone += chmodItem( $fullPath, $filePerms, $dirPerms );
2466
            }
2467
            else
2468
            {
2469
                Warning("SetPermissions: Skipping $fullPath as its not a file or directory");
2470
            }
2471
        }
2472
 
2473
        #
2474
        #   Process the topDir
2475
        #   May not be modified if --SkipRoot has been requested
2476
        #
2477
        if ( !$skipRoot && -e $topDir )
2478
        {
2479
            $someDone += chmodItem( $topDir, $filePerms, $dirPerms );
2480
        }
2481
    }
2482
 
2483
    #   Final warning
2484
    #
2485
    Warning ("SetPermissions: No files located", "Args: @_") unless ( $someDone );
2486
}
2487
 
2488
#************ INTERNAL USE ONLY  **********************************************
2489
# Function        : chmodItem 
2490
#
2491
# Description     : Internal
2492
#                   chmod a file or a folder
2493
#
2494
# Inputs          : item                        - Item to mod
2495
#                   filePerms                   - File perms
2496
#                   dirPerms                    - dire perms
2497
#
2498
# Returns         : 1   - Item modified
2499
#                   0   - Item not modified
2500
#
2501
#************ INTERNAL USE ONLY  **********************************************
2502
sub chmodItem
2503
{
2504
    my ($item, $filePerms, $dirPerms) = @_;
2505
 
2506
    if ( -d $item && defined $dirPerms)
2507
    {
2508
        Verbose("SetPermissions: $dirPerms : $item");
2509
        System ('chmod', $dirPerms, $item );
2510
        return 1;
2511
    }
2512
 
2513
    if ( -f $item  && defined $filePerms)
2514
    {
2515
        Verbose("SetPermissions: $filePerms : $item");
2516
        System ('chmod', $filePerms, $item );
2517
        return 1;
2518
    }
2519
 
2520
    return 0;
2521
}
2522
 
2523
 
2524
#-------------------------------------------------------------------------------
2525
# Function        : CreateDir
2526
#
2527
# Description     : Create a directory within the target workspace
2528
#
2529
# Inputs          : $path           - Name of the target directory
2530
#                   @opts           - Options
2531
#                     --Owner       - Tells RPM Builder that this package. Owns this directory
2532
#
2533
# Returns         : Nothing
2534
#
2535
sub CreateDir
2536
{
2537
    my ($path, @opts) = @_;
6861 dpurdie 2538
    return 1 unless ($ActiveSection);
6859 dpurdie 2539
    Verbose ("Create Dir: $path");
2540
    my $owner  = 0;
2541
    foreach ( @opts) {
2542
        if (m~^--Owner~i ) {
2543
            $owner = 1;
2544
        } else {
2545
            ReportError ("SetBaseDir: Unknown option: $_");
2546
        }
2547
    }
2548
    ErrorDoExit();
2549
 
2550
    $path =~ s~^/+~~;
2551
    $path = '/' . $path;
2552
    $OwnedDirs{$path} = $owner if $owner;
2553
    mkpath( $WorkDir . $path );
2554
}
2555
 
2556
#-------------------------------------------------------------------------------
2557
# Function        : RpmSetDefAttr 
2558
#
2559
# Description     : RPM only: Set the defAttr values 
2560
#
2561
# Inputs          : Expect 4 or less argument
2562
#                       The default permissions, or "mode" for files.
2563
#                       The default user id.
2564
#                       The default group id.
2565
#                       The default permissions, or "mode" for directories.
2566
#                   
2567
sub RpmSetDefAttr
2568
{
6861 dpurdie 2569
    return 1 unless ($ActiveSection);
6859 dpurdie 2570
    return 1 unless $opt_rpm;
2571
    my @args = @_;
2572
    Error ("RpmSetDefAttr: Expecting 4 arguments") if (scalar @args ne 4);
2573
    @RpmDefAttr = @_;
2574
    return 1;
2575
}
2576
 
2577
#-------------------------------------------------------------------------------
2578
# Function        : RpmSetAttr 
2579
#
2580
# Description     : RPM Only : Specify specific file attributes
2581
#
2582
# Inputs          : $file - file to target
2583
#                   $mode - File mode to place on the file (optional)
2584
#                   $user - user name to place on the file  (optional)
2585
#                   $group  - group name to place eon the file (optional)
2586
#
2587
sub RpmSetAttr
2588
{
6861 dpurdie 2589
    return 1 unless ($ActiveSection);
6859 dpurdie 2590
    return 1 unless $opt_rpm;
2591
    my ($file, $mode, $user, $group, @extra) = @_;
2592
    Error ("RpmSetAttr: Too many arguments") if @extra;
2593
 
2594
    #
2595
    #   Validate the file
2596
    #
2597
    $file = '/' . $file;
2598
    $file =~ s~//~/~g;
2599
    my $full_path = $WorkDir . $file;
2600
    Error ("RpmSetAttr: File not found: $WorkSubDir$file") unless (-x $full_path );
2601
 
2602
    my @data;
2603
    $data[0] = $WorkSubDir . $file;
2604
    $data[1] = $mode || '-';
2605
    $data[2] = $user || '-';
2606
    $data[3] = $group ||'-';
2607
    push @RpmAttrList, \@data;
2608
    return 1;
2609
}
2610
 
2611
 
2612
#-------------------------------------------------------------------------------
2613
# Function        : IsProduct
2614
#                   IsPlatform
2615
#                   IsTarget
2616
#                   IsVariant
2617
#                   IsAlias
6861 dpurdie 2618
#                   IsDebian
2619
#                   IsRpm
2620
#                   IsTar
6859 dpurdie 2621
#
2622
# Description     : This function allows some level of control in the
2623
#                   packaging scripts. It will return true if the current
2624
#                   product is listed.
2625
#
2626
#                   Ugly after thought
2627
#
2628
#                   Intended use:
2629
#                       Xxxxxx(...) if (IsProduct( 'aaa',bbb' );
2630
#
2631
# Inputs          : products    - a list of products to compare against
2632
#
2633
# Returns         : True if the current build is for one of the listed products
2634
#
2635
sub IsProduct
2636
{
2637
    foreach ( @_ )
2638
    {
2639
        return 1 if ( $opt_product eq $_ );
2640
    }
2641
    return 0;
2642
}
2643
 
2644
sub IsPlatform
2645
{
2646
    foreach ( @_ )
2647
    {
2648
        return 1 if ( $opt_platform eq $_ );
2649
    }
2650
    return 0;
2651
}
2652
 
2653
sub IsTarget
2654
{
2655
    foreach ( @_ )
2656
    {
2657
        return 1 if ( $opt_target eq $_ );
2658
    }
2659
    return 0;
2660
}
2661
 
2662
sub IsVariant
2663
{
2664
    foreach ( @_ )
2665
    {
2666
        return 1 if ( $opt_variant eq $_ );
2667
    }
2668
    return 0;
2669
}
2670
 
2671
sub IsAlias
2672
{
2673
 
2674
    #
2675
    #   Get the aliases from the build info
2676
    #   This function was introduced late so its not always available
2677
    #
2678
    Error("IsAlias not supported in this version of JATS")
2679
        unless (defined &ReadBuildConfig::getAliases);
2680
    #
2681
    #   Create an hash of aliases to simplify testing
6861 dpurdie 2682
    #   Do it once and cache the results
6859 dpurdie 2683
    #
2684
    unless (%opt_aliases) {
2685
        %opt_aliases = map { $_ => 1 } getAliases();
2686
    }
2687
 
2688
    foreach ( @_ )
2689
    {
2690
        return 1 if ( exists $opt_aliases{$_} );
2691
    }
2692
    return 0;
2693
}
2694
 
6861 dpurdie 2695
sub IsDebian()
2696
{
2697
    return $opt_debian ? 1 : 0;
2698
}
6859 dpurdie 2699
 
6861 dpurdie 2700
sub IsRpm()
2701
{
2702
    return $opt_rpm ? 1 : 0;
2703
}
2704
 
2705
sub IsTar()
2706
{
2707
    return $opt_tarFile ? 1 : 0;
2708
}
2709
 
6865 dpurdie 2710
#-------------------------------------------------------------------------------
2711
# Function        : PackageVersion 
2712
#
2713
# Description     : Return the version of the named package 
2714
#
2715
# Inputs          : pkgName - Name of the package 
2716
#                   Options
2717
#                       --format=SomeString. The text replacements
2718
#                           {VERSION}
2719
#                           {VERSIONNUMVER}
2720
#                           {PROJECT}
2721
#                           {NAME}
2722
#                           {TYPE}
2723
#                           {ARCH}
2724
#
2725
# Returns         : A string 
2726
#
2727
sub PackageVersion
2728
{
2729
    my ($pkgName, @args) = @_;
2730
    my ($version, $versionNumber, $project, $format);
6861 dpurdie 2731
 
6865 dpurdie 2732
    foreach ( @args)
2733
    {
2734
        if (m~^--format=(.+)~i) {
2735
            $format = $1
2736
        } else {
2737
            Error ("PackageVersion: Unknown option: $_")
2738
        }
2739
    }
2740
 
2741
    foreach my $entry ( getPackageList() )
2742
    {
2743
        if ($entry->getName() eq $pkgName ) {
2744
            $version = $entry->getVersion();
2745
            ($versionNumber = $version ) =~ s~\.[^.]+$~~;
2746
            ($project = $version ) =~ s~.*\.~~;
2747
            last;
2748
        }
2749
    }
2750
 
2751
    Error ("PackageVersion: $pkgName is not a dependent package") unless defined $version;
2752
 
2753
    #
2754
    #   Format the string
2755
    #
2756
    if ($format) {
2757
        $format =~ s~{NAME}~$pkgName~g;
2758
        $format =~ s~{VERSION}~$version~g;
2759
        $format =~ s~{VERSIONNUMBER}~$versionNumber~g;
2760
        $format =~ s~{PROJECT}~$project~g;
2761
        $format =~ s~{TYPE}~$opt_type~g;
2762
        $format =~ s~{ARCH}~$opt_pkgarch~g;
2763
 
2764
        $version = $format;
2765
    }
2766
 
2767
    return $version;
2768
}
2769
 
2770
 
6859 dpurdie 2771
#************ INTERNAL USE ONLY  **********************************************
2772
# Function        : FindFiles
2773
#
2774
# Description     : Locate files within a given dir tree
2775
#
2776
# Inputs          : $root           - Base of the search
2777
#                   $match          - Re to match
2778
#
2779
# Returns         : A list of files that match
2780
#
2781
#************ INTERNAL USE ONLY  **********************************************
2782
my @FIND_LIST;
2783
my $FIND_NAME;
2784
 
2785
sub FindFiles
2786
{
2787
    my ($root, $match ) = @_;
2788
    Verbose2("FindFiles: Root: $root, Match: $match");
2789
 
2790
    #
2791
    #   Becareful of closure, Must use globals
2792
    #
2793
    @FIND_LIST = ();
2794
    $FIND_NAME = $match;
2795
    File::Find::find( \&find_files, $root);
2796
 
2797
    #
2798
    #   Find callback program
2799
    #
2800
    sub find_files
2801
    {
2802
        my $item =  $File::Find::name;
2803
 
2804
        return if ( -d $File::Find::name );
2805
        return unless ( $_ =~ m~$FIND_NAME~ );
2806
        push @FIND_LIST, $item;
2807
    }
2808
    return @FIND_LIST;
2809
}
2810
 
2811
#-------------------------------------------------------------------------------
2812
# Function        : CalcRelPath
2813
#
2814
# Description     : Return the relative path to the current working directory
2815
#                   as provided in $Cwd
2816
#
2817
# Inputs          : $Cwd - Base dir
2818
#                   $base - Path to convert
2819
#
2820
# Returns         : Relative path from the $Cwd
2821
#
2822
sub CalcRelPath
2823
{
2824
    my ($Cwd, $base) = @_;
2825
 
2826
    my @base = split ('/', $base );
2827
    my @here = split ('/', $Cwd );
2828
    my $result;
2829
 
2830
    Debug("RelPath: Source: $base");
2831
 
2832
    return $base unless ( $base =~ m~^/~ );
2833
 
2834
    #
2835
    #   Remove common bits from the head of both lists
2836
    #
2837
    while ( $#base >= 0 && $#here >= 0 && $base[0] eq $here[0] )
2838
    {
2839
        shift @base;
2840
        shift @here;
2841
    }
2842
 
2843
    #
2844
    #   Need to go up some directories from here and then down into base
2845
    #
2846
    $result = '../' x ($#here + 1);
2847
    $result .= join ( '/', @base);
2848
    $result = '.' unless ( $result );
2849
    $result =~ s~//~/~g;
2850
    $result =~ s~/$~~;
2851
 
2852
    Debug("RelPath: Result: $result");
2853
    return $result;
2854
}
2855
 
2856
#-------------------------------------------------------------------------------
2857
# Function        : ExpandLinkFiles
2858
#
2859
# Description     : Look for .LINK files in the output image and expand
2860
#                   the links into softlinks
2861
#
2862
# Inputs          : None
2863
#                   The routine works on the $WorkDir directory tree
2864
#
2865
# Returns         : Nothing
2866
#                   Will remove .LINKS files that are processed
2867
#
2868
sub ExpandLinkFiles
2869
{
6861 dpurdie 2870
    return 1 unless ($ActiveSection);
6859 dpurdie 2871
    foreach my $linkfile ( FindFiles( $WorkDir, ".LINKS" ))
2872
    {
2873
        next if ( $linkfile =~ m~/\.svn/~ );
2874
        my $BASEDIR = StripFileExt( $linkfile );
2875
        $BASEDIR =~ s~^$WorkDir/~~;
2876
        Verbose "Expand links: $BASEDIR";
2877
 
2878
        open (LF, "<", $linkfile ) || Error ("Cannot open link file: $linkfile" );
2879
        while ( <LF> )
2880
        {
2881
            chomp;
2882
            next if ( m~^#~ );
2883
            next unless ( $_ );
2884
            my ($link, $file) = split;
2885
 
2886
            MakeSymLink($file ,"$BASEDIR/$link", '--NoDotDot' );
2887
        }
2888
        close (LF);
2889
        unlink $linkfile;
2890
    }
2891
}
2892
 
2893
#************ INTERNAL USE ONLY  **********************************************
2894
# Function        : ResolveFile
2895
#
2896
# Description     : Determine where the source for a file is
2897
#                   Will look in (default):
2898
#                       Local directory
2899
#                       Local Include
2900
#                   Or  (FromPackage)
2901
#                       Our Package directory
2902
#                       Interface directory (BuildPkgArchives)
2903
#                       Packages (LinkPkgArchive)
2904
#
2905
#                   Will scan 'parts' subdirs
2906
#
2907
# Inputs          : $from_package       - 0 - Local File
2908
#                   $file
6861 dpurdie 2909
#                   $refPlatforms       - Not used
6859 dpurdie 2910
#
2911
# Returns         : Path
2912
#
2913
#************ INTERNAL USE ONLY  **********************************************
2914
sub ResolveFile
2915
{
6861 dpurdie 2916
    my ($from_package, $file,$refPlatforms) = @_;
6859 dpurdie 2917
    my $wildcard = ($file =~ /[*?]/);
2918
    my @path;
2919
 
2920
    #
2921
    #   Determine the paths to search
2922
    #
2923
    if ( $from_package )
2924
    {
2925
        unless ( @ResolveFileList )
2926
        {
2927
            push @ResolveFileList, $opt_pkgdir;
2928
            foreach my $entry ( getPackageList() )
2929
            {
2930
                push @ResolveFileList, $entry->getBase(3);
2931
            }
2932
        }
2933
        @path = @ResolveFileList;
2934
    }
2935
    else
2936
    {
2937
        @path = ('.', $opt_localincdir);
2938
    }
2939
 
2940
    #   Determine a full list of 'parts' to search
6861 dpurdie 2941
    #       Default: Provided within the build information
2942
    #       User   : Can provide a list
2943
    my @parts = getPlatformPartsList($refPlatforms);
6859 dpurdie 2944
 
2945
    my @done;
2946
    foreach my $root (  @path )
2947
    {
2948
        foreach my $subdir ( @parts )
2949
        {
2950
            my $sfile;
2951
            $sfile = "$root/$subdir/$file";
2952
            $sfile =~ s~//~/~g;
2953
            $sfile =~ s~^./~~g;
2954
            Verbose2("LocateFile: $sfile, $root, $subdir");
2955
            if ( $wildcard )
2956
            {
2957
                push @done, glob ( $sfile );
2958
            }
2959
            else
2960
            {
2961
                push @done, $sfile if ( -f $sfile || -l $sfile )
2962
            }
2963
        }
2964
    }
2965
 
6861 dpurdie 2966
    DisplaySearchPath('ResolveFile', $file, \@parts, undef, \@path) unless (@done) ;
6859 dpurdie 2967
 
2968
    Warning ("ResolveFile: Multiple instances of file found. Only first is used", @done)
2969
        if ( $#done > 0 && ! $wildcard && !wantarray );
2970
 
2971
    return wantarray ? @done : $done[0];
2972
}
2973
 
2974
#-------------------------------------------------------------------------------
2975
# Function        : ResolveBinFile
2976
#
2977
# Description     : Determine where the source for a BIN file is
2978
#                   Will look in (default):
2979
#                       Local directory
2980
#                       Local Include
2981
#                   Or  (FromPackage)
2982
#                       Our Package directory
2983
#                       Interface directory (BuildPkgArchives)
2984
#                       Packages (LinkPkgArchive)
6861 dpurdie 2985
#                   Will scan 'parts' subdirs (default)
2986
#                   May scan user-provided parts (cross platform packaging)
6859 dpurdie 2987
#
2988
# Inputs          : $from_package       - 0 - Local File
2989
#                   $file
6861 dpurdie 2990
#                   $refPlatforms       - (optional) Ref to an array of platforms to scan
6859 dpurdie 2991
#
2992
# Returns         : Path
2993
#
2994
sub ResolveBinFile
2995
{
6861 dpurdie 2996
    my ($from_package, $file, $refPlatforms) = @_;
6859 dpurdie 2997
    my @path;
2998
    my @types;
2999
    my $wildcard = ($file =~ /[*?]/);
3000
 
3001
    #
3002
    #   Determine the paths to search
3003
    #
3004
    if ( $from_package )
3005
    {
3006
        unless ( @ResolveBinFileList )
3007
        {
3008
            push @ResolveBinFileList, $opt_pkgdir . '/bin';
3009
            foreach my $entry ( getPackageList() )
3010
            {
3011
                if ( my $path = $entry->getBase(3) )
3012
                {
3013
                    $path .= '/bin';
3014
                    push @ResolveBinFileList, $path if ( -d $path );
3015
                }
3016
            }
3017
        }
3018
        @path = @ResolveBinFileList;
3019
        @types = ($opt_type, '');
3020
    }
3021
    else
3022
    {
3023
        @path = ($opt_bindir, $opt_localbindir);
3024
        @types = '';
3025
    }
3026
 
3027
    #
3028
    #   Determine a full list of 'parts' to search
6861 dpurdie 3029
    #       Default: Provided within the build information
3030
    #       User   : Can provide a list
6859 dpurdie 3031
    #
6861 dpurdie 3032
    my @parts = getPlatformPartsList($refPlatforms);
6859 dpurdie 3033
 
3034
    my @done;
3035
    foreach my $root (  @path )
3036
    {
3037
        foreach my $subdir ( @parts )
3038
        {
3039
            foreach my $type ( @types )
3040
            {
3041
                my $sfile;
3042
                $sfile = "$root/$subdir$type/$file";
3043
                $sfile =~ s~//~/~g;
3044
                Verbose2("LocateBinFile: $sfile");
3045
                if ( $wildcard )
3046
                {
3047
                    foreach  ( glob ( $sfile ) )
3048
                    {
3049
                        # Ignore .dbg (vix) and .debug (qt) files.
3050
                        next if ( m~\.dbg$~ );
3051
                        next if ( m~\.debug$~ );
3052
                        push @done, $_;
3053
                    }
3054
                }
3055
                else
3056
                {
3057
                    push @done, $sfile if ( -f $sfile || -l $sfile )
3058
                }
3059
            }
3060
        }
3061
    }
3062
 
6861 dpurdie 3063
    #
3064
    #   Pretty display the search path - on error
3065
    #       Will not return.
3066
    #
3067
    DisplaySearchPath('ResolveBinFile', $file, \@parts, \@types, \@path) unless (@done) ;
6859 dpurdie 3068
 
3069
    if ( $#done > 0 && ! $wildcard )
3070
    {
3071
        Warning ("ResolveBinFile: Multiple instances of file found. Only first is used", @done);
3072
        splice (@done, 1);
3073
    }
3074
 
3075
    return wantarray ? @done : $done[0];
3076
}
3077
 
3078
#-------------------------------------------------------------------------------
3079
# Function        : ResolveLibFile
3080
#
3081
# Description     : Determine where the source for a LIB file is
3082
#                   Will look in (default):
3083
#                       Local directory
3084
#                       Local Include
3085
#                   Or  (FromPackage)
3086
#                       Our Package directory
3087
#                       Interface directory (BuildPkgArchives)
3088
#                       Packages (LinkPkgArchive)
3089
#                   Will scan 'parts' subdirs
3090
#
3091
# Inputs          : $from_package   - 0:Local File
3092
#                   $file           - Basename for a 'realname'
3093
#                                     Do not provide 'lib' or '.so' or version info
3094
#                                     May contain embedded options
3095
#                                       --Dll           - Use Windows style versioned DLL
3096
#                                       --VersionDll    - Use the versioned DLL
3097
#                                       --3rdParty      - Use exact name provided
6861 dpurdie 3098
#                   $refPlatforms       - Ref to an array of platforms to scan
6859 dpurdie 3099
#
3100
# Returns         : Path
3101
#
3102
sub ResolveLibFile
3103
{
6861 dpurdie 3104
    my ($from_package, $file, $refPlatforms) = @_;
6859 dpurdie 3105
    my $wildcard = ($file =~ /[*?]/);
3106
    my @options;
3107
    my $num_dll;
6861 dpurdie 3108
    my @types;
6859 dpurdie 3109
    my @path;
3110
    #
3111
    #   Extract options from file
3112
    #
3113
    $num_dll = 0;
3114
    ($file, @options) = split ( ',', $file);
3115
    foreach ( @options )
3116
    {
3117
        if ( m/^--Dll/ ) {
3118
            $num_dll = 1;
3119
        } elsif ( m/^--VersionDll/ ) {
3120
            $num_dll = 2;
3121
        } elsif ( m/^--3rdParty/ ) {
3122
            $num_dll = 3;
3123
        } else {
3124
            Error ("Unknown suboption to ResolveLibFile: $_" );
3125
        }
3126
    }
3127
 
3128
    #
3129
    #   Determine the paths to search
3130
    #
3131
    if ( $from_package )
3132
    {
3133
        unless ( @ResolveLibFileList )
3134
        {
3135
            push @ResolveLibFileList, $opt_pkgdir . '/lib';
3136
            foreach my $entry ( getPackageList() )
3137
            {
3138
                push @ResolveLibFileList, $entry->getLibDirs(3);
3139
            }
3140
        }
3141
        @path = @ResolveLibFileList;
3142
    }
3143
    else
3144
    {
3145
        @path = ($opt_libdir, $opt_locallibdir);
3146
    }
3147
 
3148
    #   Determine a full list of 'parts' to search
6861 dpurdie 3149
    #       Default: Provided within the build information
3150
    #       User   : Can provide a list
3151
    my @parts = getPlatformPartsList($refPlatforms);
6859 dpurdie 3152
 
6861 dpurdie 3153
    @types = ( $opt_type, '');
3154
 
6859 dpurdie 3155
    my @done;
3156
    foreach my $root (  @path )
3157
    {
6861 dpurdie 3158
        foreach my $type ( @types )
6859 dpurdie 3159
        {
3160
            foreach my $subdir ( @parts )
3161
            {
3162
                my $sfile;
3163
                my $exact;
3164
                if ( $num_dll == 2 ) {
3165
                    $sfile = $file . $type . '.*.dll' ;
3166
                } elsif ( $num_dll == 1 ) {
3167
                    $sfile = $file . $type . '.dll' ;
3168
                    $exact = 1;
3169
                } elsif ( $num_dll == 3 ) {
3170
                    $sfile = $file;
3171
                    $exact = 1;
3172
                } else {
3173
                    $sfile = "lib" . $file . $type . '.so.*';
3174
                }
3175
 
3176
                $sfile = "$root/$subdir/$sfile";
3177
                $sfile =~ s~//~/~g;
3178
                Verbose2("LocateLibFile: $sfile");
3179
                if ( $exact )
3180
                {
3181
                    push @done, $sfile if ( -f $sfile || -l $sfile );
3182
                }
3183
                elsif ($num_dll)
3184
                {
3185
                    push @done, glob ( $sfile );
3186
                }
3187
                else
3188
                {
3189
                    #
3190
                    #   Looking for .so files
3191
                    #   Filter out the soname so files
3192
                    #   Assume that the soname is shorter than the realname
3193
                    #       Ignore .dbg (vix) and .debug (qt) files.
3194
                    #
3195
                    my %sieve;
3196
                    foreach ( glob ( $sfile )  )
3197
                    {
3198
                        next if ( m~\.dbg$~ );
3199
                        next if ( m~\.debug$~ );
3200
                        m~(.*\.so\.)([\d\.]*\d)$~;
3201
                        if ( $1 )
3202
                        {
3203
                            my $file = $1;
3204
                            my $len = exists $sieve{$file} ? length($sieve{$file}) : 0;
3205
                            $sieve{$file} = $_
3206
                                if ( $len == 0 || length($_) > $len );
3207
                        }                                
3208
                    }
3209
 
3210
                    push @done, values %sieve;
3211
                }
3212
            }
3213
        }
3214
    }
3215
 
6861 dpurdie 3216
    DisplaySearchPath('ResolveLibFile', $file, \@parts, \@types, \@path) unless (@done) ;
6859 dpurdie 3217
 
3218
    if ( $#done > 0 && ! $wildcard )
3219
    {
3220
        Warning ("ResolveLibFile: Multiple instances of file found. Only first is used", @done);
3221
        splice (@done, 1);
3222
    }
3223
    return wantarray ? @done : $done[0];
3224
}
3225
 
3226
#-------------------------------------------------------------------------------
3227
# Function        : ResolveDebPackage
3228
#
3229
# Description     : Determine where the source for a Debian Package is
3230
#                   Will look in (default):
3231
#                       Local directory
3232
#                       Local Include
3233
#                   Or  (FromPackage)
3234
#                       Our Package directory
3235
#                       Interface directory (BuildPkgArchives)
3236
#                       Packages (LinkPkgArchive)
3237
#
3238
# Inputs          : $from_package   - 0:Local File
3239
#                   $baseName       - Basename for a 'DebianPackage'
3240
#                                     Do not provide version info, architecture or suffix
3241
#                                     May contain embedded options
6861 dpurdie 3242
#                                       --Arch=XXX      - Specify alternate architcuture
6859 dpurdie 3243
#                                       --Product=YYYY  - Specify product family
3244
#                                       --Debug         - Use alternate build type
3245
#                                       --Prod          - Use alternate build type
6861 dpurdie 3246
#                   $refPlatforms       - Ref to an array of platforms to scan
6859 dpurdie 3247
#
3248
# Returns         : Path
3249
#
3250
sub ResolveDebPackage
3251
{
6861 dpurdie 3252
    my ($from_package, $file, $refPlatforms) = @_;
6859 dpurdie 3253
    my @path;
3254
    my $arch;
3255
    my $product;
3256
    my $buildType;
3257
    my @types;
3258
    my $baseName;
3259
    my @options;
3260
 
3261
    #
3262
    #   Extract options from file
3263
    #
3264
    ($baseName, @options) = split ( ',', $file);
3265
    foreach ( @options )
3266
    {
3267
        if ( m/^--Arch=(.+)/ ) {
3268
            $arch=$1;
3269
        } elsif ( m/^--Product=(.+)/ ) {
3270
            $product = $1;
3271
        } elsif ( m/^--Debug/ ) {
3272
            Error ("ResolveDebPackage: Cannot specify --Prod and --Debug") if defined $buildType;
3273
            $buildType = 'D';
3274
        } elsif ( m/^--Prod/ ) {
3275
            Error ("ResolveDebPackage: Cannot specify --Prod and --Debug") if defined $buildType;
3276
            $buildType = 'P';
3277
        } else {
3278
            Error ("Unknown suboption to ResolveDebPackage: $_" );
3279
        }
3280
    }
3281
 
3282
    #
3283
    #   Insert defaults
3284
    #
3285
    $buildType = $opt_type unless ($buildType);
3286
    $arch = $opt_target unless ($arch);
3287
 
3288
    #
3289
    #   Determine the paths to search
3290
    #
3291
    if ( $from_package )
3292
    {
3293
        unless ( @ResolveDebFileList )
3294
        {
3295
            push @ResolveDebFileList,  $opt_pkgdir, $opt_pkgdir . '/bin';
3296
            foreach my $entry ( getPackageList() )
3297
            {
3298
                if ( my $path = $entry->getBase(3) )
3299
                {
3300
                    push @ResolveDebFileList, $path if ( -d $path );
3301
 
3302
                    $path .= '/bin';
3303
                    push @ResolveDebFileList, $path if ( -d $path );
3304
                }
3305
            }
3306
        }
3307
        @path = @ResolveDebFileList;
3308
        @types = ($buildType, '');
3309
    }
3310
    else
3311
    {
3312
        @path = ($opt_bindir, $opt_localbindir);
3313
        @types = ($buildType, '');
3314
    }
3315
 
3316
    #
3317
    #   The debian  package name is
3318
    #   In packages BIN dir
3319
    #       (BaseName)_VersionString(_Product)(_Arch).deb
3320
    #       
3321
    #   In root of package
3322
    #       (BaseName)_VersionString(_Product)(_Arch)(_Type).deb
3323
    #
3324
    #       
3325
    #   The package may be found in
3326
    #       Package Root
3327
    #       Package bin directory
3328
    #       
3329
    $file = $baseName . '_*';
3330
    if (defined $product) {
3331
        $file .= ( '_' . $product)
3332
        }
3333
    $file .= '_' . $arch;
3334
 
3335
    #   Determine a full list of 'parts' to search
6861 dpurdie 3336
    #       Default: Provided within the build information
3337
    #       User   : Can provide a list
3338
    my @parts = getPlatformPartsList($refPlatforms);
6859 dpurdie 3339
 
3340
    my @done;
3341
    foreach my $root (  @path )
3342
    {
3343
        foreach my $subdir ( @parts )
3344
        {
3345
            foreach my $type ( @types )
3346
            {
3347
                my $sfile;
3348
                $sfile = "$root/$subdir$type/$file";
3349
                $sfile =~ s~//~/~g;
3350
                foreach my $type2 ( @types )
3351
                {
3352
                    my $tfile = $sfile;
3353
                    $tfile .= '_' . $type2 if $type2;
3354
                    $tfile .= '.deb';
3355
                    Verbose2("ResolveDebPackage: $tfile");
3356
                    foreach  ( glob ( $tfile ) )
3357
                    {
3358
                        push @done, $_;
3359
                    }
3360
                }
3361
            }
3362
        }
3363
    }
3364
 
6861 dpurdie 3365
    DisplaySearchPath('ResolveDebPackage', $file, \@parts, \@types, \@path) unless (@done) ;
6859 dpurdie 3366
 
3367
    if ( $#done > 0 )
3368
    {
3369
        Error ("ResolveDebPackage: Multiple instances of Package found.", @done);
3370
    }
3371
    return wantarray ? @done : $done[0];
3372
}
3373
 
3374
#-------------------------------------------------------------------------------
6861 dpurdie 3375
# Function        : prettyArray 
3376
#
3377
# Description     : Generate a quoted string from an array
3378
#
3379
# Inputs          : Array Ref
3380
#
3381
# Returns         : A string
3382
#
3383
sub prettyArray
3384
{
3385
    my ($arrayRef) = @_;
3386
    return join(',', map { qq!"$_"! }  @{$arrayRef})
3387
}
3388
 
3389
#-------------------------------------------------------------------------------
3390
# Function        : DisplaySearchPath 
3391
#
3392
# Description     : Pretty display of the search path
3393
#                   Error display
3394
#
3395
# Inputs          : $name   - Function Name
3396
#                   $file   - Base filename being searched
3397
#                   $parts  - Ref to array of parts searched
3398
#                   $types  - Ref to array of types searched - may be undef
3399
#                   $path   - Ref to array of paths searched
3400
#
3401
# Returns         : Will not return
3402
#
3403
sub DisplaySearchPath
3404
{
3405
    my ($name, $file, $parts, $types, $path) = @_;
3406
    my @text;
3407
 
3408
    push @text, $name . ': File not found: ' . $file;
3409
    push @text, 'Search Platforms: ' . prettyArray($parts);
3410
    push @text, 'Search Types: ' . prettyArray($types) if defined $types;
3411
    push @text, 'Search Path:', @$path;
3412
    Error (@text);
3413
}
3414
 
3415
#-------------------------------------------------------------------------------
3416
# Function        : getPlatformPartsList  
3417
#
3418
# Description     : Determine a full list of 'parts' to search
3419
#                       Default: Provided within the build information
3420
#                       User   : Can provide a list
3421
#
3422
# Inputs          : $refPlatforms - Ref to an array of user provided platforms
3423
#                                   If provided will override the internal list
3424
#
3425
# Returns         : An array 
3426
#
3427
sub getPlatformPartsList
3428
{
3429
    my ($refPlatforms) = @_;
3430
    my @parts;
3431
 
3432
    if ($refPlatforms && scalar @{$refPlatforms}) {
3433
        @parts = @{$refPlatforms};
3434
 
3435
    } else {
3436
        @parts = getPlatformParts ();
3437
    }
3438
    push @parts, '';
3439
    return @parts;
3440
}
3441
 
3442
#-------------------------------------------------------------------------------
6859 dpurdie 3443
# Function        : AUTOLOAD
3444
#
3445
# Description     : Intercept unknown user directives and issue a nice error message
3446
#                   This is a simple routine to report unknown user directives
3447
#                   It does not attempt to distinguish between user errors and
3448
#                   programming errors. It assumes that the program has been
3449
#                   tested. The function simply report filename and line number
3450
#                   of the bad directive.
3451
#
3452
# Inputs          : Original function arguments ( not used )
3453
#
3454
# Returns         : This function does not return
3455
#
3456
our $AUTOLOAD;
3457
sub AUTOLOAD
3458
{
3459
    my $fname = $AUTOLOAD;
3460
    $fname =~ s~^main::~~;
3461
    my ($package, $filename, $line) = caller;
3462
    my $prefix;
3463
 
3464
    #
3465
    #   Some directives are applicable to Rpm and/or Debian only
3466
    #   If a directive starts with Rpm, Debian or All, then invoke
3467
    #   the underlying directive iff we are process a Debian/Rpm file
3468
    #   
3469
    #   The underlying directive will start with MULTI_
3470
    #   It will be called with the first argument being the name of the function
3471
    #   that it is being called as.
3472
    #
3473
    $fname =~ m~^(Rpm|Debian|All)(.*)~;
3474
    if (defined $1) {
3475
        my $type = $1;
3476
        my $tfname = 'MULTI_' . $2;
3477
        my $fRef = \&{$tfname}; 
3478
 
3479
        if (defined &{$tfname}) {
3480
            if ($type eq 'Rpm') {
3481
                $fRef->($fname, @_) if $opt_rpm;
3482
 
3483
            } elsif ($type eq 'Debian') {
3484
                $fRef->($fname, @_) if $opt_debian;
3485
 
3486
            } elsif ($type eq 'All') {
3487
                $fRef->($fname, @_);
3488
            }
3489
            return 1;
3490
        }
3491
    }
3492
 
3493
    Error ("Directive not known or not allowed in this context: $fname",
3494
           "Directive: $fname( @_ );",
3495
           "File: $filename, Line: $line" );
3496
}
3497
 
3498
1;
3499