Subversion Repositories DevTools

Rev

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