Subversion Repositories DevTools

Rev

Rev 6981 | Rev 6990 | 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 );
769
            Warning ("Multiple Manifest Files find. Only the first will be used",
770
                     "Using: $manifest",
771
                     "Ignoring: $file" ) if ( $manifest );
772
            $manifest = $file;
773
    }
774
 
775
    unless ($manifest)
776
    {
777
        ReportError ("ImportManifest. No Manifest found: $package_name");
778
        return undef;
779
    }
780
 
781
 
782
    #
783
    #
784
    #
785
    open (MF, '<', $manifest ) || Error ("Cannot open the Manifest file: $manifest", $!);
786
    while ( <MF> )
787
    {
1129 dpurdie 788
        #
6302 dpurdie 789
        #   Clean trailing whitespace ( line-feed and new lines )
790
        #   Comment out [Version] data
1129 dpurdie 791
        #
6302 dpurdie 792
        s~\s+$~~;
793
        s~(\s*\[Version])~#$1~;
794
 
5649 dpurdie 795
        #
6981 dpurdie 796
        #   Parse lines and determine files
6302 dpurdie 797
        #
798
        next unless ( $_ );
6364 dpurdie 799
        if (( m~\s*#~ ) || ( m~\s*\[~ )) {
800
            push @item_list, { 'comment' => $_ };
801
            next;
802
        }
803
        my( $aname, $atier, $afile, @additionnal_info) = split(/\s*\,\s*/, $_);
1129 dpurdie 804
#            print "---------- $_\n";
805
#            print "T: $atier, N:$aname, F:$afile\n";
6364 dpurdie 806
        my $file =  { 'file_name' => $afile
807
                    , 'file_info' => \@additionnal_info
808
                    };
809
        push @item_list, $file;
1129 dpurdie 810
 
6302 dpurdie 811
        #
812
        #   Rewrite the name and tier
813
        #
814
        if ($rewrite)
815
        {
816
            $_ = join(',', $name, $tier, $afile);
817
            $first_tier = $tier;
818
            $first_name = $name;
819
        }
820
        else
821
        {
1129 dpurdie 822
            #
6302 dpurdie 823
            #   Capture first tier and name
1129 dpurdie 824
            #
6302 dpurdie 825
            $first_tier = $atier unless ( defined $first_tier );
826
            $first_name = $aname unless ( defined $first_name );
1129 dpurdie 827
        }
6302 dpurdie 828
    }
829
    continue
830
    {
831
        push @file_contents, $_;
832
    }
833
    close MF;
1129 dpurdie 834
 
6302 dpurdie 835
    #
836
    #   Create a hash of data that describes the manifest that has
837
    #   just been read in.
838
    #
839
    $package_dirs{$pkg_root}{used} = 1;
840
    $manifest =~ s~.*/~~;
841
    return { 'contents' => \@file_contents,
6364 dpurdie 842
              'items' => \@item_list,
6302 dpurdie 843
              'file_base' => $pkg_dir,
844
              'manifest' => $manifest,
845
              'pkg_dir' => $pkg_root,
846
              'tier' => $first_tier,
847
              'name' => $first_name,
848
              'rewrite' => $rewrite,
849
            };
1119 dpurdie 850
}
851
 
852
#-------------------------------------------------------------------------------
6978 dpurdie 853
# Function        : _InsertPoint
854
#
855
# Description     : Create a Manifest Insertion Point
856
#
857
# Inputs          : Args    - [,--All,--Name,--Name=xxxx,--Tier,--Tier=Name, --Current]
858
#                   tier    - May be null
859
#                   name    - May be null
860
#
861
# Returns         : A hash of data to be used later
862
#
863
sub _InsertPoint
864
{
865
    my ($args, $tier, $name) = @_;
866
    my @item_list;
867
 
868
    ReportError("ManifestFiles: ManifestInsertionPoint. Name not yet specified") unless defined $name;
869
    ReportError("ManifestFiles: ManifestInsertionPoint. Tier not yet specified") unless defined $tier;
870
 
871
    my $argName = $name;
872
    my $argTier = $tier;
873
 
874
    #
875
    #   Extract sub options
876
    #
877
    my @subargs = split(',--', $args);
878
    foreach ( @subargs)
879
    {
880
        next unless (length($_) > 0);
881
        if (m~^All$~i){
882
            $argName = '*';
883
            $argTier = '*';
884
 
885
        } elsif (m~^Name(=(.*))?~i){
886
            if ( $1 ){
887
                $argName = $2;
888
            } else {
889
                $argName = $name;
890
            }
891
 
892
        } elsif (m~^Tier(=(.*))?~i){
893
            if ( $1 ){
894
                $argTier = $2;
895
            } else {
896
                $argTier = $tier;
897
            }
898
 
899
        } elsif (m~^Current$~i){
900
            $argName = $name;
901
            $argTier = $tier;
902
 
903
        } else {
904
            ReportError("ManifestFiles: Unknown suboption to ManifestInsertionPoint:" . $_);
905
        }
906
    }
907
 
908
    return { 'tier' => $argTier,
909
             'name' => $argName,
910
           };
911
}
912
 
913
#-------------------------------------------------------------------------------
914
# Function        : _Template
915
#
916
# Description     : Capture templating information
917
#
918
# Inputs          : --Template=Package[,--Subdir=subdir,File=name] 
919
#                   tier    - May be null
920
#                   name    - May be null
921
#
922
# Returns         : A hash of data to be used later
923
#
924
sub _Template
925
{
926
    my ($args, $tier, $name) = @_;
927
    my $subdir = 'mug';
928
    my $manifest;
929
 
930
    #
931
    #   Can only use the Template directive once
932
    #   
933
    if ($templateMode) {
934
        ReportError ("ManifestFiles:--Template option is only allowed once");
935
        return undef;
936
    }
937
    $templateMode = 1;
938
 
939
 
940
    #
941
    #   Locate the mugfile subdir
942
    #
943
    my $package_name = $args;
944
 
945
    #
946
    #   Extract sub options
947
    #       --Subdir=xxxx
948
    #       --File=name
949
    #       
950
    if ( $package_name =~ m/(.*?)(,.*)/ )
951
    {
952
        $package_name = $1;
953
        my @subargs = split(',--', $2);
954
        foreach ( @subargs)
955
        {
956
            next unless (length($_) > 0);
957
            if (m~^Subdir=(.*)~i){
958
                $subdir = $1;
959
 
960
            } elsif (m~^File=(.*)~i) {
961
                $manifest = $1;
962
 
963
            } else {
964
                ReportError("ManifestFiles: Unknown suboption to Template:" . $_);
965
            }
966
        }
967
    }
968
 
969
    my $package = ::GetPackageEntry( $package_name );
970
    unless ( $package )
971
    {
972
        ReportError ("ManifestFiles: Package not known to build: $package_name");
973
        return undef;
974
    }
975
 
976
    my $pkg_root = $package->{'ROOT'};
977
    my $pkgDir = CatPaths( $pkg_root, $subdir);
978
    unless (-d $pkgDir) {
979
        ReportError ("ManifestFiles: Template subdir not found in $package_name: $subdir");
980
        return undef;
981
    }
982
 
983
    #
984
    #   Determine Manifest File name, unless specified by user
985
    #
986
    unless ($manifest) {
987
        foreach my $file ( glob ($pkgDir . '/Manifest*' ) )
988
        {
989
                next unless ( -f $file );
990
                if ( $manifest ) {
991
                    Warning ("Multiple Manifest Files find. Only the first will be used",
992
                             "Using: $manifest",
993
                             "Ignoring: $file" ) ;
994
                    next;
995
                }
996
                $manifest = $file;
997
        }
998
        unless ($manifest)
999
        {
1000
            ReportError ("ImportManifest. No Manifest template found: $package_name");
1001
            return undef;
1002
        }
1003
    } else { 
1004
        $manifest = CatPaths($pkgDir, $manifest);
1005
    }
1006
 
1007
    unless (-f $manifest) {
1008
        ReportError ("ImportManifest. No Manifest template found: $package_name, $subdir, $manifest");
1009
        return undef;
1010
    }
1011
 
1012
    #
1013
    #   Return paramters for later processing
1014
    #
1015
 
1016
    $package_dirs{$pkg_root}{used} = 1;
6981 dpurdie 1017
    $templateMode = { 'manifest' => $manifest,
6978 dpurdie 1018
             'pkg_dir' => $pkg_root,
1019
             'subdir' => $subdir,
1020
             'manifest_dir' => $pkgDir,
1021
             'package' => $package_name,
6981 dpurdie 1022
    };
1023
    return $templateMode; 
6978 dpurdie 1024
}
1025
 
1026
#-------------------------------------------------------------------------------
6932 dpurdie 1027
# Function        : Generate
1119 dpurdie 1028
#
1029
# Description     : Internal Function
1030
#                   Process all the collected data and create directives
1031
#                   for the creation of the manifest
1032
#
1033
#                   This function will be called, just before the Makefile
1034
#                   is created. The function will:
1035
#                       1) Create the Manifest File
1036
#                       2) Package the Manifest File
1037
#                       3) Package the manifest file contents
1038
#
1039
#                   using (mostly) normal makefile.pl directives.
1040
#
1041
# Inputs          : None
1042
#
1043
# Returns         : Nothing
1044
#
6932 dpurdie 1045
sub Generate
1119 dpurdie 1046
{
6932 dpurdie 1047
    Debug ("Generate");
1119 dpurdie 1048
    Message ("Generating Manifest File");
1123 dpurdie 1049
 
1050
    #
1051
    #   Need at least one Manifest Entry
1052
    #
6932 dpurdie 1053
#DebugDumpData ( "Manifests", \@Manifests );
1123 dpurdie 1054
    return unless ( @Manifests );
1119 dpurdie 1055
 
1056
    #
6932 dpurdie 1057
    #   Init the signing subsystem
1058
    # 
1059
    GenSigInit();
1060
 
1061
    #
1125 alewis 1062
    #   Determine the target packaging directory
1063
    #   Default is .../mug
1064
    #
6962 dpurdie 1065
    $pkg_subdir = 'mug';
1129 dpurdie 1066
    if ( exists $Manifests[0]->{pkgsubdir} && defined $Manifests[0]->{pkgsubdir} )
1125 alewis 1067
    {
1068
        my $subdir = $Manifests[0]->{pkgsubdir};
6962 dpurdie 1069
        $pkg_subdir .= '/' . $subdir;
1070
        $pkg_subdir =~ s~^mug/mug~mug~;
1125 alewis 1071
    }
1072
 
1073
    #
1119 dpurdie 1074
    #   Create the Manifest File as we process the lists
1125 alewis 1075
    #   Place this in the 'lib' directory:
1119 dpurdie 1076
    #       - So that it will be deleted on clobber
1123 dpurdie 1077
    #       - So that it can be placed in a target-specific subdir
1125 alewis 1078
    #       - So that we can have one per makefile.pl
1119 dpurdie 1079
    #
1080
    Error ("ManifestFiles: Needs local directory specified in build.pl") unless ( $::ScmLocal );
1081
 
1125 alewis 1082
    my $manifest_dir = "$::ScmPlatform.LIB";
1119 dpurdie 1083
    System( "$::GBE_BIN/mkdir -p $manifest_dir" );
1084
 
6962 dpurdie 1085
    $manifestName = $manifest_dir . '/Manifest';
1086
    $manifestName .= '_' . $::ScmBuildVersion if ( $Manifest_has_version );
6981 dpurdie 1087
    PackageFile ('*', $manifestName, '--Subdir=' . $pkg_subdir, '--Strip' );
6962 dpurdie 1088
    ::ToolsetGenerate( $manifestName );
5649 dpurdie 1089
 
6962 dpurdie 1090
    Verbose ("Generate: File: $manifestName");
1119 dpurdie 1091
 
6962 dpurdie 1092
    open (MF, '>', $manifestName ) || Error ("Cannot create the Manifest file: $manifestName");
5711 kspencer 1093
    binmode (MF);
5767 alewis 1094
 
6364 dpurdie 1095
    if ($Manifests[0]->{is_sub_manifest} == 1) {
1096
        print_mf ("# Package $::ScmBuildPackage $::ScmBuildVersion built: $::CurrentTime");
1097
    } else {
1098
        print_mf ("# PackageName: $::ScmBuildPackage");
1099
        print_mf ("# PackageVersion: $::ScmBuildVersion");
1100
        print_mf ("# BuildDate: $::CurrentTime");
1101
        print_mf ("#");
1102
        print_mf ("[Version],$::ScmBuildVersion");
1103
        print_mf ("#");
1104
    }
1119 dpurdie 1105
 
1106
    #
6932 dpurdie 1107
    #   Insert the certificate used to verify the files
1108
    #       Currently we only handle one certificate
1109
    #       Certificate name must end in .crt
1110
    #   In production the .crt file MUST be signed by the VixManifestRoot-CA
1111
    #   The assumtion is that the public key for VixManifestRoot-CA is on the device
1112
    #
1113
    unless (($Manifests[0]->{is_sub_manifest} == 1) || $noSigs) {
1114
        print_mf ("");
1115
        print_mf ("#");
1116
        print_mf ("# Signing Certificate");
1117
        print_mf ("[Certificate],$certName");
1118
 
6981 dpurdie 1119
        PackageFile ('*', $certFile, '--Subdir=' . $pkg_subdir, '--Strip' );
6932 dpurdie 1120
    }
6981 dpurdie 1121
 
6932 dpurdie 1122
    #
6981 dpurdie 1123
    #   If in templating mode, then process the base template
1119 dpurdie 1124
    #
6981 dpurdie 1125
    if ($templateMode) {
1126
        templateProcessing();
1119 dpurdie 1127
 
6981 dpurdie 1128
    } else {
1119 dpurdie 1129
 
1130
        #
6981 dpurdie 1131
        #   Process each tier in the order presented in the source file
1119 dpurdie 1132
        #
6981 dpurdie 1133
        foreach my $entry ( @Manifests )
1119 dpurdie 1134
        {
6981 dpurdie 1135
            DmfGenerate($entry) if ( $entry->{dmf} );
1136
            processManifestEntry($entry);
1137
        }
1138
    }
1123 dpurdie 1139
 
6981 dpurdie 1140
    #
1141
    #   Complete the creation of the Manifest File
1142
    #
1143
    print_mf ("# end of $::ScmBuildPackage");
1144
    close MF;
1145
    ErrorDoExit();
6978 dpurdie 1146
 
6981 dpurdie 1147
    #
1148
    #   Post process files from the manifest
1149
    #   May include signature generation
1150
    GenSignatures();
6978 dpurdie 1151
 
6981 dpurdie 1152
    #
1153
    #   Sanity test of packages that did not provide a debian file
1154
    #   Just a hint that something may have been missed
1155
    #
1156
    unless ($noWarn) {
1157
        my @not_used_packages;
1158
        foreach my $package_dir ( getPackagePaths ('--All') ) {
1159
            next if ( $package_dir =~ m~/manifest-tool/~ );
1160
            unless ( exists $package_dirs{$package_dir}{used} ) {
1161
                push @not_used_packages, $package_dir;
6978 dpurdie 1162
            }
6981 dpurdie 1163
        }
1164
        if ( @not_used_packages ) {
1165
            Warning ("Packages that did not contribute packages to the manifest:",
1166
                      @not_used_packages );
1167
        }
1168
    }
1169
}
6978 dpurdie 1170
 
6981 dpurdie 1171
#-------------------------------------------------------------------------------
1172
# Function        : processManifestEntry 
1173
#
1174
# Description     : Process a single Manifest entry 
1175
#
1176
# Inputs          : Globals
1177
#
1178
# Returns         : 
1179
#
1180
sub processManifestEntry
1181
{
1182
    my ($entry) = @_;
1183
#DebugDumpData ( "Manifest Entry", $entry );
1125 alewis 1184
 
6981 dpurdie 1185
    my $tier = $entry->{tier};
1186
    my $name = $entry->{name};
1187
    my $include_md5 = $entry->{md5};
1188
    my $last_was_comment = 0;
1189
    my $last_was_insert = 0;
1190
 
1191
    #
1192
    #   Flag that this entry has been processed
1193
    #
1194
    $entry->{wasProcessed}++;
1195
 
1196
    #
1197
    #   Insert all the files that have been specified
1198
    #   The user specified order is preserved
1199
    #
1200
    #   Entries may be either a file or a comment
1201
    #   Comments: Merge multiple comments and create blocks
1202
    #
1203
    #
1204
    my @files = @{ $entry->{files} };
1205
    foreach my $fentry ( @files ) {
1206
        if ( my $cmt = $fentry->{'cmt'} ) {
1207
            print_mf ('') unless ( $last_was_comment ) ;
1208
            print_mf ( map (('# ' . $_) , split ("\n", $cmt) ));
1209
            $last_was_comment = 1;
1210
            next;
1211
        }
1212
 
1213
        print_mf ('#') if ( $last_was_comment);
1214
        $last_was_comment = 0;
1215
 
1216
        if ( my $ip = $fentry->{'insertPoint'} ) {
1217
           #
1218
           #   Create an insertion point
1219
           #   Looks like a comment for the purposes of backward compatability
1220
           #
1221
 
1222
           print_mf ('') unless $last_was_insert;
1223
           print_mf ("##INSERT POINT [Name:$ip->{name}] [Tier:$ip->{tier}]");
1224
           $last_was_insert = 1;
1225
           next;
1226
        }
1227
        print_mf ('#') if ( $last_was_insert);
1228
        $last_was_insert = 0;
1229
 
1230
        if ( my $file = $fentry->{'file'} ) {
1231
            my $base_file = StripDir( $file );
1232
            my @items = ($name, $tier, $base_file);
1233
            if ($include_md5) {
1234
                my $md5 = digest_file_hex($file, 'MD5');
1235
                push @items, "MD5=$md5" ;
1125 alewis 1236
            }
6981 dpurdie 1237
            if (exists $entry->{fileVersions} && exists $entry->{fileVersions}{$file} ) {
1238
                push @items, "VERSION=" . $entry->{fileVersions}{$file};
1239
            }
1240
            print_mf (join (',', @items));
1241
            PackageManifestFile ($name, $tier, $file );
1242
        }
1129 dpurdie 1243
 
6981 dpurdie 1244
        if ( my $file = $fentry->{'filenocopy'} ) {
1245
            print_mf ("$name,$tier,$file");
1246
        }
1247
 
1248
        if ( my $emf = $fentry->{'manifest'} ) {
1249
            #
1250
            #   Insert the entire manifest
1251
            #   Items are:
1252
            #        contents
1253
            #        items:
1254
            #               file_name + arrays of file_info
1255
            #           or  comment line to copy
1256
            #        file_base
1257
            #        manifest
1258
            #
1129 dpurdie 1259
#DebugDumpData ( "Embedded Manifest Entry", $emf );
6981 dpurdie 1260
            if ($emf->{'rewrite'}) {
1261
                foreach my $item ( @{$emf->{'items'}}) {
1262
                    if (defined($item->{'file_name'}))
1263
                    {
1264
                        my @items = ($name, $tier, $item->{'file_name'});
1265
                        my $md5_added = 0;
1266
                        foreach my $info (@{$item->{'file_info'}}) {
1267
                            push @items, $info;
1268
                            $md5_added = 1 if ($info =~ m~^MD5=~i);
6364 dpurdie 1269
                        }
6981 dpurdie 1270
                        if ($include_md5 && $md5_added == 0) { # add md5 if requested and not already added from submanifest
1271
                            my $md5 = digest_file_hex($emf->{'file_base'} . '/' . $item->{'file_name'}, 'MD5');
1272
                            push @items, "MD5=$md5";
6364 dpurdie 1273
                        }
6981 dpurdie 1274
                        print_mf (join (',', @items));
1275
                        PackageManifestFile ( $name, $tier, $emf->{'file_base'} . '/' . $item->{'file_name'} );
6364 dpurdie 1276
                    }
6981 dpurdie 1277
                    elsif (defined($item->{'comment'})) {
1278
                        print_mf($item->{'comment'});
1279
                    }
6364 dpurdie 1280
                }
6981 dpurdie 1281
                print_mf('#');
1282
            }
1283
            else {
1284
                print_mf ($_) foreach  ( @{$emf->{'contents'}} );
1285
                foreach my $item ( @{$emf->{'items'}}) {
1286
                    if (defined($item->{'file_name'})) {
1287
                        PackageManifestFile ( $name, $tier, $emf->{'file_base'} . '/' . $item->{'file_name'} );
6364 dpurdie 1288
                    }
1289
                }
6981 dpurdie 1290
                print_mf('#');
1129 dpurdie 1291
            }
1119 dpurdie 1292
        }
6981 dpurdie 1293
    }
1119 dpurdie 1294
 
6981 dpurdie 1295
    #
1296
    #   Expand out the entire MUG directory
1297
    #   All .mug files in the MUG directory will be added to the manifest
1298
    #   The assumption is that the MUG directory has been created by
1299
    #   something that knows what its doing
1300
    #
1301
    if ( my $mugdir = $entry->{mugdir} )
1302
    {
1303
        foreach my $file ( glob ($mugdir . '/*.mug' ) )
1119 dpurdie 1304
        {
6981 dpurdie 1305
            next unless ( -f $file );
1306
            my $base_file = StripDir($file);
6314 dpurdie 1307
 
6981 dpurdie 1308
            my @items = ($name, $tier, $base_file);
6314 dpurdie 1309
 
6981 dpurdie 1310
            if ($include_md5) {
1311
                my $md5 = digest_file_hex($file, 'MD5');
1312
                push @items, "MD5=$md5" ;
1119 dpurdie 1313
            }
6981 dpurdie 1314
            print_mf (join (',', @items));
1315
            PackageManifestFile ($name, $tier, $file );
1119 dpurdie 1316
        }
1317
    }
6981 dpurdie 1318
}
1119 dpurdie 1319
 
6981 dpurdie 1320
 
1321
#-------------------------------------------------------------------------------
1322
# Function        : templateProcessing 
1323
#
1324
# Description     : The manifest is created from a povided manifest with MUST
1325
#                   have one or more insertion points
1326
#                   
1327
#                   Purpose: Pulse can provide a template and SI teams can
1328
#                            insert there own packages 
1329
#
1330
# Inputs          : Globals
1331
#
1332
# Returns         : 
1333
#
1334
sub templateProcessing
1335
{
1336
    my $insertFound;
1337
    my $last_was_comment;
1338
 
1119 dpurdie 1339
    #
6981 dpurdie 1340
    #   Open the template manifest and process each line
1119 dpurdie 1341
    #
6981 dpurdie 1342
    print_mf( '#Start of Template from: ' . $templateMode->{'package'} );
1343
    my $tfile;
1344
    my $line;
1345
    open( $tfile, '<', $templateMode->{'manifest'} ) || Error ("Cound not open template manifest: $?", "File: $templateMode->{'manifest'}");
1346
    while ( <$tfile> ) {
1347
        $line = $_;
1348
        $line =~ s~\s+$~~;
1349
        next unless ($line);
1121 dpurdie 1350
 
6981 dpurdie 1351
        #
1352
        #   Detect insertion point
1353
        #
1354
        if ($line =~ m~^##INSERT POINT~) {
1355
            $line =~ m~\[Name:(.+)\].*\[Tier:(.+)\]~i;
1356
            my $iname = $1;
1357
            my $itier = $2;
1358
            print_mf ("# Start of Template Insert: $iname, $itier");
1359
            templateInsert($iname,$itier);
1360
            print_mf ("# End of Template Insert: $iname, $itier");
1361
            $insertFound = 1;
1362
            next;
1363
 
1364
        } elsif( $line =~ m~^#$~) {
1365
            # Ignore 'empty' comment lines
1366
            # They will be regenerated
1367
            next;
6932 dpurdie 1368
 
6981 dpurdie 1369
        } elsif( $line =~ m~^#~) {
1370
            # Non empty comments are transferred
1371
            print_mf ('') unless ( $last_was_comment ) ;
1372
            print_mf( $line);
1373
            $last_was_comment = 1;
1374
            next;
1375
 
1376
        } elsif ($line =~ m~^\[~ ) {
1377
            # Metadata from the template
1378
            # Insert it as a comment
1379
            print_mf( '#' . $line);
1380
            next;
1381
        }
1382
        print_mf ('#') if ( $last_was_comment);
1383
        $last_was_comment = 0;
1384
 
1385
        my( $aname, $atier, $afile, @additionnal_info) = split(/\s*\,\s*/, $line);
1386
        my $test = CatPaths($templateMode->{manifest_dir}, $afile);
1387
        ReportError("Template processing: File not found with template: $afile", $test) unless -f $test;
1388
 
1389
        print_mf( $line);
1390
        PackageManifestFile ( $aname, $atier, $test );
1391
 
1392
    }
1393
    close $tfile;
1394
 
6932 dpurdie 1395
    #
6981 dpurdie 1396
    #   Sanity Checks
1397
    #       Was an insertion point found
1398
    #       Were all manifest bits used
1121 dpurdie 1399
    #
6981 dpurdie 1400
    ReportError ("No insertion points in template") unless $insertFound;
1401
 
1402
    my @notUsed;
1403
    my @overUsed;
1404
 
1405
    foreach my $entry ( @Manifests ) {
1406
        if ( !exists $entry->{wasProcessed}) {
1407
            push @notUsed, "Name: $entry->{name}, Tier: $entry->{tier}";
1408
        } elsif ($entry->{wasProcessed} > 1) {
1409
            push @overUsed, "Name: $entry->{name}, Tier: $entry->{tier}";
1121 dpurdie 1410
        }
1411
    }
6981 dpurdie 1412
    Warning ("Template did not used data from: ", @notUsed)  if @notUsed;
1413
    Warning ("Template used data multiple times from: ", @overUsed)  if @overUsed;
1414
    ErrorDoExit();
6932 dpurdie 1415
}
1416
 
1417
#-------------------------------------------------------------------------------
6981 dpurdie 1418
# Function        : templateInsert 
1419
#
1420
# Description     : Helper routine to insert required bits into the template
1421
#                   Need to scan the manifest entries and determine which need
1422
#                   to be inserted at this point in the template.
1423
#
1424
# Inputs          : $iname  - Insert name
1425
#                   $itier  - Insert Tier
1426
#
1427
# Returns         : Nothing
1428
#
1429
sub templateInsert
1430
{
1431
    my ($iname, $itier) = @_;
1432
    foreach my $entry ( @Manifests ) {
1433
        next unless ((($iname eq '*') || ($iname eq $entry->{name}) ) && (($itier eq '*') || ($itier eq $entry->{tier})) );
1434
        processManifestEntry($entry);
1435
    }
1436
}
1437
 
1438
#-------------------------------------------------------------------------------
6932 dpurdie 1439
# Function        : print_mf
1440
#
1441
# Description     : Internal Function
1442
#                   Print one line to the Manifest File
1443
#                   Checks the length of the line being created
1444
#
1445
# Inputs          : $line
1446
#
1447
# Returns         :
1448
#
1449
 
1450
sub print_mf
1451
{
1452
    foreach  ( @_ )
1121 dpurdie 1453
    {
6932 dpurdie 1454
        my $ll = length ($_);
1455
        ReportError ( "Manifest line too long: $ll. Max is $ManifestLineWidth.",
1456
                "Line: $_" ) if ( $ManifestLineWidth && $ll > $ManifestLineWidth);
1457
        print MF $_ . "\n";
1121 dpurdie 1458
    }
6932 dpurdie 1459
}
1121 dpurdie 1460
 
6932 dpurdie 1461
#-------------------------------------------------------------------------------
1462
# Function        : PackageManifestFile  
1463
#
1464
# Description     : Process and package a manifest file
6978 dpurdie 1465
#                       Retain a list of files in the manifest to allow postprocessing
6932 dpurdie 1466
#                       such as signature generation
1467
#                   
1468
#
6962 dpurdie 1469
# Inputs          : $name           - Target platform name
1470
#                   $tier           - Target tier
1471
#                   $srcFile        - Full path to the source file
6932 dpurdie 1472
#
1473
# Returns         : Nothing
1474
#
1475
sub PackageManifestFile {
6962 dpurdie 1476
    my ($name, $tier, $srcFile ) = @_;
1477
    push @{$ManifestFiles}, ({srcFile => $srcFile, name =>$name, tier => $tier});
1119 dpurdie 1478
 
6981 dpurdie 1479
    PackageFile ('*', $srcFile, '--Subdir=' . $pkg_subdir, '--Strip' );
6932 dpurdie 1480
}
1481
 
1482
#-------------------------------------------------------------------------------
1483
# Function        : GenSigInit 
1484
#
1485
# Description     : Initialise the Siganture Generation process
1486
#                   Populate some globals for use in creating the manifest
1487
#                   Bail if there are errors
1488
#
1489
# Inputs          : 
1490
#
1491
# Returns         : 
1492
#
1493
sub GenSigInit
1494
{
6933 dpurdie 1495
    Debug("GenSigInit:", $noSigs);
6932 dpurdie 1496
    return if $noSigs;
1497
 
1498
    my @warnings;
1499
 
1119 dpurdie 1500
    #
6933 dpurdie 1501
    #   Locate and setup openssl
1502
    #   Should be provided by a package
1503
    #   set OPENSSL_CONF=...../openssl.cfg 
1504
    #   
1505
    $opensslProg = ::ToolExtensionProgram( 'openssl', '', '.exe');
1506
 
1507
    #   Generate  a dummy openssl.cnf - to keep the uitility happy (quiet)
1508
    $opensslConf = FullPath(CatPaths( $::ScmRoot, $::ScmInterface, 'openssl.cfg'));
1509
    TouchFile($opensslConf);
1510
    ::ToolsetGenerate($opensslConf);
1511
    $ENV{OPENSSL_CONF}= $opensslConf;
1512
 
1513
    #
1514
    #   Figure out default operation if openssl cannot be found
1515
    #       If --signature - then report error
1516
    #       If not specified, then default is -NoSig
1517
    #
1518
    unless ($opensslProg) {
1519
        if (defined $noSigs) {
1520
            ReportError ("The openssl utility is not available. Must be provided by a package") unless $opensslProg;  
1521
        } else {
1522
            Verbose("openssl not found in a package. Default to no signature");
1523
            $noSigs = 1;
1524
            return;
1525
        }
1526
    }
1527
 
1528
    #
6932 dpurdie 1529
    #   Signatures 'should' be generated for a target paltform of 'MANSIG'
1530
    #       In the automated build system this will be a controlled machine
1531
    #   Warn if attemting to create signatures for a different target    
1119 dpurdie 1532
    #
6932 dpurdie 1533
    push @warnings, "# Package build for platform other than MANSIG - will generate test signatures" if ($::ScmPlatform ne 'MANSIG');
1534
 
1535
 
1119 dpurdie 1536
    #
6932 dpurdie 1537
    #   Locate the signature file
1538
    #   Use an internal key that unless being run on a controlled build machine
1539
    #   The controlled build machine will have
1540
    #       GBE_MANIFEST_KEY set to a path that contains the keyfile
1541
    #           Yes, a user can fudge this, but not with the real file
1542
    #          
1543
    #  Internal cert created with:
1544
    #  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 1545
    #
6932 dpurdie 1546
    $keyFile = CatPaths( $pkgBase, 'VixPulseManifestTest.key');
1547
    my $localKey = 1;
1548
    if (exists $ENV{GBE_MANIFEST_KEY} ) {
1549
        $keyFile = $ENV{GBE_MANIFEST_KEY};
1550
        $localKey = 0;
1551
    }
1552
    $certFile = $keyFile;
1553
    $certFile =~ s~\.key$~.crt~;
1554
    $certName = $certFile;
1555
    $certName =~ s~.*[\\/]~~;
1119 dpurdie 1556
 
6932 dpurdie 1557
    ReportError ("Manifest signing key not found", $keyFile) unless -f $keyFile;
1558
    ReportError ("Manifest signing key not found", $certFile) unless -f $certFile;
1559
 
1560
    push @warnings, "#  Using uncontrolled test key to sign the manifest" if ($localKey);
1561
    Warning("#############################################################", "#",
1562
             @warnings,
1563
            "#", "#############################################################") if (@warnings);
1564
 
1565
    ErrorDoExit();
1566
    Message("OpenSsl Prog: $opensslProg");
1567
    Message("OpenSsl Conf: $opensslConf");
1568
    Message("Signing with: $keyFile");
1569
 
1119 dpurdie 1570
}
1571
 
6932 dpurdie 1572
#-------------------------------------------------------------------------------
1573
# Function        : GenSignatures 
1574
#
1575
# Description     : Generate signatures on all packages
1576
#
1577
# Inputs          : Used the array of files in $ManifestFiles 
1578
#
1579
# Returns         : Nothing 
1580
#
1581
sub GenSignatures
1582
{
6933 dpurdie 1583
    Debug("GenSignatures:", $noSigs);
6932 dpurdie 1584
    return if $noSigs;
5767 alewis 1585
 
6962 dpurdie 1586
    my %sigManifest;
1587
 
6932 dpurdie 1588
    foreach my $entry ( @{$ManifestFiles}) {
6962 dpurdie 1589
        Verbose("PostProcess: $entry->{srcFile}");
6932 dpurdie 1590
 
1591
        #
1592
        #   Generate the name of the signature file
1593
        #   Generate Packaging directives for the signature
1594
        #   
1595
        my $sigFileName = CatPaths( "$::ScmPlatform.LIB", StripDir($entry->{srcFile}) . '.sig' );
6981 dpurdie 1596
        PackageFile ('*', $sigFileName, '--Subdir=' . $pkg_subdir, '--Strip' );
6932 dpurdie 1597
        ::ToolsetGenerate($sigFileName);
1598
 
1599
        #
6962 dpurdie 1600
        #   Generate the name/tier for the manifest signature
1601
        #       ie: Manifest_<name>_<tier>.sig
1602
        #   Generate the name for the manifest signature
1603
        #       ie: Manifest_<name>.sig
1604
        #   Will generate signature of signatures
6932 dpurdie 1605
        #
6962 dpurdie 1606
        my $sigManifest =  join('_', $entry->{name}, $entry->{tier});
1607
        push @{$sigManifest{$sigManifest}}, $sigFileName;
1608
        push @{$sigManifest{$entry->{name}}}, $sigFileName;
6932 dpurdie 1609
 
1610
 
6962 dpurdie 1611
        # Generate the signature over the file
1612
        genSigForFile($entry->{srcFile}, $sigFileName);
1613
    }
1614
 
1615
    #
1616
    #   Create a file of signatures
1617
    #   Create one for each platform/tier
1618
    #
1619
    foreach my $nameTier ( keys %sigManifest)
1620
    {
1621
        Verbose("PostProcessSig: $nameTier");
1622
        my $sigSigTemp = $manifestName . '_' . $nameTier . '.sig';
1623
        my $sigSigTempCat = $sigSigTemp . '.content';
1624
        ::ToolsetGenerate($sigSigTemp, $sigSigTempCat);
6981 dpurdie 1625
        PackageFile ('*', $sigSigTemp, '--Subdir=' . $pkg_subdir, '--Strip' );
6962 dpurdie 1626
 
6932 dpurdie 1627
        #
6962 dpurdie 1628
        #   Concatenate the contents of the required .sig files
1629
        #   Treat them as binary files. 
1630
        #
1631
        open  (my $ofh, '>', $sigSigTempCat ) || Error( "Cannot create file: $sigSigTempCat", "Reason: $!" );
1632
        binmode ($ofh);
1633
        foreach my $entry (@{$sigManifest{$nameTier}}) {
1634
            Verbose("PostProcessSig: $entry");
1635
            open( my $file, '<', $entry ) || Error("Cannot open '$entry'. $!");
1636
            binmode ($file);
1637
            my @lines = <$file>;
1638
            close $file;
6932 dpurdie 1639
 
6962 dpurdie 1640
            foreach my $entry ( @lines ) {
1641
                print $ofh $entry;
1642
            }
6932 dpurdie 1643
        }
6962 dpurdie 1644
        close $ofh;
6932 dpurdie 1645
 
6962 dpurdie 1646
        #
1647
        #   Generate a signature over the file
1648
        #
1649
        genSigForFile($sigSigTempCat, $sigSigTemp);
1650
        #unlink $sigSigTempCat;
6932 dpurdie 1651
    }
6962 dpurdie 1652
 
6932 dpurdie 1653
    unlink $opensslConf;
5767 alewis 1654
}
1655
 
6962 dpurdie 1656
#-------------------------------------------------------------------------------
1657
# Function        : genSigForFile 
1658
#
1659
# Description     : Generate a .sig file for a named file (internal)
1660
#                   Will be smart and only 'touch' the output file if the input has chnaged
1661
#                       It will maintain a fingerprint file to do this.
1662
#                   
1663
#                   Generate package signature
1664
#                   The required custom(vix) 'sig' file has the format:
1665
#                       line-1 : name of the certificate to decode
1666
#                                Assume its the keyname with .key -> .crt - with no path elements
1667
#                       line-2 : Text representation of the signature (base64)
1668
#                                The openssl dgst command generates a binary output by default
1669
#                                This is then converted into base64 with -A option
1670
#                   
1671
# Inputs          : $srcFile        - Source file to process
1672
#                   $tgtFile        - Output file name
1673
#
1674
# Returns         : 
1675
#
1676
sub genSigForFile
1677
{
1678
    my ($srcFile, $tgtFile) = @_;
5767 alewis 1679
 
6962 dpurdie 1680
    my $tmp1 = CatPaths( "$::ScmPlatform.LIB", 'temp1');
1681
    my $tmp2 = CatPaths( "$::ScmPlatform.LIB", 'temp2');
1682
    ::ToolsetGenerate($tmp1, $tmp2);
1683
 
1684
    Verbose("Signing: " . StripDir($srcFile));
1685
    System( '--Exit', '--NoShell', $opensslProg, 'dgst', '-sha256', '-sign', $keyFile, '-out', $tmp1, $srcFile );
1686
    System( '--Exit', '--NoShell', $opensslProg, 'base64', '-A', '-in', $tmp1, '-out', $tmp2 );
1687
    my $base64 = TagFileRead($tmp2);
1688
 
1689
    #
1690
    #   In a development environment we don't want to create the signature file every time we run. Its noisy. 
1691
    #   Solution: Only generate a signature file if:
1692
    #               It doesn't exist
1693
    #               A copy of the signed digest doesn't exist (.fpp)
1694
    #               The signed digest has changed
1695
    #   
1696
    my $fppFileName = CatPaths( "$::ScmPlatform.LIB", StripDir($srcFile) . '.fpp' );
1697
    ::ToolsetGenerate($fppFileName);
1698
    my $genSig = 0;
1699
    $genSig = 1 unless ( -e $tgtFile &&  -e $fppFileName);
1700
    unless ($genSig) {
1701
        my $ffp = TagFileRead($fppFileName);
1702
        $genSig = ($ffp ne $base64);
1703
    }
1704
 
1705
    if ($genSig) {
1706
        FileCreate($tgtFile, $certName, $base64);
1707
        rename $tmp2, $fppFileName ;
1708
    }
1709
 
1710
    unlink $tmp1;
1711
    unlink $tmp2;
1712
}
1713
 
5767 alewis 1714
#-------------------------------------------------------------------------------
1715
# Function        : DmfGenerate
1716
#
1717
# Description     : Import an existing manifest
1718
#
1719
# Inputs          : entry   - The manifest that is being processed.
1720
#
1721
# Returns         : Nothing
1722
#
1723
sub DmfGenerate
1724
{
1725
    my ($entry) = @_;
1726
 
1727
    # Get the generation time.
1728
    my $gen_time = time();
1729
 
1730
    my $work_dir = "$::ScmPlatform.BIN/";
1731
    System( "$::GBE_BIN/mkdir -p $work_dir" );
1732
 
1733
    my $name = $entry->{name};
1734
    my $version = $entry->{dmf_version};
1735
 
1736
    # Configure base manifest information.
1737
    my %manifest;
5771 alewis 1738
    $manifest{'mugsetId'} = $name . '_' . $version;
5767 alewis 1739
    $manifest{'name'} = $name;
1740
    $manifest{'version'} = $version;
5771 alewis 1741
    $manifest{'packageName'} = $::ScmBuildPackage;
1742
    $manifest{'packageVersion'} = $::ScmBuildVersionFull;
5767 alewis 1743
    $manifest{'datetime'} = localtime($gen_time);
1744
    $gen_time *= 1000;  # Make to milliseconds
1745
    $manifest{'timestamp'} = $gen_time;
1746
    $manifest{'tier'} = $entry->{tier};
1747
 
1748
    # Process each file.
1749
    my @files = @{ $entry->{files} };
1750
    my $zip = Archive::Zip->new();
1751
    my $i = 0;
1752
    foreach my $fentry ( @files )
1753
    {
1754
        if ( my $file = $fentry->{'file'} )
1755
        {
6302 dpurdie 1756
            my $order = $i + 1;
5767 alewis 1757
            my $base_file = StripDir( $file );
1758
            my $publish_file = $name . '_' . $version . '_' . $order . '.aup';
1759
            my $aup_file = $work_dir . $publish_file;
1760
 
1761
            GenerateCesFile($file, $aup_file, 0x3, $gen_time, $publish_file);
1762
 
1763
            my $file_member = $zip->addFile( $aup_file, $publish_file );
1764
 
1765
            $manifest{'tasks'}[$i]{'order'} = 1 * $order;
1766
            $manifest{'tasks'}[$i]{'filename'} = $base_file;
1767
            $manifest{'tasks'}[$i]{'download'} = $publish_file;
5771 alewis 1768
            $manifest{'tasks'}[$i]{'sha256'} = digest_file_base64($file, 'SHA-256');
1769
            $manifest{'tasks'}[$i]{'size'} = -s $file;
1770
 
5767 alewis 1771
            if ($base_file =~ /\.sh$/)
1772
            {
1773
                $manifest{'tasks'}[$i]{'action'} = 'exec-shell';
1774
            }
1775
            elsif ($base_file =~ /\.deb$/)
1776
            {
1777
                $manifest{'tasks'}[$i]{'action'} = 'dpkg-install';
5771 alewis 1778
 
1779
                my ($pkg_name, $pkg_version, $pkg_arch) = ($base_file =~ /([^_]*)_([^_]*)_(.*)/);
1780
                $manifest{'tasks'}[$i]{'arch'} = $pkg_arch;
1781
                $manifest{'tasks'}[$i]{'name'} = $pkg_name;
1782
                $manifest{'tasks'}[$i]{'version'} = $pkg_version;
5767 alewis 1783
            }
1784
            else
1785
            {
1786
                ReportError ("Manifest entry $base_file does not have a supported DMF install action");
1787
            }
1788
 
1789
            $i = $i + 1;
1790
        }
1791
    }
1792
 
1793
    # Encode and commit the JSON.
1794
    my $json_encoder = JSON->new->allow_nonref;
1795
    my $json = $json_encoder->pretty->encode( \%manifest );
1796
 
1797
    my $manifest_filename = $name . '_' . $version;
1798
    my $aum_filename = $manifest_filename . '_0.aum';
1799
    my $manifest_file = $work_dir . $manifest_filename . '.json';
1800
    my $aum_file = $work_dir . $aum_filename;
1801
 
1802
    # Save our manifest.
1803
    open (J, '>', $manifest_file ) || Error ("Cannot create the DMF Manifest file");
1804
    binmode (J);
1805
    print J $json;
1806
    close J;
1807
 
1808
    GenerateCesFile($manifest_file, $aum_file, 0x2, $gen_time, $aum_filename);
1809
 
1810
    $zip->addFile($aum_file, $aum_filename);
1811
 
1812
    my $zip_filename = $work_dir . $name . '_' . $version . '.zip';
1813
    if ( $zip->writeToFileNamed($zip_filename) != AZ_OK )
1814
    {
1815
        ReportError("DMF ZIP file creation failed");
1816
    }
6981 dpurdie 1817
    PackageFile('*', $zip_filename, '--Strip');
1818
    PackageFile('*', $manifest_file, '--Strip');
5767 alewis 1819
 
1820
}
1821
 
1822
#-------------------------------------------------------------------------------
6981 dpurdie 1823
# Function        : PackageFile  
1824
#
1825
# Description     : Package or Install a manifest file
1826
#
1827
# Inputs          : Same as PackageFile
1828
#
1829
# Returns         : 
1830
#
1831
sub PackageFile
1832
{
1833
    if ($localInstall) {
1834
        ::InstallHdr(@_);
1835
    } else {
1836
        ::PackageFile(@_);
1837
    }
1838
}
1839
 
1840
#-------------------------------------------------------------------------------
6932 dpurdie 1841
# Function        : GenerateCesFile
5767 alewis 1842
#
1843
# Description     : Import an existing manifest
1844
#
1845
# Inputs          : src_file     - The input file.
1846
#                   dst_file     - The output CES file.
1847
#                   content_type - The content type to report.
1848
#                   gen_time     - The generation time for the file.
1849
#                   filename     - The filename to embed in the CES file.
1850
#
1851
#
1852
# Returns         : Nothing
1853
#
1854
sub GenerateCesFile
1855
{
1856
    my ($src_file, $dst_file, $content_type, $gen_time, $filename) = @_;
1857
 
1858
    open (INF, '<', $src_file ) || Error ("Cannot open file $src_file for reading");
1859
    binmode (INF);
1860
 
1861
    open (OUTF, '>', $dst_file ) || Error ("Cannot open file $dst_file for writing");
1862
    binmode (OUTF);
1863
 
1864
    my $signing_key_name = "";
1865
    my $signature_size = 0;
1866
    my $format_version = 0xCE500000;
1867
    my $compression_method = 0;
1868
    my $encryption_method = 0;
1869
    my $kek_name = "";
1870
    my $encryption_key_size = 0;
1871
    my $filename_size = length($filename);
1872
 
1873
    print OUTF pack("Z32", $signing_key_name);
1874
    print OUTF pack("n", $signature_size);
1875
    print OUTF pack("N", $format_version);
1876
    print OUTF pack("N", $content_type);
1877
    print OUTF pack("Q>", $gen_time);
1878
    print OUTF pack("N", $compression_method);
1879
    print OUTF pack("N", $encryption_method);
1880
    print OUTF pack("Z32", $kek_name);
1881
    print OUTF pack("n", $encryption_key_size);
1882
    print OUTF pack("n", $filename_size);
1883
    # Encryption key HERE
1884
    print OUTF pack("A$filename_size", $filename);
1885
 
1886
    my $buf;
1887
    while (read(INF,$buf,65536))
1888
    {
1889
        print OUTF $buf;
1890
    }
1891
    print OUTF $buf;
1892
    close INF;
1893
 
1894
    # Signature HERE
1895
 
1896
    # Finish with file.
1897
    close OUTF;
1898
}
1899
 
1119 dpurdie 1900
1;