Subversion Repositories DevTools

Rev

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

Rev Author Line No. Line
1119 dpurdie 1
########################################################################
6302 dpurdie 2
# COPYRIGHT - VIX IP PTY LTD ("VIX"). ALL RIGHTS RESERVED.
1119 dpurdie 3
#
6302 dpurdie 4
# Module name   : ManifestFiles.pm
1119 dpurdie 5
# Module type   : Makefile system
6302 dpurdie 6
# Environment(s): JATS Build System
5654 dpurdie 7
# Documents     : MASS-00232 Format of the Linux App Upgrade Manifest File
1119 dpurdie 8
#
9
# Description   : This package extends the JATS toolset at build time
10
#                 It provides additional directives to the JATS makefiles
11
#                 to simplify the directives.
12
#
13
#                 This directive does all its work at 'build' time
14
#                 It uses makefile.pl directives
15
#
16
# Operation     : This package adds the JATS directive ManifestFiles
17
#                 This is used to create linux manifest files
18
#
19
# Syntax        : ManifestFiles (<platforms>, Options+);
20
#                 See the function header for details
21
#
22
#......................................................................#
23
 
24
require 5.6.1;
25
use strict;
26
use warnings;
6306 dpurdie 27
use ArrayHashUtils;
1119 dpurdie 28
 
29
#
30
#   Globals
6932 dpurdie 31
#   These are exposed to all of JATS, so:
32
#       Limit the number (ideally none)
33
#       Be away of the potential name conflicts
1119 dpurdie 34
#
35
 
36
#-------------------------------------------------------------------------------
37
# Function        : BEGIN
38
#
39
# Description     : Setup directive hooks
40
#                   Register a function to be called just before we start to
41
#                   generate makefiles. This will be used to process the data
42
#                   collected in all the ManifestFiles directives
43
#
44
# Inputs          : None
45
#
46
# Returns         : None
47
#
48
BEGIN
49
{
6932 dpurdie 50
    RegisterMakefileGenerate (\&ManifestFiles::Generate);
1119 dpurdie 51
}
52
 
53
#-------------------------------------------------------------------------------
54
# Function        : ManifestFiles
55
#
56
# Description     : Create a ManifestFiles entry
57
#
58
# Inputs          : Platform             - Active Platform Selector
59
#                   Options              - One or more options
60
#                       --Name=Name             - Mandatory
61
#                       --Tier=Name             - Mandatory
62
#                       --Architecture=xxxx     - Default actitecture is the current target
63
#                       --Product=yyyy          - Product Family
64
#                       --Debian=BaseName[,--Prod,--Debug,--Arch=xxxx,--Product=yyyy]
6302 dpurdie 65
#                       --Apk=BaseName[,--Prod,--Debug,--Platform=pppp]
66
#                                                   Default platform = ANDROID
67
#                                                   Default type = Production
1119 dpurdie 68
#                       --MugPackage=Package[,--Subdir=subdir[,subdir]+]
69
#                       --SrcFile=xxx
1125 alewis 70
#                       --SrcFileNoCopy=xxx
1123 dpurdie 71
#                       --Comment=xxx           - Add comment to Manifst
1125 alewis 72
#                       --NoManifestVersion     - Create unversioned Manifest File
73
#                       --PkgSubdir=xxx         - Specifies packaging subdir
6981 dpurdie 74
#                       --LocalInstall          - Output manifest to the 'local' directory, not the output package
5105 dpurdie 75
#                       --ImportManifest=Package[,--Subdir=subdir,--ReWrite] - Import Manifest from package
5649 dpurdie 76
#                       --Md5                   - Add MD5 checksums to the Manifest File
5767 alewis 77
#                       --Dmf                   - Generate the Device Management Framework
78
#                                                 combined archive ZIP file.
79
#                       --DmfVersion=xxxx       - Generate the Device Management Framework
80
#                                                 combined archive ZIP using a modified
81
#                                                 version number; only for testing!
6364 dpurdie 82
#                       --LineLength=nnn        - Limit line length. Default is 79
83
#                       --SubManifest           - Create a sub-manifest (not installable). Manifest will have no version.
84
#                                                 Gives a default name, tier and subdir if not explicitly provided.
6981 dpurdie 85
#                       --[No]Signatures        - Control generation of .sig files
86
#                                                 Default is to not generate .sigFiles
6978 dpurdie 87
#                       --ManifestInsertionPoint[,--All,--Name,--Name=xxxx,--Tier,--Tier=Name,--Current]
88
#                                                 Create template insertion hook
6987 dpurdie 89
#                       --Template=Package[,--Subdir=subdir,--File=name]
6981 dpurdie 90
#                                                 Use Specified template                                                                           
6932 dpurdie 91
#                       --NoWarn                - Supress warnings about unused packages
92
#                                                 Will supress sanity test. Useful when generating multiple
93
#                                                 manifests.                          
7199 sdenys 94
#                       --UseFullVersion        - Use the full version (with the project extention) when building the manifest file
95
#                                                 Will only modify the content of the manifest file
6932 dpurdie 96
#                                                 
97
# Notes: On sig file generation
98
#   This tool will use an internal key file to generate signatures
99
#   UNLESS the tool is being run on a special build machine with a controlled signature file
100
#   the generated signatures will not work on-target.
101
#   
1119 dpurdie 102
#
103
# Returns         : Nothing
104
#
105
sub ManifestFiles
106
{
107
    my( $platforms, @elements ) = @_;
108
    Debug2( "ManifestFiles($platforms, @elements)" );
109
    return if ( ! ActivePlatform($platforms) );
110
 
111
    my $name;
112
    my $tier;
113
    my @files;
6306 dpurdie 114
    my %fileVersions;
1119 dpurdie 115
    my $mug_dir;
116
    my $default_arch = $::ScmPlatform;
117
    my $default_prod = '';
1129 dpurdie 118
    my $imported_manifest = 0;
5649 dpurdie 119
    my $include_md5 = 0;
5767 alewis 120
    my $generate_dmf = 0;
5771 alewis 121
    my $dmf_version = $::ScmBuildVersionFull;
6314 dpurdie 122
    my $useDefaultLineWidth = 1;
6364 dpurdie 123
    my $is_sub_manifest = 0;
1119 dpurdie 124
 
125
    #
126
    #   Collect user options
127
    #
128
    foreach ( @elements )
129
    {
130
        if ( m~^--Name=(.+)~ ) {
6302 dpurdie 131
            if ( $name ) {
1119 dpurdie 132
                ReportError ("ManifestFiles:--Name option is only allowed once");
133
                next;
134
            }
135
            $name = $1;
136
 
137
        } elsif ( m~^--Tier=(.+)~ ) {
6302 dpurdie 138
            if ( $tier ) {
1119 dpurdie 139
                ReportError ("ManifestFiles:--Tier option is only allowed once");
140
                next;
141
            }
142
            $tier = $1;
143
 
6981 dpurdie 144
 
145
        } elsif ( m~^--LocalInstall~ ) {
146
            $ManifestFiles::localInstall = 1;
147
 
1123 dpurdie 148
        } elsif ( m~^--Comment=~ ) {
149
            my $cmt = $_;
150
            $cmt =~ s~.+=~~;
151
            $cmt =~ s~\s*\n\s*~\n~g;
152
            push @files, {'cmt' => $cmt };
153
 
1119 dpurdie 154
        } elsif ( m~^--Debian=(.+)~ ) {
6932 dpurdie 155
            push @files, {'file' => ManifestFiles::_LocateDebianFile($1, $default_arch, $default_prod)};
1119 dpurdie 156
 
6302 dpurdie 157
        } elsif ( m~^--Apk=(.+)~ ) {
6932 dpurdie 158
            my $apkData = ManifestFiles::_LocateApkFile($1, $default_arch);
6306 dpurdie 159
            my ($fname, $fversion) = split($;, $apkData);
160
            $fileVersions{$fname} = $fversion;
161
            push @files, {'file' => $fname };
6314 dpurdie 162
            $useDefaultLineWidth = 0;
6302 dpurdie 163
 
1119 dpurdie 164
        } elsif ( m~^--SrcFile=(.+)~ ) {
1123 dpurdie 165
            push @files, {'file' => LocatePreReq($1)};
5649 dpurdie 166
 
1125 alewis 167
        } elsif ( m~^--SrcFileNoCopy=(.+)~ ) {
168
            push @files, {'filenocopy' => $1};
5649 dpurdie 169
 
1119 dpurdie 170
        } elsif ( m~^--MugPackage=(.+)~ ) {
6302 dpurdie 171
            if ( $mug_dir ) {
1119 dpurdie 172
                ReportError ("ManifestFiles:--MugPackage option is only allowed once");
173
                next;
5649 dpurdie 174
            }
6932 dpurdie 175
            $mug_dir = ManifestFiles::_LocateMugDir($1);
1119 dpurdie 176
 
177
        } elsif ( m/^--Arch(.*)=(.+)/ ) {
178
            $default_arch = $2;
179
 
180
        } elsif ( m/^--Product=(.+)/ ) {
181
            $default_prod = $1;
182
 
1125 alewis 183
        } elsif ( m/^--NoManifestVersion/i ) {
6932 dpurdie 184
            $ManifestFiles::Manifest_has_version = 0;
1125 alewis 185
 
186
        } elsif ( m/^--PkgSubdir=(.+)/i ) {
6932 dpurdie 187
            if ( $ManifestFiles::pkg_subdir ) {
1129 dpurdie 188
                ReportError ("ManifestFiles:--PkgSubdir option is only allowed once");
1125 alewis 189
                next;
190
            }
6932 dpurdie 191
            $ManifestFiles::pkg_subdir = $1;
1125 alewis 192
 
1129 dpurdie 193
        } elsif ( m/^--ImportManifest=(.+)/i ) {
6932 dpurdie 194
            my $import_info = ManifestFiles::_ImportManifest($1, $tier, $name);
1129 dpurdie 195
#DebugDumpData("ImportInfo", $import_info );
196
            push @files, {'manifest' => $import_info };
197
 
198
            #
199
            #   Fill in details unless already provided
200
            #
201
            $tier = $import_info->{'tier'} unless ( defined $tier );
202
            $name = $import_info->{'name'} unless ( defined $name );
203
            $imported_manifest = 1;
204
 
6978 dpurdie 205
        } elsif ( m/^--ManifestInsertionPoint(.*)/i ) {
206
            my $insert_info = ManifestFiles::_InsertPoint($1, $tier, $name);
207
#DebugDumpData("InsertPoint", $insert_info );
208
            push @files, {'insertPoint' => $insert_info };
209
 
210
        } elsif ( m/^--Template=(.+)/i ) {
211
            my $template_info = ManifestFiles::_Template($1, $tier, $name);
212
#DebugDumpData("TemplateInfo", $template_info );
213
 
5649 dpurdie 214
        } elsif (m/^--Md5/i) {
6314 dpurdie 215
            $include_md5 = 1;
216
            $useDefaultLineWidth = 0;
5649 dpurdie 217
 
5767 alewis 218
        } elsif (m/^--Dmf/i) {
219
            $generate_dmf = 1
220
 
221
        } elsif ( m/^--DmfVersion=(.+)/ ) {
222
            $generate_dmf = 1;
223
            $dmf_version = $1;
224
 
6314 dpurdie 225
        } elsif ( m/^--LineLength=(\d+)$/i ) {
6932 dpurdie 226
            $ManifestFiles::ManifestLineWidth = $1;
6314 dpurdie 227
            $useDefaultLineWidth = 0;
228
 
6364 dpurdie 229
        } elsif (m/^--SubManifest/i) {
230
            $is_sub_manifest = 1;
6932 dpurdie 231
            $ManifestFiles::Manifest_has_version = 0;
232
            $name = $::ScmPlatform unless $name;
233
            $ManifestFiles::pkg_subdir = $name unless $ManifestFiles::pkg_subdir;
234
            $tier = 0 unless defined($tier);
6364 dpurdie 235
 
6932 dpurdie 236
        } elsif (m/^--(No)?Signatures/i) {
237
           $ManifestFiles::noSigs = !! $1;
238
 
239
        } elsif (m/^--(No)?Warn/i) {
240
           $ManifestFiles::noWarn = !! $1;
241
 
7205 sdenys 242
        } elsif (m/^--UseFullVersion/i) {
7199 sdenys 243
            $ManifestFiles::useFullVersion = 1;
244
 
1119 dpurdie 245
        } else {
246
            ReportError ("ManifestFiles: Unknown option or argument: $_");
247
 
248
        }
249
    }
250
 
251
    #
252
    #   Sanity test the user options
253
    #
254
    ReportError ("ManifestFiles: No name specified")
255
        unless $name;
256
    ReportError ("ManifestFiles: No tier specified")
1129 dpurdie 257
        unless defined ($tier);
6302 dpurdie 258
    ReportError ("ManifestFiles: Cannot mix --Debian/-Apk/--SrcFile with --MugPackage in one directive")
1129 dpurdie 259
        if ( $mug_dir && (@files || $imported_manifest) );
1119 dpurdie 260
    ReportError ("ManifestFiles: Must specify files to add to Manifest")
1129 dpurdie 261
        unless ( $mug_dir ||  @files || $imported_manifest);
1119 dpurdie 262
    ErrorDoExit();
263
 
264
    #
6314 dpurdie 265
    #   Set ManifestLineWidth
266
    #   The default is largely historical - for MOS
267
    #   
6932 dpurdie 268
    unless (defined $ManifestFiles::ManifestLineWidth) {
269
        $ManifestFiles::ManifestLineWidth = $useDefaultLineWidth ? 79 : 0;
6314 dpurdie 270
    }
6932 dpurdie 271
    Verbose("ManifestLineWidth:$ManifestFiles::ManifestLineWidth");
6314 dpurdie 272
 
273
    #
1119 dpurdie 274
    #   Save information for processing at the end of the parsing phase
275
    #   Data collected from ALL the ManifestFiles directives will be collected
276
    #   and processed into one Manifest file
277
    #
278
    my %data;
279
    $data{tier} = $tier;
280
    $data{name} = $name;
281
    $data{files} = \@files;
6306 dpurdie 282
    $data{fileVersions} = \%fileVersions;
1119 dpurdie 283
    $data{mugdir} = $mug_dir;
6932 dpurdie 284
    $data{pkgsubdir} = $ManifestFiles::pkg_subdir;
5649 dpurdie 285
    $data{md5} = $include_md5;
5767 alewis 286
    $data{dmf} = $generate_dmf;
287
    $data{arch} = $default_arch;
288
    $data{dmf_version} = $dmf_version;
6364 dpurdie 289
    $data{is_sub_manifest} = $is_sub_manifest;
5767 alewis 290
 
1129 dpurdie 291
#DebugDumpData("DirectiveData", \%data );
1119 dpurdie 292
 
6932 dpurdie 293
    push @ManifestFiles::Manifests, \%data;
6302 dpurdie 294
}
1119 dpurdie 295
 
6932 dpurdie 296
#==================================================================================================
297
#   End of externally exposed methods
6933 dpurdie 298
#       The remainder is package-internal
6932 dpurdie 299
#
300
package ManifestFiles;
301
 
302
use strict;
303
use warnings;
304
use Digest::file qw(digest_file_hex);
305
use Digest::file qw(digest_file_base64);
306
use File::Spec::Functions qw(rel2abs);
307
use File::Basename qw(dirname);
308
 
309
use JatsError;
310
use FileUtils;
311
use ReadBuildConfig;
312
use ArrayHashUtils;
313
use JatsSystem;
314
 
315
#
316
#   Variables
317
#   Config - must be 'our'
318
#
319
our @Manifests;                     # Manifest entries
320
our $Manifest_has_version = 1;      # Create Manifest_xxxx by default
321
our $pkg_subdir;                    # Alternate packaging
322
our $ManifestLineWidth;             # Max length of lines
323
 
324
our %package_dirs;                  # Package dirs discovered and used
325
our $ManifestFiles;                 # Files in the Manifest
326
our $noWarn = 0;                    # Control unused package warnings
7199 sdenys 327
our $useFullVersion = 0;            # Use the full version to build the manifest contents
6932 dpurdie 328
our $pkgBase;                       # Where the package is being sourced from
6933 dpurdie 329
our $noSigs = 1;                    # Control signature generation (Force noSigs. could use use undef)
6978 dpurdie 330
our $templateMode;                  # In templating mode
6981 dpurdie 331
our $localInstall;                  # Install or Package the manifest
6932 dpurdie 332
 
333
#
334
#   Internal
6962 dpurdie 335
#   Used while generating a manifest
6932 dpurdie 336
#
337
my $certName;                       # Signing Cert Name
338
my $certFile;                       # Path to the certificate
339
my $keyFile;                        # Path to the keyfile
340
my $opensslProg;                    # Path to openssl program
341
my $opensslConf;                    # Path to openssl config
6962 dpurdie 342
my $manifestName;                   # Name of the current manifest file
6932 dpurdie 343
 
344
BEGIN {
345
    my $path = rel2abs( __FILE__ );
346
    $pkgBase = dirname( $path );
347
}
348
 
6302 dpurdie 349
#-------------------------------------------------------------------------------
6932 dpurdie 350
# Bring in the DMF build requirements.
351
use lib $pkgBase;
352
use Archive::Zip qw( :ERROR_CODES :CONSTANTS );
353
use JSON;
354
 
355
#-------------------------------------------------------------------------------
6302 dpurdie 356
# Function        : _LocateDebianFile
357
#
358
# Description     : Locate a debian file
359
#                   Internal Function
360
#
361
#                   Scan packages for the Debian package specified
362
#                   The user provides the base name of the package
363
#                   A Debian Package name has several fields
364
#                   These are:
365
#                       1) Base Name - Provided by the user
6730 dpurdie 366
#                       2) Version - Default Version will be wildcarded if it hadn't been provided by user
6302 dpurdie 367
#                       3) Architecture - Wildcarded. Uses bin/arch directory
368
#
369
#                   Expect to find Debian Packages in the bin/PLATFORM subdir
370
#
371
# Inputs          : Debian base name, complete with suboptions
372
#
373
# Returns         : Full path of the file
374
#
375
sub _LocateDebianFile
376
{
377
    my ($arg, $arch, $product) = @_;
378
    Verbose("LocateDebianFile: Processing: $arg");
379
 
380
    my @type = qw( P D );
381
    my @debian_file_path;
6306 dpurdie 382
    my @searchPath;
6730 dpurdie 383
    my $version='*';
6302 dpurdie 384
 
1119 dpurdie 385
    #
6302 dpurdie 386
    #   Extract sub-options
387
    #       --Prod[uction]
388
    #       --Debug
389
    #       --Arch[itecture]=yyy
390
    #       --Product=yyy
6730 dpurdie 391
    #       --Version=yy.yy.yyyyy  default value is wildcard 
1119 dpurdie 392
    #
6302 dpurdie 393
    my ($base_name, @opts) = split( ',', $arg );
394
    foreach ( @opts )
395
    {
396
        if ( m/^--Arch(.*)=(.+)/ ) {
397
            $arch=$2;
398
        } elsif ( m/^--Product=(.+)/ ) {
399
            $product=$1;
400
        } elsif ( m/^--Prod/ ) {
401
            @type = 'P';
402
        } elsif ( m/^--Debug/ ) {
403
            @type = 'D';
6730 dpurdie 404
        } elsif ( m/^--Version=(.+)/ ) {
405
            $version=$1;
6302 dpurdie 406
        } else {
407
            Warning ('--Debian: Unknown Option: ' . $_);
408
        }
409
    }
410
 
5649 dpurdie 411
    #
6302 dpurdie 412
    #   Create a list of products
413
    #   ie: PRODUCT_ARCH
1119 dpurdie 414
    #
6302 dpurdie 415
    my @products;
416
    push @products, $product . '_' . $arch if ( $product );
417
    push @products, $arch;
418
 
1119 dpurdie 419
    #
6302 dpurdie 420
    #   Scan all packages for the specified debian package
1119 dpurdie 421
    #
6302 dpurdie 422
    foreach my $package_dir ( getPackagePaths ('--All') )
1119 dpurdie 423
    {
6302 dpurdie 424
        foreach my $type ( @type )
1119 dpurdie 425
        {
6302 dpurdie 426
            foreach my $prd ( @products )
1119 dpurdie 427
            {
6302 dpurdie 428
                foreach my $joiner ( qw(/ .) )
1119 dpurdie 429
                {
6302 dpurdie 430
                    my $dir = "$package_dir/bin$joiner$prd$type";
6306 dpurdie 431
                    UniquePush(\@searchPath, $dir);
5873 acammell 432
                    next unless ( -d $dir );
6734 dpurdie 433
                    my @files = glob ( "$dir/${base_name}_${version}*.deb" );
5873 acammell 434
                    next unless ( @files );
435
                    push @debian_file_path, @files;
436
                    $package_dirs{$package_dir}{used} = 1;
437
                }
438
            }
1119 dpurdie 439
        }
6302 dpurdie 440
        foreach my $type ( @type )
441
        {
442
            foreach my $prd ( @products )
443
            {
444
                my $dir = "$package_dir";
6306 dpurdie 445
                UniquePush(\@searchPath, $dir);
6730 dpurdie 446
                next unless ( -d $dir ); 
447
                if ( $version eq "*" ){
448
                    my @files = glob ( "$dir/${base_name}_${version}_${prd}_${type}.deb" );
449
                    if ( @files ){
450
                        push @debian_file_path, @files;
451
                        $package_dirs{$package_dir}{used} = 1;
452
                    }
453
                }
454
                else{
455
                    if( -e "$dir/${base_name}_${version}_${prd}_${type}.deb" ) {
456
                        my $file = "$dir/${base_name}_${version}_${prd}_${type}.deb";
457
                        push(@debian_file_path, $file);
458
                        $package_dirs{$package_dir}{used} = 1;
459
                    } elsif ( -e "$dir/${base_name}_${version}_${prd}.deb") {
460
                        my $file = "$dir/${base_name}_${version}_${prd}.deb";
461
                        push(@debian_file_path, $file);
462
                        $package_dirs{$package_dir}{used} = 1;
6734 dpurdie 463
                    }
6730 dpurdie 464
                }
6302 dpurdie 465
            }
466
        }
1119 dpurdie 467
    }
468
 
6306 dpurdie 469
    #
470
    #   Keep user informed
471
    #   Report errors and provide useful information
472
    #
473
    if (IsVerbose(1) || IsDebug(1) || $#debian_file_path != 0)
474
    {
475
        Message ("Search for ($base_name). In search Path", @searchPath);
476
    }
6730 dpurdie 477
 
6302 dpurdie 478
    ReportError ("Required Debian package not found: $base_name") unless @debian_file_path;
479
    ReportError ("Multiple matching Debian Packages located: $base_name", @debian_file_path ) if ( $#debian_file_path > 0 );
480
    return $debian_file_path[0];
481
}
482
 
483
#-------------------------------------------------------------------------------
484
# Function        : _LocateApkFile
485
#
486
# Description     : Locate a APK file
487
#                   Internal Function
488
#
489
#                   Scan packages for the APK package specified
490
#                   The user provides the base name of the package
491
#                   APK ( Android Packages )
492
#                   Expect to have a '-release' or '-debug' suffix, except those provided via a
493
#                   3rd party SDK.
494
#                   Expect to find APK Packages in the bin/PLATFORM(P/D) subdir
495
#                   Expect to find -debug in the <PLATFORM>D directory
496
#                   Expect to find -release' in the <PLATFORM>P directory
497
#                   
498
#                   Allow for:
499
#                       Full path to .apk file
500
#                       .apk in package root directory
501
#
502
# Inputs          : Apk base name, complete with suboptions
503
#
6306 dpurdie 504
# Returns         : Full path of the file $; PackageVersion
505
#                   apk packages do not appear to have version numbers in the file name
506
#                   Retain package version number for later processing
6302 dpurdie 507
#
508
sub _LocateApkFile
509
{
510
    my ($arg, $arch) = @_;
511
    Verbose("LocateApkFile: Processing: $arg");
512
 
513
    my @type = qw( P );
514
    my @apk_file_path;
515
    my %type = ('P' => '-release', 'D' => '-debug' );
6306 dpurdie 516
    my @searchPath;
6302 dpurdie 517
 
1119 dpurdie 518
    #
6302 dpurdie 519
    #   Extract sub-options
520
    #       --Prod[uction]
521
    #       --Debug
522
    #       --Architecture=yyy
1119 dpurdie 523
    #
6302 dpurdie 524
    my ($base_name, @opts) = split( ',', $arg );
525
    foreach ( @opts )
1119 dpurdie 526
    {
6302 dpurdie 527
        if ( m/^--Arch(.*)=(.+)/ ) {
528
            $arch=$2;
529
        } elsif ( m/^--Prod/ ) {
530
            @type = 'P';
531
        } elsif ( m/^--Debug/ ) {
532
            @type = 'D';
533
        } else {
534
            Warning ('--Apk: Unknown Option: ' . $_);
1119 dpurdie 535
        }
6302 dpurdie 536
    }
1119 dpurdie 537
 
6302 dpurdie 538
    #
539
    #   Scan all packages for the specified APK package
540
    #   Try:
541
    #       Raw name - for apks from the SDK or 3rd parties
542
    #       PLATFORM(P|D)/baseName-(release|debug) - Expected
543
    #       baseName-(release|debug) - Repackaged badly
6306 dpurdie 544
    # 
545
    foreach my $pkgEntry ( getPackageList() )
6302 dpurdie 546
    {
6306 dpurdie 547
        next if ($pkgEntry->getType() eq 'interface');
548
        my $pkgVersion = $pkgEntry->getVersion();
549
 
550
        my $pkgLocal = $pkgEntry->getBase(2);
551
        my $pkgRoot = $pkgEntry->getDir();
1119 dpurdie 552
 
6306 dpurdie 553
        #
554
        #   Helper function
555
        #   Uses closure
556
        #   Notes: Test the package in dpkg_archive so that we can retain the package-version
557
        #          Use the version in the interface directory if BuildPkgArchive
558
        #   $pkgLocal - Local base of the package. May in the interface directory
559
        #   $pkgRoot  - Directory in dpkg_achive. Will have version info
560
        #   $subdir   - subdir within the package
561
        #   $fname    - File to look for
562
        #   
563
        #   Returns: Nothing
564
        #   Maintains: apk_file_path. Tupple: filename, PackageVersion
565
        #
566
        my $testOneFile = sub {
567
            my ( $subdir, $fname) = @_;
568
            my $testFile = "$pkgRoot/$subdir";
569
            $testFile =~ s~//~/~g;
570
            $testFile =~ s~/$~~;
571
            UniquePush(\@searchPath, $testFile);
572
            return unless (-d $testFile);
6302 dpurdie 573
 
6306 dpurdie 574
            $testFile .= '/' . $fname;
575
            if (-f $testFile ) {
576
                if ($pkgLocal ne $pkgRoot) {
577
                    my $testFile2 = "$pkgLocal/$subdir/$fname";
578
                    $testFile2 =~ s~//~/~g;
579
                    if ( -f $testFile2 ) {
580
                        $testFile = $testFile2;
581
                    }
582
                }
583
 
584
             $testFile = join($;, $testFile, $pkgVersion);
585
             push @apk_file_path, $testFile;
586
            }
587
        };
588
 
589
        #
590
        #   Test for the specified file in the package root
591
        #
592
        $testOneFile->("", "${base_name}.apk");
593
 
594
        #
595
        #   Test for BIN/PLATFORM
596
        #   
6302 dpurdie 597
        foreach my $type ( @type )
1119 dpurdie 598
        {
6302 dpurdie 599
            my $typeSuffix = $type{$type};
6306 dpurdie 600
            foreach my $joiner ( qw(/ .) ) {
601
                $testOneFile->("bin$joiner$arch$type","${base_name}${typeSuffix}.apk");
1119 dpurdie 602
            }
603
        }
6306 dpurdie 604
 
6302 dpurdie 605
        foreach my $type ( @type )
606
        {
607
            my $typeSuffix = $type{$type};
6306 dpurdie 608
            $testOneFile->("","${base_name}${typeSuffix}.apk");
6302 dpurdie 609
        }
6306 dpurdie 610
        $package_dirs{$pkgRoot}{used} = 1 if (@apk_file_path) ;
1119 dpurdie 611
    }
1129 dpurdie 612
 
6306 dpurdie 613
    #
614
    #   Keep user informed
615
    #   Report errors and provide useful information
616
    #
617
    if (IsVerbose(1) || IsDebug(1) || $#apk_file_path != 0)
618
    {
619
        Message ("Search for ($base_name). In search Path", @searchPath);
620
    }
621
 
6302 dpurdie 622
    ReportError ("Required APK package not found: $base_name") unless @apk_file_path;
623
    ReportError ("Multiple matching APK Packages located: $base_name", @apk_file_path ) if ( $#apk_file_path > 0 );
6306 dpurdie 624
 
625
#DebugDumpData("apk_file_path", \@apk_file_path);
6302 dpurdie 626
    return $apk_file_path[0];
627
}
628
 
629
#-------------------------------------------------------------------------------
630
# Function        : _LocateMugDir
631
#
632
# Description     : Locate the directory containing the mugfiles
633
#                   Internal Function
634
#
635
# Inputs          : Mufile package, with embedded options
636
#
637
# Returns         : Full path
638
#
639
sub _LocateMugDir
640
{
641
    my ($mug_package) = @_;
642
 
1129 dpurdie 643
    #
6302 dpurdie 644
    #   Locate the mugfile subdir
1129 dpurdie 645
    #
6302 dpurdie 646
    my $package_name = $mug_package;
647
    my @dirs = 'mug';
648
    my $mug_dir;
649
 
1129 dpurdie 650
    #
6302 dpurdie 651
    #   Extract sub options
652
    #       --Subdir=xxxx,yyyy,zzzz
1129 dpurdie 653
    #
6302 dpurdie 654
    if ( $package_name =~ m/(.*?),--Subdir=(.*)/ )
1129 dpurdie 655
    {
6302 dpurdie 656
        $package_name = $1;
657
        @dirs = split( ',', $2 );
658
    }
1129 dpurdie 659
 
6978 dpurdie 660
    my $package = ::GetPackageEntry( $package_name );
6302 dpurdie 661
    unless ( $package )
662
    {
663
        ReportError ("ManifestFiles: Package not known to build: $package_name");
664
        return undef;
665
    }
1129 dpurdie 666
 
6302 dpurdie 667
    foreach my $subdir ( @dirs )
668
    {
669
        my $dir = "$package->{'ROOT'}/$subdir";
670
        if ( -d $dir )
1129 dpurdie 671
        {
6302 dpurdie 672
            Warning ("Multiple Mugfile directories located. Only the first will be used",
673
                     "Ignoring: $subdir" )if ( $mug_dir );
674
            $mug_dir = $dir;
675
        }
676
    }
677
    ReportError ("Mugfile directory not found in package: $package_name")
678
        unless $mug_dir;
5105 dpurdie 679
 
6302 dpurdie 680
    return $mug_dir;
681
}
5105 dpurdie 682
 
1129 dpurdie 683
 
6302 dpurdie 684
#-------------------------------------------------------------------------------
685
# Function        : _ImportManifest
686
#
687
# Description     : Import an existing manifest
688
#
689
# Inputs          : Args    - PackageName[,Subdir=name,--ReWrite]
690
#                   tier    - May be null
691
#                   name    - May be null
692
#
693
# Returns         : A hash of data to be used later
694
#
695
sub _ImportManifest
696
{
697
    my ($args, $tier, $name) = @_;
698
    my @file_contents;
6364 dpurdie 699
    my @item_list;
1129 dpurdie 700
 
6302 dpurdie 701
    #
702
    #   Locate the mugfile subdir
703
    #
704
    my $package_name = $args;
705
    my @dirs = 'mug';
706
    my $pkg_dir;
707
    my $pkg_root;
708
    my $manifest;
709
    my $first_tier;
710
    my $first_name;
711
    my $rewrite;
712
 
713
    #
714
    #   Extract sub options
715
    #       --Subdir=xxxx,yyyy,zzzz
716
    #       --ReWrite
717
    #
718
    if ( $package_name =~ m/(.*?)(,.*)/ )
719
    {
720
        $package_name = $1;
721
        my @subargs = split(',--', $2);
722
        foreach ( @subargs)
5105 dpurdie 723
        {
6302 dpurdie 724
            next unless (length($_) > 0);
725
            if (m~^Subdir=(.*)~i){
726
                @dirs = split( ',', $1 );
5105 dpurdie 727
 
6302 dpurdie 728
            } elsif (m~^ReWrite~i) {
729
                $rewrite = 1;
730
 
731
            } else {
732
                ReportError("ManifestFiles: Unknown suboption to ImportManifest:" . $_);
1129 dpurdie 733
            }
734
        }
6302 dpurdie 735
    }
1129 dpurdie 736
 
6978 dpurdie 737
    my $package = ::GetPackageEntry( $package_name );
6302 dpurdie 738
    unless ( $package )
739
    {
740
        ReportError ("ManifestFiles: Package not known to build: $package_name");
741
        return undef;
742
    }
5105 dpurdie 743
 
6302 dpurdie 744
    if (defined ($rewrite) && ( !defined($tier) || !defined($name)))
745
    {
746
        ReportError ("ManifestFiles: ImportManifest. --ReWrite cannot be used unless tier and name are specified");
747
        return undef;
748
    }
1129 dpurdie 749
 
6302 dpurdie 750
    foreach my $subdir ( @dirs )
751
    {
752
        my $dir = "$package->{'ROOT'}/$subdir";
753
        my $root = $package->{'ROOT'};
754
        if ( -d $dir )
5105 dpurdie 755
        {
6302 dpurdie 756
            Warning ("Multiple Package directories located. Only the first will be used",
757
                     "Ignoring: $subdir" )if ( $pkg_dir );
758
            $pkg_dir = $dir;
759
            $pkg_root = $root;
5105 dpurdie 760
        }
6302 dpurdie 761
    }
1129 dpurdie 762
 
6302 dpurdie 763
    unless ($pkg_dir)
764
    {
765
        ReportError ("Package directory not found in package: $package_name");
766
        return undef;
767
    }
5105 dpurdie 768
 
6302 dpurdie 769
    #
770
    #   Determine Manifest File name
771
    #
772
    foreach my $file ( glob ($pkg_dir . '/Manifest*' ) )
773
    {
774
            next unless ( -f $file );
6990 dpurdie 775
            next if ( $file  =~ m~\.sig~i );
6302 dpurdie 776
            Warning ("Multiple Manifest Files find. Only the first will be used",
777
                     "Using: $manifest",
778
                     "Ignoring: $file" ) if ( $manifest );
779
            $manifest = $file;
780
    }
781
 
782
    unless ($manifest)
783
    {
784
        ReportError ("ImportManifest. No Manifest found: $package_name");
785
        return undef;
786
    }
787
 
788
 
789
    #
790
    #
791
    #
792
    open (MF, '<', $manifest ) || Error ("Cannot open the Manifest file: $manifest", $!);
793
    while ( <MF> )
794
    {
1129 dpurdie 795
        #
6302 dpurdie 796
        #   Clean trailing whitespace ( line-feed and new lines )
797
        #   Comment out [Version] data
1129 dpurdie 798
        #
6302 dpurdie 799
        s~\s+$~~;
800
        s~(\s*\[Version])~#$1~;
801
 
5649 dpurdie 802
        #
6981 dpurdie 803
        #   Parse lines and determine files
6302 dpurdie 804
        #
805
        next unless ( $_ );
6364 dpurdie 806
        if (( m~\s*#~ ) || ( m~\s*\[~ )) {
807
            push @item_list, { 'comment' => $_ };
808
            next;
809
        }
810
        my( $aname, $atier, $afile, @additionnal_info) = split(/\s*\,\s*/, $_);
1129 dpurdie 811
#            print "---------- $_\n";
812
#            print "T: $atier, N:$aname, F:$afile\n";
6364 dpurdie 813
        my $file =  { 'file_name' => $afile
814
                    , 'file_info' => \@additionnal_info
815
                    };
816
        push @item_list, $file;
1129 dpurdie 817
 
6302 dpurdie 818
        #
819
        #   Rewrite the name and tier
820
        #
821
        if ($rewrite)
822
        {
823
            $_ = join(',', $name, $tier, $afile);
824
            $first_tier = $tier;
825
            $first_name = $name;
826
        }
827
        else
828
        {
1129 dpurdie 829
            #
6302 dpurdie 830
            #   Capture first tier and name
1129 dpurdie 831
            #
6302 dpurdie 832
            $first_tier = $atier unless ( defined $first_tier );
833
            $first_name = $aname unless ( defined $first_name );
1129 dpurdie 834
        }
6302 dpurdie 835
    }
836
    continue
837
    {
838
        push @file_contents, $_;
839
    }
840
    close MF;
1129 dpurdie 841
 
6302 dpurdie 842
    #
843
    #   Create a hash of data that describes the manifest that has
844
    #   just been read in.
845
    #
846
    $package_dirs{$pkg_root}{used} = 1;
847
    $manifest =~ s~.*/~~;
848
    return { 'contents' => \@file_contents,
6364 dpurdie 849
              'items' => \@item_list,
6302 dpurdie 850
              'file_base' => $pkg_dir,
851
              'manifest' => $manifest,
852
              'pkg_dir' => $pkg_root,
853
              'tier' => $first_tier,
854
              'name' => $first_name,
855
              'rewrite' => $rewrite,
856
            };
1119 dpurdie 857
}
858
 
859
#-------------------------------------------------------------------------------
6978 dpurdie 860
# Function        : _InsertPoint
861
#
862
# Description     : Create a Manifest Insertion Point
863
#
864
# Inputs          : Args    - [,--All,--Name,--Name=xxxx,--Tier,--Tier=Name, --Current]
865
#                   tier    - May be null
866
#                   name    - May be null
867
#
868
# Returns         : A hash of data to be used later
869
#
870
sub _InsertPoint
871
{
872
    my ($args, $tier, $name) = @_;
873
    my @item_list;
874
 
875
    ReportError("ManifestFiles: ManifestInsertionPoint. Name not yet specified") unless defined $name;
876
    ReportError("ManifestFiles: ManifestInsertionPoint. Tier not yet specified") unless defined $tier;
877
 
878
    my $argName = $name;
879
    my $argTier = $tier;
880
 
881
    #
882
    #   Extract sub options
883
    #
884
    my @subargs = split(',--', $args);
885
    foreach ( @subargs)
886
    {
887
        next unless (length($_) > 0);
888
        if (m~^All$~i){
889
            $argName = '*';
890
            $argTier = '*';
891
 
892
        } elsif (m~^Name(=(.*))?~i){
893
            if ( $1 ){
894
                $argName = $2;
895
            } else {
896
                $argName = $name;
897
            }
898
 
899
        } elsif (m~^Tier(=(.*))?~i){
900
            if ( $1 ){
901
                $argTier = $2;
902
            } else {
903
                $argTier = $tier;
904
            }
905
 
906
        } elsif (m~^Current$~i){
907
            $argName = $name;
908
            $argTier = $tier;
909
 
910
        } else {
911
            ReportError("ManifestFiles: Unknown suboption to ManifestInsertionPoint:" . $_);
912
        }
913
    }
914
 
915
    return { 'tier' => $argTier,
916
             'name' => $argName,
917
           };
918
}
919
 
920
#-------------------------------------------------------------------------------
921
# Function        : _Template
922
#
923
# Description     : Capture templating information
924
#
925
# Inputs          : --Template=Package[,--Subdir=subdir,File=name] 
926
#                   tier    - May be null
927
#                   name    - May be null
928
#
929
# Returns         : A hash of data to be used later
930
#
931
sub _Template
932
{
933
    my ($args, $tier, $name) = @_;
934
    my $subdir = 'mug';
935
    my $manifest;
936
 
937
    #
938
    #   Can only use the Template directive once
939
    #   
940
    if ($templateMode) {
941
        ReportError ("ManifestFiles:--Template option is only allowed once");
942
        return undef;
943
    }
944
    $templateMode = 1;
945
 
946
 
947
    #
948
    #   Locate the mugfile subdir
949
    #
950
    my $package_name = $args;
951
 
952
    #
953
    #   Extract sub options
954
    #       --Subdir=xxxx
955
    #       --File=name
956
    #       
957
    if ( $package_name =~ m/(.*?)(,.*)/ )
958
    {
959
        $package_name = $1;
960
        my @subargs = split(',--', $2);
961
        foreach ( @subargs)
962
        {
963
            next unless (length($_) > 0);
964
            if (m~^Subdir=(.*)~i){
965
                $subdir = $1;
966
 
967
            } elsif (m~^File=(.*)~i) {
968
                $manifest = $1;
969
 
970
            } else {
971
                ReportError("ManifestFiles: Unknown suboption to Template:" . $_);
972
            }
973
        }
974
    }
975
 
976
    my $package = ::GetPackageEntry( $package_name );
977
    unless ( $package )
978
    {
979
        ReportError ("ManifestFiles: Package not known to build: $package_name");
980
        return undef;
981
    }
982
 
983
    my $pkg_root = $package->{'ROOT'};
984
    my $pkgDir = CatPaths( $pkg_root, $subdir);
985
    unless (-d $pkgDir) {
986
        ReportError ("ManifestFiles: Template subdir not found in $package_name: $subdir");
987
        return undef;
988
    }
989
 
990
    #
991
    #   Determine Manifest File name, unless specified by user
992
    #
993
    unless ($manifest) {
994
        foreach my $file ( glob ($pkgDir . '/Manifest*' ) )
995
        {
996
                next unless ( -f $file );
6990 dpurdie 997
                next if ( $file  =~ m~\.sig~i );
6978 dpurdie 998
                if ( $manifest ) {
999
                    Warning ("Multiple Manifest Files find. Only the first will be used",
1000
                             "Using: $manifest",
1001
                             "Ignoring: $file" ) ;
1002
                    next;
1003
                }
1004
                $manifest = $file;
1005
        }
1006
        unless ($manifest)
1007
        {
1008
            ReportError ("ImportManifest. No Manifest template found: $package_name");
1009
            return undef;
1010
        }
1011
    } else { 
1012
        $manifest = CatPaths($pkgDir, $manifest);
1013
    }
1014
 
1015
    unless (-f $manifest) {
1016
        ReportError ("ImportManifest. No Manifest template found: $package_name, $subdir, $manifest");
1017
        return undef;
1018
    }
1019
 
1020
    #
1021
    #   Return paramters for later processing
1022
    #
1023
 
1024
    $package_dirs{$pkg_root}{used} = 1;
6981 dpurdie 1025
    $templateMode = { 'manifest' => $manifest,
6978 dpurdie 1026
             'pkg_dir' => $pkg_root,
1027
             'subdir' => $subdir,
1028
             'manifest_dir' => $pkgDir,
1029
             'package' => $package_name,
6981 dpurdie 1030
    };
1031
    return $templateMode; 
6978 dpurdie 1032
}
1033
 
1034
#-------------------------------------------------------------------------------
6932 dpurdie 1035
# Function        : Generate
1119 dpurdie 1036
#
1037
# Description     : Internal Function
1038
#                   Process all the collected data and create directives
1039
#                   for the creation of the manifest
1040
#
1041
#                   This function will be called, just before the Makefile
1042
#                   is created. The function will:
1043
#                       1) Create the Manifest File
1044
#                       2) Package the Manifest File
1045
#                       3) Package the manifest file contents
1046
#
1047
#                   using (mostly) normal makefile.pl directives.
1048
#
1049
# Inputs          : None
1050
#
1051
# Returns         : Nothing
1052
#
6932 dpurdie 1053
sub Generate
1119 dpurdie 1054
{
6932 dpurdie 1055
    Debug ("Generate");
1119 dpurdie 1056
    Message ("Generating Manifest File");
1123 dpurdie 1057
 
1058
    #
1059
    #   Need at least one Manifest Entry
1060
    #
6932 dpurdie 1061
#DebugDumpData ( "Manifests", \@Manifests );
1123 dpurdie 1062
    return unless ( @Manifests );
1119 dpurdie 1063
 
1064
    #
6932 dpurdie 1065
    #   Init the signing subsystem
1066
    # 
1067
    GenSigInit();
1068
 
1069
    #
1125 alewis 1070
    #   Determine the target packaging directory
1071
    #   Default is .../mug
1072
    #
6962 dpurdie 1073
    $pkg_subdir = 'mug';
1129 dpurdie 1074
    if ( exists $Manifests[0]->{pkgsubdir} && defined $Manifests[0]->{pkgsubdir} )
1125 alewis 1075
    {
1076
        my $subdir = $Manifests[0]->{pkgsubdir};
6962 dpurdie 1077
        $pkg_subdir .= '/' . $subdir;
1078
        $pkg_subdir =~ s~^mug/mug~mug~;
1125 alewis 1079
    }
1080
 
1081
    #
1119 dpurdie 1082
    #   Create the Manifest File as we process the lists
1125 alewis 1083
    #   Place this in the 'lib' directory:
1119 dpurdie 1084
    #       - So that it will be deleted on clobber
1123 dpurdie 1085
    #       - So that it can be placed in a target-specific subdir
1125 alewis 1086
    #       - So that we can have one per makefile.pl
1119 dpurdie 1087
    #
1088
    Error ("ManifestFiles: Needs local directory specified in build.pl") unless ( $::ScmLocal );
1089
 
1125 alewis 1090
    my $manifest_dir = "$::ScmPlatform.LIB";
1119 dpurdie 1091
    System( "$::GBE_BIN/mkdir -p $manifest_dir" );
1092
 
6962 dpurdie 1093
    $manifestName = $manifest_dir . '/Manifest';
1094
    $manifestName .= '_' . $::ScmBuildVersion if ( $Manifest_has_version );
6981 dpurdie 1095
    PackageFile ('*', $manifestName, '--Subdir=' . $pkg_subdir, '--Strip' );
6962 dpurdie 1096
    ::ToolsetGenerate( $manifestName );
5649 dpurdie 1097
 
6962 dpurdie 1098
    Verbose ("Generate: File: $manifestName");
1119 dpurdie 1099
 
6962 dpurdie 1100
    open (MF, '>', $manifestName ) || Error ("Cannot create the Manifest file: $manifestName");
5711 kspencer 1101
    binmode (MF);
7199 sdenys 1102
    my $version;
1103
    if ($useFullVersion == 1) {
1104
        $version = $::ScmBuildVersionFull;
1105
    } else {
1106
        $version = $::ScmBuildVersion;
1107
    }
1108
 
6364 dpurdie 1109
    if ($Manifests[0]->{is_sub_manifest} == 1) {
7199 sdenys 1110
        print_mf ("# Package $::ScmBuildPackage $version built: $::CurrentTime");
6364 dpurdie 1111
    } else {
1112
        print_mf ("# PackageName: $::ScmBuildPackage");
7199 sdenys 1113
        print_mf ("# PackageVersion: $version");
6364 dpurdie 1114
        print_mf ("# BuildDate: $::CurrentTime");
1115
        print_mf ("#");
7199 sdenys 1116
        print_mf ("[Version],$version");
6364 dpurdie 1117
        print_mf ("#");
1118
    }
1119 dpurdie 1119
 
1120
    #
6932 dpurdie 1121
    #   Insert the certificate used to verify the files
1122
    #       Currently we only handle one certificate
1123
    #       Certificate name must end in .crt
1124
    #   In production the .crt file MUST be signed by the VixManifestRoot-CA
1125
    #   The assumtion is that the public key for VixManifestRoot-CA is on the device
1126
    #
1127
    unless (($Manifests[0]->{is_sub_manifest} == 1) || $noSigs) {
1128
        print_mf ("");
1129
        print_mf ("#");
1130
        print_mf ("# Signing Certificate");
1131
        print_mf ("[Certificate],$certName");
1132
 
6981 dpurdie 1133
        PackageFile ('*', $certFile, '--Subdir=' . $pkg_subdir, '--Strip' );
6932 dpurdie 1134
    }
6981 dpurdie 1135
 
6932 dpurdie 1136
    #
6981 dpurdie 1137
    #   If in templating mode, then process the base template
1119 dpurdie 1138
    #
6981 dpurdie 1139
    if ($templateMode) {
1140
        templateProcessing();
1119 dpurdie 1141
 
6981 dpurdie 1142
    } else {
1119 dpurdie 1143
 
1144
        #
6981 dpurdie 1145
        #   Process each tier in the order presented in the source file
1119 dpurdie 1146
        #
6981 dpurdie 1147
        foreach my $entry ( @Manifests )
1119 dpurdie 1148
        {
6981 dpurdie 1149
            DmfGenerate($entry) if ( $entry->{dmf} );
1150
            processManifestEntry($entry);
1151
        }
1152
    }
1123 dpurdie 1153
 
6981 dpurdie 1154
    #
1155
    #   Complete the creation of the Manifest File
1156
    #
1157
    print_mf ("# end of $::ScmBuildPackage");
1158
    close MF;
1159
    ErrorDoExit();
6978 dpurdie 1160
 
6981 dpurdie 1161
    #
1162
    #   Post process files from the manifest
1163
    #   May include signature generation
1164
    GenSignatures();
6978 dpurdie 1165
 
6981 dpurdie 1166
    #
1167
    #   Sanity test of packages that did not provide a debian file
1168
    #   Just a hint that something may have been missed
1169
    #
1170
    unless ($noWarn) {
1171
        my @not_used_packages;
1172
        foreach my $package_dir ( getPackagePaths ('--All') ) {
1173
            next if ( $package_dir =~ m~/manifest-tool/~ );
1174
            unless ( exists $package_dirs{$package_dir}{used} ) {
1175
                push @not_used_packages, $package_dir;
6978 dpurdie 1176
            }
6981 dpurdie 1177
        }
1178
        if ( @not_used_packages ) {
1179
            Warning ("Packages that did not contribute packages to the manifest:",
1180
                      @not_used_packages );
1181
        }
1182
    }
1183
}
6978 dpurdie 1184
 
6981 dpurdie 1185
#-------------------------------------------------------------------------------
1186
# Function        : processManifestEntry 
1187
#
1188
# Description     : Process a single Manifest entry 
1189
#
1190
# Inputs          : Globals
1191
#
1192
# Returns         : 
1193
#
1194
sub processManifestEntry
1195
{
1196
    my ($entry) = @_;
1197
#DebugDumpData ( "Manifest Entry", $entry );
1125 alewis 1198
 
6981 dpurdie 1199
    my $tier = $entry->{tier};
1200
    my $name = $entry->{name};
1201
    my $include_md5 = $entry->{md5};
1202
    my $last_was_comment = 0;
1203
    my $last_was_insert = 0;
1204
 
1205
    #
1206
    #   Flag that this entry has been processed
1207
    #
1208
    $entry->{wasProcessed}++;
1209
 
1210
    #
1211
    #   Insert all the files that have been specified
1212
    #   The user specified order is preserved
1213
    #
1214
    #   Entries may be either a file or a comment
1215
    #   Comments: Merge multiple comments and create blocks
1216
    #
1217
    #
1218
    my @files = @{ $entry->{files} };
1219
    foreach my $fentry ( @files ) {
1220
        if ( my $cmt = $fentry->{'cmt'} ) {
1221
            print_mf ('') unless ( $last_was_comment ) ;
1222
            print_mf ( map (('# ' . $_) , split ("\n", $cmt) ));
1223
            $last_was_comment = 1;
1224
            next;
1225
        }
1226
 
1227
        print_mf ('#') if ( $last_was_comment);
1228
        $last_was_comment = 0;
1229
 
1230
        if ( my $ip = $fentry->{'insertPoint'} ) {
1231
           #
1232
           #   Create an insertion point
1233
           #   Looks like a comment for the purposes of backward compatability
1234
           #
1235
 
1236
           print_mf ('') unless $last_was_insert;
1237
           print_mf ("##INSERT POINT [Name:$ip->{name}] [Tier:$ip->{tier}]");
1238
           $last_was_insert = 1;
1239
           next;
1240
        }
1241
        print_mf ('#') if ( $last_was_insert);
1242
        $last_was_insert = 0;
1243
 
1244
        if ( my $file = $fentry->{'file'} ) {
1245
            my $base_file = StripDir( $file );
1246
            my @items = ($name, $tier, $base_file);
1247
            if ($include_md5) {
1248
                my $md5 = digest_file_hex($file, 'MD5');
1249
                push @items, "MD5=$md5" ;
1125 alewis 1250
            }
6981 dpurdie 1251
            if (exists $entry->{fileVersions} && exists $entry->{fileVersions}{$file} ) {
1252
                push @items, "VERSION=" . $entry->{fileVersions}{$file};
1253
            }
1254
            print_mf (join (',', @items));
1255
            PackageManifestFile ($name, $tier, $file );
1256
        }
1129 dpurdie 1257
 
6981 dpurdie 1258
        if ( my $file = $fentry->{'filenocopy'} ) {
1259
            print_mf ("$name,$tier,$file");
1260
        }
1261
 
1262
        if ( my $emf = $fentry->{'manifest'} ) {
1263
            #
1264
            #   Insert the entire manifest
1265
            #   Items are:
1266
            #        contents
1267
            #        items:
1268
            #               file_name + arrays of file_info
1269
            #           or  comment line to copy
1270
            #        file_base
1271
            #        manifest
1272
            #
1129 dpurdie 1273
#DebugDumpData ( "Embedded Manifest Entry", $emf );
6981 dpurdie 1274
            if ($emf->{'rewrite'}) {
1275
                foreach my $item ( @{$emf->{'items'}}) {
1276
                    if (defined($item->{'file_name'}))
1277
                    {
1278
                        my @items = ($name, $tier, $item->{'file_name'});
1279
                        my $md5_added = 0;
1280
                        foreach my $info (@{$item->{'file_info'}}) {
1281
                            push @items, $info;
1282
                            $md5_added = 1 if ($info =~ m~^MD5=~i);
6364 dpurdie 1283
                        }
6981 dpurdie 1284
                        if ($include_md5 && $md5_added == 0) { # add md5 if requested and not already added from submanifest
1285
                            my $md5 = digest_file_hex($emf->{'file_base'} . '/' . $item->{'file_name'}, 'MD5');
1286
                            push @items, "MD5=$md5";
6364 dpurdie 1287
                        }
6981 dpurdie 1288
                        print_mf (join (',', @items));
1289
                        PackageManifestFile ( $name, $tier, $emf->{'file_base'} . '/' . $item->{'file_name'} );
6364 dpurdie 1290
                    }
6981 dpurdie 1291
                    elsif (defined($item->{'comment'})) {
1292
                        print_mf($item->{'comment'});
1293
                    }
6364 dpurdie 1294
                }
6981 dpurdie 1295
                print_mf('#');
1296
            }
1297
            else {
1298
                print_mf ($_) foreach  ( @{$emf->{'contents'}} );
1299
                foreach my $item ( @{$emf->{'items'}}) {
1300
                    if (defined($item->{'file_name'})) {
1301
                        PackageManifestFile ( $name, $tier, $emf->{'file_base'} . '/' . $item->{'file_name'} );
6364 dpurdie 1302
                    }
1303
                }
6981 dpurdie 1304
                print_mf('#');
1129 dpurdie 1305
            }
1119 dpurdie 1306
        }
6981 dpurdie 1307
    }
1119 dpurdie 1308
 
6981 dpurdie 1309
    #
1310
    #   Expand out the entire MUG directory
1311
    #   All .mug files in the MUG directory will be added to the manifest
1312
    #   The assumption is that the MUG directory has been created by
1313
    #   something that knows what its doing
1314
    #
1315
    if ( my $mugdir = $entry->{mugdir} )
1316
    {
1317
        foreach my $file ( glob ($mugdir . '/*.mug' ) )
1119 dpurdie 1318
        {
6981 dpurdie 1319
            next unless ( -f $file );
1320
            my $base_file = StripDir($file);
6314 dpurdie 1321
 
6981 dpurdie 1322
            my @items = ($name, $tier, $base_file);
6314 dpurdie 1323
 
6981 dpurdie 1324
            if ($include_md5) {
1325
                my $md5 = digest_file_hex($file, 'MD5');
1326
                push @items, "MD5=$md5" ;
1119 dpurdie 1327
            }
6981 dpurdie 1328
            print_mf (join (',', @items));
1329
            PackageManifestFile ($name, $tier, $file );
1119 dpurdie 1330
        }
1331
    }
6981 dpurdie 1332
}
1119 dpurdie 1333
 
6981 dpurdie 1334
 
1335
#-------------------------------------------------------------------------------
1336
# Function        : templateProcessing 
1337
#
1338
# Description     : The manifest is created from a povided manifest with MUST
1339
#                   have one or more insertion points
1340
#                   
1341
#                   Purpose: Pulse can provide a template and SI teams can
1342
#                            insert there own packages 
1343
#
1344
# Inputs          : Globals
1345
#
1346
# Returns         : 
1347
#
1348
sub templateProcessing
1349
{
1350
    my $insertFound;
1351
    my $last_was_comment;
1352
 
1119 dpurdie 1353
    #
6981 dpurdie 1354
    #   Open the template manifest and process each line
1119 dpurdie 1355
    #
7005 dpurdie 1356
    print_mf( '# Start of Template from: ' . $templateMode->{'package'} );
6981 dpurdie 1357
    my $tfile;
1358
    my $line;
1359
    open( $tfile, '<', $templateMode->{'manifest'} ) || Error ("Cound not open template manifest: $?", "File: $templateMode->{'manifest'}");
1360
    while ( <$tfile> ) {
1361
        $line = $_;
1362
        $line =~ s~\s+$~~;
1363
        next unless ($line);
1121 dpurdie 1364
 
6981 dpurdie 1365
        #
1366
        #   Detect insertion point
1367
        #
1368
        if ($line =~ m~^##INSERT POINT~) {
1369
            $line =~ m~\[Name:(.+)\].*\[Tier:(.+)\]~i;
1370
            my $iname = $1;
1371
            my $itier = $2;
1372
            print_mf ("# Start of Template Insert: $iname, $itier");
1373
            templateInsert($iname,$itier);
1374
            print_mf ("# End of Template Insert: $iname, $itier");
1375
            $insertFound = 1;
1376
            next;
1377
 
1378
        } elsif( $line =~ m~^#$~) {
1379
            # Ignore 'empty' comment lines
1380
            # They will be regenerated
1381
            next;
6932 dpurdie 1382
 
6981 dpurdie 1383
        } elsif( $line =~ m~^#~) {
1384
            # Non empty comments are transferred
7004 dpurdie 1385
            #   Prepend another '#' marker as some moron decided that they could parse comments for data
1386
            #   A double # should defeat that
1387
            #   
6981 dpurdie 1388
            print_mf ('') unless ( $last_was_comment ) ;
7004 dpurdie 1389
            print_mf( '#' . $line);
6981 dpurdie 1390
            $last_was_comment = 1;
1391
            next;
1392
 
1393
        } elsif ($line =~ m~^\[~ ) {
1394
            # Metadata from the template
1395
            # Insert it as a comment
1396
            print_mf( '#' . $line);
1397
            next;
1398
        }
1399
        print_mf ('#') if ( $last_was_comment);
1400
        $last_was_comment = 0;
1401
 
1402
        my( $aname, $atier, $afile, @additionnal_info) = split(/\s*\,\s*/, $line);
1403
        my $test = CatPaths($templateMode->{manifest_dir}, $afile);
1404
        ReportError("Template processing: File not found with template: $afile", $test) unless -f $test;
1405
 
1406
        print_mf( $line);
1407
        PackageManifestFile ( $aname, $atier, $test );
1408
 
1409
    }
1410
    close $tfile;
7005 dpurdie 1411
    print_mf( '# End of Template from: ' . $templateMode->{'package'} );
6981 dpurdie 1412
 
6932 dpurdie 1413
    #
6981 dpurdie 1414
    #   Sanity Checks
1415
    #       Was an insertion point found
1416
    #       Were all manifest bits used
1121 dpurdie 1417
    #
6981 dpurdie 1418
    ReportError ("No insertion points in template") unless $insertFound;
1419
 
1420
    my @notUsed;
1421
    my @overUsed;
1422
 
1423
    foreach my $entry ( @Manifests ) {
1424
        if ( !exists $entry->{wasProcessed}) {
1425
            push @notUsed, "Name: $entry->{name}, Tier: $entry->{tier}";
1426
        } elsif ($entry->{wasProcessed} > 1) {
1427
            push @overUsed, "Name: $entry->{name}, Tier: $entry->{tier}";
1121 dpurdie 1428
        }
1429
    }
6981 dpurdie 1430
    Warning ("Template did not used data from: ", @notUsed)  if @notUsed;
1431
    Warning ("Template used data multiple times from: ", @overUsed)  if @overUsed;
1432
    ErrorDoExit();
6932 dpurdie 1433
}
1434
 
1435
#-------------------------------------------------------------------------------
6981 dpurdie 1436
# Function        : templateInsert 
1437
#
1438
# Description     : Helper routine to insert required bits into the template
1439
#                   Need to scan the manifest entries and determine which need
1440
#                   to be inserted at this point in the template.
1441
#
1442
# Inputs          : $iname  - Insert name
1443
#                   $itier  - Insert Tier
1444
#
1445
# Returns         : Nothing
1446
#
1447
sub templateInsert
1448
{
1449
    my ($iname, $itier) = @_;
1450
    foreach my $entry ( @Manifests ) {
1451
        next unless ((($iname eq '*') || ($iname eq $entry->{name}) ) && (($itier eq '*') || ($itier eq $entry->{tier})) );
1452
        processManifestEntry($entry);
1453
    }
1454
}
1455
 
1456
#-------------------------------------------------------------------------------
6932 dpurdie 1457
# Function        : print_mf
1458
#
1459
# Description     : Internal Function
1460
#                   Print one line to the Manifest File
1461
#                   Checks the length of the line being created
1462
#
1463
# Inputs          : $line
1464
#
1465
# Returns         :
1466
#
1467
 
1468
sub print_mf
1469
{
1470
    foreach  ( @_ )
1121 dpurdie 1471
    {
6932 dpurdie 1472
        my $ll = length ($_);
1473
        ReportError ( "Manifest line too long: $ll. Max is $ManifestLineWidth.",
1474
                "Line: $_" ) if ( $ManifestLineWidth && $ll > $ManifestLineWidth);
1475
        print MF $_ . "\n";
1121 dpurdie 1476
    }
6932 dpurdie 1477
}
1121 dpurdie 1478
 
6932 dpurdie 1479
#-------------------------------------------------------------------------------
1480
# Function        : PackageManifestFile  
1481
#
1482
# Description     : Process and package a manifest file
6978 dpurdie 1483
#                       Retain a list of files in the manifest to allow postprocessing
6932 dpurdie 1484
#                       such as signature generation
1485
#                   
1486
#
6962 dpurdie 1487
# Inputs          : $name           - Target platform name
1488
#                   $tier           - Target tier
1489
#                   $srcFile        - Full path to the source file
6932 dpurdie 1490
#
1491
# Returns         : Nothing
1492
#
1493
sub PackageManifestFile {
6962 dpurdie 1494
    my ($name, $tier, $srcFile ) = @_;
1495
    push @{$ManifestFiles}, ({srcFile => $srcFile, name =>$name, tier => $tier});
1119 dpurdie 1496
 
6981 dpurdie 1497
    PackageFile ('*', $srcFile, '--Subdir=' . $pkg_subdir, '--Strip' );
6932 dpurdie 1498
}
1499
 
1500
#-------------------------------------------------------------------------------
1501
# Function        : GenSigInit 
1502
#
1503
# Description     : Initialise the Siganture Generation process
1504
#                   Populate some globals for use in creating the manifest
1505
#                   Bail if there are errors
1506
#
1507
# Inputs          : 
1508
#
1509
# Returns         : 
1510
#
1511
sub GenSigInit
1512
{
6933 dpurdie 1513
    Debug("GenSigInit:", $noSigs);
6932 dpurdie 1514
    return if $noSigs;
1515
 
1516
    my @warnings;
1517
 
1119 dpurdie 1518
    #
6933 dpurdie 1519
    #   Locate and setup openssl
1520
    #   Should be provided by a package
1521
    #   set OPENSSL_CONF=...../openssl.cfg 
1522
    #   
1523
    $opensslProg = ::ToolExtensionProgram( 'openssl', '', '.exe');
1524
 
1525
    #   Generate  a dummy openssl.cnf - to keep the uitility happy (quiet)
1526
    $opensslConf = FullPath(CatPaths( $::ScmRoot, $::ScmInterface, 'openssl.cfg'));
1527
    TouchFile($opensslConf);
1528
    ::ToolsetGenerate($opensslConf);
1529
    $ENV{OPENSSL_CONF}= $opensslConf;
1530
 
1531
    #
1532
    #   Figure out default operation if openssl cannot be found
1533
    #       If --signature - then report error
1534
    #       If not specified, then default is -NoSig
1535
    #
1536
    unless ($opensslProg) {
1537
        if (defined $noSigs) {
1538
            ReportError ("The openssl utility is not available. Must be provided by a package") unless $opensslProg;  
1539
        } else {
1540
            Verbose("openssl not found in a package. Default to no signature");
1541
            $noSigs = 1;
1542
            return;
1543
        }
1544
    }
1545
 
1546
    #
6932 dpurdie 1547
    #   Signatures 'should' be generated for a target paltform of 'MANSIG'
1548
    #       In the automated build system this will be a controlled machine
1549
    #   Warn if attemting to create signatures for a different target    
1119 dpurdie 1550
    #
6932 dpurdie 1551
    push @warnings, "# Package build for platform other than MANSIG - will generate test signatures" if ($::ScmPlatform ne 'MANSIG');
1552
 
1553
 
1119 dpurdie 1554
    #
6932 dpurdie 1555
    #   Locate the signature file
1556
    #   Use an internal key that unless being run on a controlled build machine
1557
    #   The controlled build machine will have
1558
    #       GBE_MANIFEST_KEY set to a path that contains the keyfile
1559
    #           Yes, a user can fudge this, but not with the real file
1560
    #          
1561
    #  Internal cert created with:
1562
    #  openssl req -nodes -x509 -sha256 -newkey rsa:4096 -keyout VixPulseManifestTest.key -out VixPulseManifestTest.crt -days 10000 -subj "/C=AU/CN=Vix.Pulse.Manifest.Test"
1119 dpurdie 1563
    #
6932 dpurdie 1564
    $keyFile = CatPaths( $pkgBase, 'VixPulseManifestTest.key');
1565
    my $localKey = 1;
1566
    if (exists $ENV{GBE_MANIFEST_KEY} ) {
1567
        $keyFile = $ENV{GBE_MANIFEST_KEY};
1568
        $localKey = 0;
1569
    }
1570
    $certFile = $keyFile;
1571
    $certFile =~ s~\.key$~.crt~;
1572
    $certName = $certFile;
1573
    $certName =~ s~.*[\\/]~~;
1119 dpurdie 1574
 
6932 dpurdie 1575
    ReportError ("Manifest signing key not found", $keyFile) unless -f $keyFile;
1576
    ReportError ("Manifest signing key not found", $certFile) unless -f $certFile;
1577
 
1578
    push @warnings, "#  Using uncontrolled test key to sign the manifest" if ($localKey);
1579
    Warning("#############################################################", "#",
1580
             @warnings,
1581
            "#", "#############################################################") if (@warnings);
1582
 
1583
    ErrorDoExit();
1584
    Message("OpenSsl Prog: $opensslProg");
1585
    Message("OpenSsl Conf: $opensslConf");
1586
    Message("Signing with: $keyFile");
1587
 
1119 dpurdie 1588
}
1589
 
6932 dpurdie 1590
#-------------------------------------------------------------------------------
1591
# Function        : GenSignatures 
1592
#
1593
# Description     : Generate signatures on all packages
1594
#
1595
# Inputs          : Used the array of files in $ManifestFiles 
1596
#
1597
# Returns         : Nothing 
1598
#
1599
sub GenSignatures
1600
{
6933 dpurdie 1601
    Debug("GenSignatures:", $noSigs);
6932 dpurdie 1602
    return if $noSigs;
5767 alewis 1603
 
6962 dpurdie 1604
    my %sigManifest;
1605
 
6932 dpurdie 1606
    foreach my $entry ( @{$ManifestFiles}) {
6962 dpurdie 1607
        Verbose("PostProcess: $entry->{srcFile}");
6932 dpurdie 1608
 
1609
        #
1610
        #   Generate the name of the signature file
1611
        #   Generate Packaging directives for the signature
1612
        #   
1613
        my $sigFileName = CatPaths( "$::ScmPlatform.LIB", StripDir($entry->{srcFile}) . '.sig' );
6981 dpurdie 1614
        PackageFile ('*', $sigFileName, '--Subdir=' . $pkg_subdir, '--Strip' );
6932 dpurdie 1615
        ::ToolsetGenerate($sigFileName);
1616
 
1617
        #
6962 dpurdie 1618
        #   Generate the name/tier for the manifest signature
1619
        #       ie: Manifest_<name>_<tier>.sig
1620
        #   Generate the name for the manifest signature
1621
        #       ie: Manifest_<name>.sig
1622
        #   Will generate signature of signatures
6932 dpurdie 1623
        #
6962 dpurdie 1624
        my $sigManifest =  join('_', $entry->{name}, $entry->{tier});
1625
        push @{$sigManifest{$sigManifest}}, $sigFileName;
1626
        push @{$sigManifest{$entry->{name}}}, $sigFileName;
6932 dpurdie 1627
 
1628
 
6962 dpurdie 1629
        # Generate the signature over the file
1630
        genSigForFile($entry->{srcFile}, $sigFileName);
1631
    }
1632
 
1633
    #
1634
    #   Create a file of signatures
1635
    #   Create one for each platform/tier
1636
    #
1637
    foreach my $nameTier ( keys %sigManifest)
1638
    {
1639
        Verbose("PostProcessSig: $nameTier");
1640
        my $sigSigTemp = $manifestName . '_' . $nameTier . '.sig';
1641
        my $sigSigTempCat = $sigSigTemp . '.content';
1642
        ::ToolsetGenerate($sigSigTemp, $sigSigTempCat);
6981 dpurdie 1643
        PackageFile ('*', $sigSigTemp, '--Subdir=' . $pkg_subdir, '--Strip' );
6962 dpurdie 1644
 
6932 dpurdie 1645
        #
6962 dpurdie 1646
        #   Concatenate the contents of the required .sig files
1647
        #   Treat them as binary files. 
1648
        #
1649
        open  (my $ofh, '>', $sigSigTempCat ) || Error( "Cannot create file: $sigSigTempCat", "Reason: $!" );
1650
        binmode ($ofh);
1651
        foreach my $entry (@{$sigManifest{$nameTier}}) {
1652
            Verbose("PostProcessSig: $entry");
1653
            open( my $file, '<', $entry ) || Error("Cannot open '$entry'. $!");
1654
            binmode ($file);
1655
            my @lines = <$file>;
1656
            close $file;
6932 dpurdie 1657
 
6962 dpurdie 1658
            foreach my $entry ( @lines ) {
1659
                print $ofh $entry;
1660
            }
6932 dpurdie 1661
        }
6962 dpurdie 1662
        close $ofh;
6932 dpurdie 1663
 
6962 dpurdie 1664
        #
1665
        #   Generate a signature over the file
1666
        #
1667
        genSigForFile($sigSigTempCat, $sigSigTemp);
1668
        #unlink $sigSigTempCat;
6932 dpurdie 1669
    }
6962 dpurdie 1670
 
6932 dpurdie 1671
    unlink $opensslConf;
5767 alewis 1672
}
1673
 
6962 dpurdie 1674
#-------------------------------------------------------------------------------
1675
# Function        : genSigForFile 
1676
#
1677
# Description     : Generate a .sig file for a named file (internal)
1678
#                   Will be smart and only 'touch' the output file if the input has chnaged
1679
#                       It will maintain a fingerprint file to do this.
1680
#                   
1681
#                   Generate package signature
1682
#                   The required custom(vix) 'sig' file has the format:
1683
#                       line-1 : name of the certificate to decode
1684
#                                Assume its the keyname with .key -> .crt - with no path elements
1685
#                       line-2 : Text representation of the signature (base64)
1686
#                                The openssl dgst command generates a binary output by default
1687
#                                This is then converted into base64 with -A option
1688
#                   
1689
# Inputs          : $srcFile        - Source file to process
1690
#                   $tgtFile        - Output file name
1691
#
1692
# Returns         : 
1693
#
1694
sub genSigForFile
1695
{
1696
    my ($srcFile, $tgtFile) = @_;
5767 alewis 1697
 
6962 dpurdie 1698
    my $tmp1 = CatPaths( "$::ScmPlatform.LIB", 'temp1');
1699
    my $tmp2 = CatPaths( "$::ScmPlatform.LIB", 'temp2');
1700
    ::ToolsetGenerate($tmp1, $tmp2);
1701
 
1702
    Verbose("Signing: " . StripDir($srcFile));
1703
    System( '--Exit', '--NoShell', $opensslProg, 'dgst', '-sha256', '-sign', $keyFile, '-out', $tmp1, $srcFile );
1704
    System( '--Exit', '--NoShell', $opensslProg, 'base64', '-A', '-in', $tmp1, '-out', $tmp2 );
1705
    my $base64 = TagFileRead($tmp2);
1706
 
1707
    #
1708
    #   In a development environment we don't want to create the signature file every time we run. Its noisy. 
1709
    #   Solution: Only generate a signature file if:
1710
    #               It doesn't exist
1711
    #               A copy of the signed digest doesn't exist (.fpp)
1712
    #               The signed digest has changed
1713
    #   
1714
    my $fppFileName = CatPaths( "$::ScmPlatform.LIB", StripDir($srcFile) . '.fpp' );
1715
    ::ToolsetGenerate($fppFileName);
1716
    my $genSig = 0;
1717
    $genSig = 1 unless ( -e $tgtFile &&  -e $fppFileName);
1718
    unless ($genSig) {
1719
        my $ffp = TagFileRead($fppFileName);
1720
        $genSig = ($ffp ne $base64);
1721
    }
1722
 
1723
    if ($genSig) {
1724
        FileCreate($tgtFile, $certName, $base64);
1725
        rename $tmp2, $fppFileName ;
1726
    }
1727
 
1728
    unlink $tmp1;
1729
    unlink $tmp2;
1730
}
1731
 
5767 alewis 1732
#-------------------------------------------------------------------------------
1733
# Function        : DmfGenerate
1734
#
1735
# Description     : Import an existing manifest
1736
#
1737
# Inputs          : entry   - The manifest that is being processed.
1738
#
1739
# Returns         : Nothing
1740
#
1741
sub DmfGenerate
1742
{
1743
    my ($entry) = @_;
1744
 
1745
    # Get the generation time.
1746
    my $gen_time = time();
1747
 
1748
    my $work_dir = "$::ScmPlatform.BIN/";
1749
    System( "$::GBE_BIN/mkdir -p $work_dir" );
1750
 
1751
    my $name = $entry->{name};
1752
    my $version = $entry->{dmf_version};
1753
 
1754
    # Configure base manifest information.
1755
    my %manifest;
5771 alewis 1756
    $manifest{'mugsetId'} = $name . '_' . $version;
5767 alewis 1757
    $manifest{'name'} = $name;
1758
    $manifest{'version'} = $version;
5771 alewis 1759
    $manifest{'packageName'} = $::ScmBuildPackage;
1760
    $manifest{'packageVersion'} = $::ScmBuildVersionFull;
5767 alewis 1761
    $manifest{'datetime'} = localtime($gen_time);
1762
    $gen_time *= 1000;  # Make to milliseconds
1763
    $manifest{'timestamp'} = $gen_time;
1764
    $manifest{'tier'} = $entry->{tier};
1765
 
1766
    # Process each file.
1767
    my @files = @{ $entry->{files} };
1768
    my $zip = Archive::Zip->new();
1769
    my $i = 0;
1770
    foreach my $fentry ( @files )
1771
    {
1772
        if ( my $file = $fentry->{'file'} )
1773
        {
6302 dpurdie 1774
            my $order = $i + 1;
5767 alewis 1775
            my $base_file = StripDir( $file );
1776
            my $publish_file = $name . '_' . $version . '_' . $order . '.aup';
1777
            my $aup_file = $work_dir . $publish_file;
1778
 
1779
            GenerateCesFile($file, $aup_file, 0x3, $gen_time, $publish_file);
1780
 
1781
            my $file_member = $zip->addFile( $aup_file, $publish_file );
1782
 
1783
            $manifest{'tasks'}[$i]{'order'} = 1 * $order;
1784
            $manifest{'tasks'}[$i]{'filename'} = $base_file;
1785
            $manifest{'tasks'}[$i]{'download'} = $publish_file;
5771 alewis 1786
            $manifest{'tasks'}[$i]{'sha256'} = digest_file_base64($file, 'SHA-256');
1787
            $manifest{'tasks'}[$i]{'size'} = -s $file;
1788
 
5767 alewis 1789
            if ($base_file =~ /\.sh$/)
1790
            {
1791
                $manifest{'tasks'}[$i]{'action'} = 'exec-shell';
1792
            }
1793
            elsif ($base_file =~ /\.deb$/)
1794
            {
1795
                $manifest{'tasks'}[$i]{'action'} = 'dpkg-install';
5771 alewis 1796
 
1797
                my ($pkg_name, $pkg_version, $pkg_arch) = ($base_file =~ /([^_]*)_([^_]*)_(.*)/);
1798
                $manifest{'tasks'}[$i]{'arch'} = $pkg_arch;
1799
                $manifest{'tasks'}[$i]{'name'} = $pkg_name;
1800
                $manifest{'tasks'}[$i]{'version'} = $pkg_version;
5767 alewis 1801
            }
1802
            else
1803
            {
1804
                ReportError ("Manifest entry $base_file does not have a supported DMF install action");
1805
            }
1806
 
1807
            $i = $i + 1;
1808
        }
1809
    }
1810
 
1811
    # Encode and commit the JSON.
1812
    my $json_encoder = JSON->new->allow_nonref;
1813
    my $json = $json_encoder->pretty->encode( \%manifest );
1814
 
1815
    my $manifest_filename = $name . '_' . $version;
1816
    my $aum_filename = $manifest_filename . '_0.aum';
1817
    my $manifest_file = $work_dir . $manifest_filename . '.json';
1818
    my $aum_file = $work_dir . $aum_filename;
1819
 
1820
    # Save our manifest.
1821
    open (J, '>', $manifest_file ) || Error ("Cannot create the DMF Manifest file");
1822
    binmode (J);
1823
    print J $json;
1824
    close J;
1825
 
1826
    GenerateCesFile($manifest_file, $aum_file, 0x2, $gen_time, $aum_filename);
1827
 
1828
    $zip->addFile($aum_file, $aum_filename);
1829
 
1830
    my $zip_filename = $work_dir . $name . '_' . $version . '.zip';
1831
    if ( $zip->writeToFileNamed($zip_filename) != AZ_OK )
1832
    {
1833
        ReportError("DMF ZIP file creation failed");
1834
    }
6981 dpurdie 1835
    PackageFile('*', $zip_filename, '--Strip');
1836
    PackageFile('*', $manifest_file, '--Strip');
5767 alewis 1837
 
1838
}
1839
 
1840
#-------------------------------------------------------------------------------
6981 dpurdie 1841
# Function        : PackageFile  
1842
#
1843
# Description     : Package or Install a manifest file
1844
#
1845
# Inputs          : Same as PackageFile
1846
#
1847
# Returns         : 
1848
#
1849
sub PackageFile
1850
{
1851
    if ($localInstall) {
1852
        ::InstallHdr(@_);
1853
    } else {
1854
        ::PackageFile(@_);
1855
    }
1856
}
1857
 
1858
#-------------------------------------------------------------------------------
6932 dpurdie 1859
# Function        : GenerateCesFile
5767 alewis 1860
#
1861
# Description     : Import an existing manifest
1862
#
1863
# Inputs          : src_file     - The input file.
1864
#                   dst_file     - The output CES file.
1865
#                   content_type - The content type to report.
1866
#                   gen_time     - The generation time for the file.
1867
#                   filename     - The filename to embed in the CES file.
1868
#
1869
#
1870
# Returns         : Nothing
1871
#
1872
sub GenerateCesFile
1873
{
1874
    my ($src_file, $dst_file, $content_type, $gen_time, $filename) = @_;
1875
 
1876
    open (INF, '<', $src_file ) || Error ("Cannot open file $src_file for reading");
1877
    binmode (INF);
1878
 
1879
    open (OUTF, '>', $dst_file ) || Error ("Cannot open file $dst_file for writing");
1880
    binmode (OUTF);
1881
 
1882
    my $signing_key_name = "";
1883
    my $signature_size = 0;
1884
    my $format_version = 0xCE500000;
1885
    my $compression_method = 0;
1886
    my $encryption_method = 0;
1887
    my $kek_name = "";
1888
    my $encryption_key_size = 0;
1889
    my $filename_size = length($filename);
1890
 
1891
    print OUTF pack("Z32", $signing_key_name);
1892
    print OUTF pack("n", $signature_size);
1893
    print OUTF pack("N", $format_version);
1894
    print OUTF pack("N", $content_type);
1895
    print OUTF pack("Q>", $gen_time);
1896
    print OUTF pack("N", $compression_method);
1897
    print OUTF pack("N", $encryption_method);
1898
    print OUTF pack("Z32", $kek_name);
1899
    print OUTF pack("n", $encryption_key_size);
1900
    print OUTF pack("n", $filename_size);
1901
    # Encryption key HERE
1902
    print OUTF pack("A$filename_size", $filename);
1903
 
1904
    my $buf;
1905
    while (read(INF,$buf,65536))
1906
    {
1907
        print OUTF $buf;
1908
    }
1909
    print OUTF $buf;
1910
    close INF;
1911
 
1912
    # Signature HERE
1913
 
1914
    # Finish with file.
1915
    close OUTF;
1916
}
1917
 
1119 dpurdie 1918
1;