Subversion Repositories DevTools

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

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