root/morphix/trunk/morph-scripts/build_minimod

Revision 2, 11.9 kB (checked in by nextime, 2 years ago)

Initial import, branching from morphix svn

  • Property svn:executable set to
Line 
1 #!/usr/bin/perl -w
2 # build_minimod
3 # -- Rene Cunningham Mon,  7 Feb 2005 17:42:19 +0800
4
5 use strict;
6 use Getopt::Std;
7 use File::Basename;
8
9 =pod
10
11 =head1 NAME
12
13 build_minimod - build a minimod from the latest packages that you specify on the command line.
14
15 =head1 SYNOPSIS
16
17 build_minimod [MINIMOD NAME].. [MORPHIX DIR].. [OUTPUT MODULE].. [PACKAGES]..
18
19 =head1 DESCRIPTION
20
21 build_minimod is a perl script that builds a minimod from the latest packages that you specify on the command line.
22
23 It uses apt-cache to gather package meta information and downloads these packages from the repositorie(s) specified on the command line or located within /etc/apt/sources.list.
24
25 The output is a cloop iso image that can ulitimately be used with a morphix livecd.
26
27 =head1 OPTIONS
28
29 All options are mandetory unless specified optional.
30
31 -n [name]
32     The minimod name
33
34 -m [directory]
35     The morphix directory that will be copied within the minimod. This directory should contain the loadmod.sh shell script which will be sourced by the morphix base.
36
37 -r [repository]
38     An optional argument where packages are specified instead of the repositories found within /etc/apt/sources.list
39
40 -o [file]
41     The output cloop iso image.
42
43 -p [packages|file]
44     A list of packages or a file that contains a list of packages that will be extracted and copied into the minimod.
45
46
47 =head1 EXAMPLES
48
49 build a minimod that is called sendmail, uses /home/rene/morphix as the morphix dir, contains a few sendmail and a spamassassin package and outputs to /home/rene/sendmail.mod
50
51 $ build_minimod -n sendmail -m /home/rene/morphix -o /home/rene/sendmail.mod -p sendmail sendmail-base sendmail-bin sendmail-cf spamassassin
52
53 =head1 NOTES
54
55 Debian packages are downloaded from the debian repositories that are found in your /etc/apt/sources.list file.
56
57 The packages {post,pre}insts are not used but are copied to /usr/src/build_mod/{minimod name}/build/{package}/control/. Its up to the user to move the code into mini module, usually done in morphix/loadmod.sh.
58
59 =head1 BUGS
60
61 Please email bug reports to rene@dclabs.com.au
62
63 =head1 AUTHOR
64
65 Rene Cunningham <rene@dclabs.com.au>
66
67 =cut
68
69 my $version = '0.5';
70
71 my $tmp;
72 my @tmp;
73 my $verbose = 1;
74 my %options;
75 my $minimod_name;
76 my $cache_file;
77 my $morphix_dir;
78 my $output_mod;
79 my $debian_mirror;
80 my $apt_archive = '/var/cache/apt/archive';
81 my $basename = basename($0);
82 my @needed_files = ('/usr/sbin/module-builder');
83
84 if ($> ne '0') {
85     print "$basename: you must run this as root\n";
86     exit(0);
87 }
88
89 foreach my $file (@needed_files) {
90     if (not -f $file) {
91         print "$basename: cant find file $file\n";
92         exit(0);
93     }
94 }
95
96 getopts("vr:hn:m:po:",\%options);
97
98 # needed argvs
99 if(defined $options{n}) {
100     $minimod_name = $options{n};
101 } else {
102     &usage;
103     exit(0);
104 }
105
106 if(defined $options{m}) {
107     $morphix_dir = $options{m};
108 } else {
109     &usage;
110     exit(0);
111 }
112
113 if(defined $options{o}) {
114     $output_mod = $options{o};
115 } else {
116     &usage;
117     exit(0);
118 }
119
120 if (defined $options{v}) {
121     $verbose = 1;
122 }
123
124 $minimod_name = "NULL" unless defined $minimod_name;
125
126 my $minimod_dir = "/usr/src/build_minimod/$minimod_name";
127 my $build_cache_dir = "$minimod_dir/packages";
128 my $build_temp_dir = "$minimod_dir/temp";
129 my $build_dir = "$minimod_dir/build";
130 my $exec_path = $ENV{PWD};
131 my $cmd;
132
133 # global hash used by most routines
134 our %package_info;
135
136 $build_cache_dir =~ s/\/+$// if substr($build_cache_dir,-1) eq '/';
137
138 #-- Helper Routines --#
139
140 # Find and return the latest package within our cache dir
141 sub find_package_in_cache ($) {
142     my @files;
143     my $p = shift;
144     my $f;
145     @files = `ls -1 $build_cache_dir | grep "^$p"`;
146     $f = pop(@files);
147     chomp($f) if defined $f;
148     if (defined $f) {
149         return $f;
150     } else {
151         return;
152     }
153 }
154
155 sub print_and_execute_cmd ($) {
156     my $cmd = shift;
157     print "Executing: $cmd\n";
158     system("$cmd");
159 }
160
161 sub print_info {
162     print "Packages were downloaded and stored in $build_cache_dir\n";
163     print "The build dir for your mini module is $build_dir/temp\n";
164 }
165
166 # Copy contents of users morphix dir over to build_dir
167 sub copy_morphix_dir  {
168     $cmd = "rm -rf $build_dir/temp/morphix/";
169     &print_and_execute_cmd($cmd);
170     $cmd = "mkdir $build_dir/temp/morphix/";
171     &print_and_execute_cmd($cmd);
172     $cmd = "cp -a $exec_path/$morphix_dir/* $build_dir/temp/morphix/";
173     &print_and_execute_cmd($cmd);
174 }
175
176 # wrapper routine for module-builder
177 sub create_cloop ($) {
178     my $cmd;
179     my $dir = "$build_cache_dir/";
180     print "dir is $dir\n";
181     if (-d $dir) {
182         $cmd = "sudo module-builder -t iso9660 $build_dir/temp $output_mod";
183         &print_and_execute_cmd($cmd);
184     }
185 }
186
187 sub setup_build_dir {
188     my $cmd;
189
190     $cmd = "mkdir -p $build_dir/temp";
191     &print_and_execute_cmd($cmd);
192 }
193
194 sub clean_build_dir {
195     my $cmd;
196     $cmd = "rm -rf $build_dir/*";
197     &print_and_execute_cmd($cmd);
198 }
199
200 sub usage {
201     print <<EOF
202 name: $basename
203 author: Rene Cunningham <rene\@dclabs.com.au>
204 version: $version
205 description: build a minimod from the latest packages that you specify on the command line.
206
207 usage: $basename [MINIMOD NAME].. [MORPHIX DIR].. [OUTPUT MODULE].. [PACKAGES]..
208
209 -v                              verbose
210 -n [name]                       the name of the minimodule
211 -m [dir]                        the directory of your minimods /morphix
212 -r [repository]                 the debian repository <defaults to $debian_mirror>
213 -o [file]                       output mini module
214 -p [package(s)]                 a list of debian packages to install in the minimodule or a text file that contains a list of debian packages
215
216 example:
217 $basename -n sendmail -m /home/rene/morphix -o /home/rene/sendmail.mod -p sendmail sendmail-base sendmail-bin sendmail-cf spamassassin
218
219 For more information, perldoc build_minimod
220
221 EOF
222
223 }
224
225 sub getdeb ($) {
226     my $pkg = shift;
227     my $uri;
228
229     open(PIPE,"apt-get -q2 --print-uris --reinstall install $pkg 2>&1 | grep $pkg |") or die "cant open pipe : $!\n";
230
231     while (my $line = <PIPE>) {
232         $uri = (split /\'/, $line)[1];
233     }
234     system("wget -P $build_cache_dir -c $uri");
235 }
236
237 #-- Main Routines --#
238
239 # Populate %package_info with information regarding the package
240 sub get_package_info ($) {
241
242     my $package = shift;
243     my $flag;
244     my (@version,$version);
245     my $uri;
246     my $arch;
247     my $filename;
248     my %seen = ();
249
250     $cache_file = '';
251
252     chomp($package);
253
254     # clear %package_info
255     %package_info = ();
256
257     $package_info{package} = $package;
258     $package_info{na} = 1;
259
260     print "\nPackage name    : $package_info{package}\n" if $verbose eq 1;
261
262     open(PIPE,"apt-cache show $package 2>/dev/null |") or die "Could not open a pipe from apt-cache command : $!\n";
263    
264     while (my $line = <PIPE>) {
265
266         # Check to see if package is in our apt-cache.
267         if($line =~ /^Package:/) {
268             $package_info{na} = 0;
269         }
270
271         if ($line =~ /^Version:/) {
272             chomp($line);
273             $version = (split /Version:/, $line)[1];
274             $version =~ s/\s//;
275             $version =~ s/[\d\w]+://;
276             if(defined $version and not defined $seen{version}) {
277                 $seen{version} = 1;
278                 $package_info{version} = $version;
279                 print "Package version : $package_info{version}\n" if $verbose eq 1;
280             }
281         }
282
283         if ($line =~ /^Filename:/) {
284             chomp($line);
285             $uri = (split /:/, $line)[1];
286             if(defined $uri and not defined $seen{uri}) {
287                 $seen{uri} = 1;
288                 $uri =~ s/\s//;
289                 $package_info{uri} = $uri;
290                 print "Package URI     : $package_info{uri}\n" if $verbose eq 1;
291             }
292         }
293
294         if($line =~ /^Architecture:/) {
295             chomp($line);
296             $arch = (split /:/, $line)[1]; if(defined $arch and not defined $seen{arch}) {
297                 $seen{arch} = 1;
298                 $arch =~ s/\s//;
299                 $package_info{arch} = $arch;
300                 print "Package Arch    : $package_info{arch}\n" if $verbose eq 1;
301             }
302         }           
303
304     }
305
306     close(PIPE);
307
308     # make warnings happy
309     if (defined $package_info{arch}) {
310         $filename = $package_info{package}
311                     ."_"
312                     .$package_info{version}
313                     ."_"
314                     .$package_info{arch}
315                     .".deb";
316     }
317
318     $package_info{filename} = $filename;
319
320     # Maybe apt-cache doesnt know about our package, though
321     # we have the package file in our cache dir.
322     if ($package_info{na} eq '1') {
323         if($cache_file = &find_package_in_cache($package_info{package})) {
324             $package_info{na} = '0';
325             # Create meta information from cache file
326             $cache_file =~ /([a-z-]+)_([\d\w\.-]+)_([\d\w]+)\.deb/;
327             $package_info{version} = "$2";
328             $package_info{arch} = "$3";
329         }
330     }
331
332     # If apt-cache doesnt return a URI then check
333     # to see if we have the package in our cache dir.
334     # If we dont have a package in our cache dir, and
335     # the package doesnt have a URI mark it as NA
336     if (not defined $package_info{uri} and
337             $package_info{na} ne '1') {
338         if (not $cache_file = &find_package_in_cache($package_info{package})) {
339             $package_info{na} = 1;
340         }
341     }
342
343
344 }
345
346 sub download_package ($) {
347
348     my $apt_sources = '/etc/apt/sources.list';
349     my $version;
350     my $fc;
351     my $cmd;
352     my $url;
353
354     if ($package_info{na} eq '1') {
355         print "$basename : $package_info{package} cant be found in apt-cache\n";
356         return;
357     }
358
359     if (defined $package_info{filename}) {
360         # return if we already have the file in our cache dir
361         if (-f "$build_cache_dir/$package_info{filename}") {
362             print "$basename : $package_info{filename} is already in cache dir.. not downloading\n";
363             return;
364         } elsif (-f "$apt_archive"."$package_info{filename}") {
365             print "$basename : $package_info{filename} is already in apt archive dir.. not downloading\n";
366             $cmd = "cp $apt_archive"."$package_info{filename}";
367             &print_and_execute_cmd($cmd);
368             return;
369         }
370     }
371
372     # work out if the package belongs in a lib[a-z] pool dir
373     if($package_info{package} =~ /lib[a-z]/) {
374         $fc = substr($package_info{package}, 0, 4);
375     } else {
376         $fc = substr($package_info{package}, 0, 1);
377     }
378
379     # if the user specifies a repository, use it
380     if (defined $package_info{uri}) {
381         if (defined $options{r}) {
382             $url = $options{r};
383             $url =~ s/\/+$// if substr($url,-1) eq '/';
384             $cmd = "wget -c $url/$package_info{uri} -P $build_cache_dir 2>/dev/null";
385             &print_and_execute_cmd($cmd);
386         } else {
387             &getdeb($package_info{package});
388         }
389     } elsif (defined $cache_file) {
390         print "$basename : couldnt download $package_info{package} from repositories within sources.list, but found $cache_file in cache dir\n";
391         return;
392     }
393
394     # had to do this again because -w was complaining
395     if (defined $cache_file and not -f $package_info{filename}) {
396         print "$basename : couldnt download $package_info{filename} from repositories within sources.list, but found $cache_file in cache dir\n";
397     }
398
399 }
400
401 sub unpack_and_copy_package {
402
403     my $file;
404     my $cmd;
405
406     if ($package_info{na} eq '1') {
407         return;
408     }
409
410     if (defined $package_info{uri}) {
411         $file = "$build_cache_dir/$package_info{filename}";
412         print "file is $build_cache_dir/$cache_file\n";
413     } else {
414         $file = "$build_cache_dir/$cache_file";
415         print "file is $build_cache_dir/$cache_file\n";
416     }
417
418     if (-f $file) {
419         $cmd = "rm -rf $build_dir/$package_info{package}";
420         &print_and_execute_cmd($cmd);
421         $cmd = "mkdir -p $build_dir/$package_info{package}";
422         &print_and_execute_cmd($cmd);
423         chdir "$build_dir/$package_info{package}";
424         $cmd = "ar -x $file";
425         &print_and_execute_cmd($cmd);
426         $cmd = "mkdir control";
427         &print_and_execute_cmd($cmd);
428         $cmd = "tar zxvf control.tar.gz -C control";
429         &print_and_execute_cmd($cmd);
430         $cmd = "tar zxvf data.tar.gz -C ../temp";
431         &print_and_execute_cmd($cmd);
432     }
433
434     print "\n\n";
435
436 }
437
438 if (defined $options{h}) {
439     &usage;
440     exit(0);
441 }
442
443 if(defined $options{p}) {
444
445     if(not defined $minimod_name) {
446         &usage;
447         exit(0);
448     }
449
450     &clean_build_dir;
451     &setup_build_dir;
452
453     if (-f $ARGV[0]) {
454         $tmp = $ARGV[0];
455         open(PKGFILE, "$tmp") or die "cant open $tmp : $!\n";
456         while (my $line = <PKGFILE>) {
457             if($line =~ /^\w/) {
458                 chomp($line);
459                 push(@tmp,$line);
460             }
461         }
462         close(PKGFILE);
463         foreach my $p (@tmp) {
464             &get_package_info($p);
465             &download_package;
466             &unpack_and_copy_package;
467         }
468     } else {
469         foreach my $p (@ARGV) {
470             &get_package_info($p);
471             &download_package;
472             &unpack_and_copy_package;
473         }
474     }
475
476     &copy_morphix_dir;
477     &create_cloop;
478     &print_info;
479     exit(0);
480 } 
Note: See TracBrowser for help on using the browser.