1 | #!/usr/bin/perl -w
|
---|
2 | #
|
---|
3 | # pbmkbm, a project-builder.org utility to make boot media
|
---|
4 | #
|
---|
5 | # $Id$
|
---|
6 | #
|
---|
7 | # Copyright B. Cornec 2011
|
---|
8 | # Provided under the GPL v2
|
---|
9 |
|
---|
10 | # Syntax: see at end
|
---|
11 |
|
---|
12 | use strict 'vars';
|
---|
13 | use Getopt::Long qw(:config auto_abbrev no_ignore_case);
|
---|
14 | use Data::Dumper;
|
---|
15 | use English;
|
---|
16 | use File::Basename;
|
---|
17 | use File::Copy;
|
---|
18 | use File::Find;
|
---|
19 | use POSIX qw(strftime);
|
---|
20 |
|
---|
21 | use ProjectBuilder::Version;
|
---|
22 | use ProjectBuilder::Base;
|
---|
23 | use ProjectBuilder::Env;
|
---|
24 | use ProjectBuilder::Conf;
|
---|
25 | use ProjectBuilder::Distribution;
|
---|
26 | use ProjectBuilder::VE;
|
---|
27 |
|
---|
28 | # Global variables
|
---|
29 | my %opts; # CLI Options
|
---|
30 |
|
---|
31 | =pod
|
---|
32 |
|
---|
33 | =head1 NAME
|
---|
34 |
|
---|
35 | pbmkbm - a project-builder.org utility to make boot media
|
---|
36 |
|
---|
37 | =head1 DESCRIPTION
|
---|
38 |
|
---|
39 | pbmkbm creates a bootable media (CD/DVD, USB device, Network, tape, ...)
|
---|
40 | with a minimal distribution in it, suited for building packages for example.
|
---|
41 | It aims at supporting all distributions supported by project-builder.org
|
---|
42 | (RHEL, RH, Fedora, OpeSUSE, SLES, Mandriva, ...)
|
---|
43 |
|
---|
44 | It is inspired by work done by Jean-Marc André around the HP SSSTK and
|
---|
45 | aim at replacing the mindi project (http://www.mondorescue.org), but
|
---|
46 | fully integrated with project-builder.org
|
---|
47 |
|
---|
48 | pbmkbm works in different phases. The first one is to check all
|
---|
49 |
|
---|
50 | pbmkbm needs to gather a certain number of components that could come
|
---|
51 | from various sources and could be put on a different target media.
|
---|
52 | We need a kernel, an initrd/initramfs for additional modules and init script,
|
---|
53 | a root filesystem and a boot configuration file.
|
---|
54 | Kernel, modules could come either from the local installed system
|
---|
55 | (typically for disaster recovery context) or from a kernel package of a
|
---|
56 | given configuration or a referenced content.
|
---|
57 | Utilities could come from busybox, local utilities or set of packages.
|
---|
58 | The root filesystem is made with them.
|
---|
59 | The initrd/initramfs could be made internaly or by calling dracut.
|
---|
60 | The boot config file is generated from analysis content or provided externally.
|
---|
61 |
|
---|
62 | =head1 SYNOPSIS
|
---|
63 |
|
---|
64 | pbmkbm [-vhq][-t boot-type [-d device]][-b boot-method][-m os-ver-arch]
|
---|
65 | [-s script][-a pkg1[,pkg2,...]] [target-dir]
|
---|
66 |
|
---|
67 | pbmkbm [--verbose][--help][--man][--quiet][--type boot-type [--device device]]
|
---|
68 | [--machine os-ver-arch][--boot boot-method]
|
---|
69 | [--script script][--add pkg1,[pkg2,...]] [target-dir]
|
---|
70 |
|
---|
71 | =head1 OPTIONS
|
---|
72 |
|
---|
73 | =over 4
|
---|
74 |
|
---|
75 | =item B<-v|--verbose>
|
---|
76 |
|
---|
77 | Print a brief help message and exits.
|
---|
78 |
|
---|
79 | =item B<-h|--help>
|
---|
80 |
|
---|
81 | Print a brief help message and exits.
|
---|
82 |
|
---|
83 | =item B<--man>
|
---|
84 |
|
---|
85 | Prints the manual page and exits.
|
---|
86 |
|
---|
87 | =item B<-q|--quiet>
|
---|
88 |
|
---|
89 | Do not print any output.
|
---|
90 |
|
---|
91 | =item B<-t|--type boot-type>
|
---|
92 |
|
---|
93 | Type of the boot device to generate. A boot-type can be:
|
---|
94 |
|
---|
95 | =over 4
|
---|
96 |
|
---|
97 | =item B<iso>
|
---|
98 |
|
---|
99 | Generate an ISO9660 image format (suitable to be burned later on or loopback mounted. Uses isolinux.
|
---|
100 |
|
---|
101 | =item B<usb>
|
---|
102 |
|
---|
103 | Generate a USB image format (typically a key of external hard drive). Uses syslinux.
|
---|
104 |
|
---|
105 | =item B<pxe>
|
---|
106 |
|
---|
107 | Generate a PXE environement (suitable to be integrated in a PXElinux configuration). Uses pxelinux.
|
---|
108 |
|
---|
109 | =back
|
---|
110 |
|
---|
111 | =item B<-d|--device device-file>
|
---|
112 |
|
---|
113 | Name of the device or file on which you want to create the boot media.
|
---|
114 |
|
---|
115 | =item B<-b|--boot boot-method>
|
---|
116 |
|
---|
117 | This is the boot method to use to create the boot media. A boot-method can be:
|
---|
118 |
|
---|
119 | =over 4
|
---|
120 |
|
---|
121 | =item B<native>
|
---|
122 |
|
---|
123 | Use the tools of the native distribution to create the boot media. No other dependency.
|
---|
124 |
|
---|
125 | =item B<ve>
|
---|
126 |
|
---|
127 | Use the project-builder.org virtual environment notion to create the boot media. No other dependency outside of the project.
|
---|
128 |
|
---|
129 | =item B<busybox>
|
---|
130 |
|
---|
131 | Use the busybox tool to create the boot media. Cf: L<http://www.busybox.net>
|
---|
132 |
|
---|
133 | =item B<dracut>
|
---|
134 |
|
---|
135 | Use the dracut tool to create the boot media. Cf: L<http://www.dracut.net>
|
---|
136 |
|
---|
137 | =back
|
---|
138 |
|
---|
139 | =item B<-s|--script script>
|
---|
140 |
|
---|
141 | Name of the script you want to execute on the related boot media at the end of the build.
|
---|
142 |
|
---|
143 | =item B<-a|--add pkg1[,pkg2,...]>
|
---|
144 |
|
---|
145 | Additional packages to add from the distribution you want to install on the related boot media
|
---|
146 | at the end of the build.
|
---|
147 |
|
---|
148 | =item B<-m|--machine os-ver-arch>
|
---|
149 |
|
---|
150 | This is the target tuple operating system-version-architecture for which you want to create the boot media.
|
---|
151 |
|
---|
152 | =back
|
---|
153 |
|
---|
154 | =head1 ARGUMENTS
|
---|
155 |
|
---|
156 | target-dir is the directory under which the boot media will be build.
|
---|
157 |
|
---|
158 | =over 4
|
---|
159 |
|
---|
160 | =back
|
---|
161 |
|
---|
162 | =head1 EXAMPLE
|
---|
163 |
|
---|
164 | To setup a USB busybox based boot media on the /dev/sdb device for a Fedora 12 distribution with an i386 architecture issue:
|
---|
165 |
|
---|
166 | pbmkbm -t usb -d /dev/sdb -m fedora-12-i386 -b busybox
|
---|
167 |
|
---|
168 | To setup an ISO image under /tmp for a RHEL 6 x86_64 distribution issue using the native environment:
|
---|
169 |
|
---|
170 | pbmkbm -t iso -d /tmp -m rhel-6-x86_64 -b ve
|
---|
171 |
|
---|
172 | =head1 WEB SITES
|
---|
173 |
|
---|
174 | The main Web site of the project is available at L<http://www.project-builder.org/>.
|
---|
175 | Bug reports should be filled using the trac instance of the project at L<http://trac.project-builder.org/>.
|
---|
176 |
|
---|
177 | =head1 USER MAILING LIST
|
---|
178 |
|
---|
179 | Cf: L<http://www.mondorescue.org/sympa/info/pb-announce> for announces and
|
---|
180 | L<http://www.mondorescue.org/sympa/info/pb-devel> for the development of the pb project.
|
---|
181 |
|
---|
182 | =head1 CONFIGURATION FILE
|
---|
183 |
|
---|
184 | Uses Project-Builder.org configuration file (/etc/pb/pb.conf or /usr/local/etc/pb/pb.conf)
|
---|
185 |
|
---|
186 | =head1 AUTHORS
|
---|
187 |
|
---|
188 | The Project-Builder.org team L<http://trac.project-builder.org/> lead by Bruno Cornec L<mailto:bruno@project-builder.org>.
|
---|
189 |
|
---|
190 | =head1 COPYRIGHT
|
---|
191 |
|
---|
192 | Project-Builder.org is distributed under the GPL v2.0 license
|
---|
193 | described in the file C<COPYING> included with the distribution.
|
---|
194 |
|
---|
195 | =cut
|
---|
196 |
|
---|
197 | # ---------------------------------------------------------------------------
|
---|
198 |
|
---|
199 | my ($projectbuilderver,$projectbuilderrev) = pb_version_init();
|
---|
200 | my $appname = "pbmkbm";
|
---|
201 | $ENV{'PBPROJ'} = $appname;
|
---|
202 |
|
---|
203 | # Initialize the syntax string
|
---|
204 |
|
---|
205 | pb_syntax_init("$appname Version $projectbuilderver-$projectbuilderrev\n");
|
---|
206 | pb_temp_init();
|
---|
207 |
|
---|
208 | GetOptions("help|?|h" => \$opts{'h'},
|
---|
209 | "man" => \$opts{'man'},
|
---|
210 | "verbose|v+" => \$opts{'v'},
|
---|
211 | "quiet|q" => \$opts{'q'},
|
---|
212 | "log-files|l=s" => \$opts{'l'},
|
---|
213 | "script|s=s" => \$opts{'s'},
|
---|
214 | "machine|m=s" => \$opts{'m'},
|
---|
215 | "add|a=s" => \$opts{'a'},
|
---|
216 | "device|d=s" => \$opts{'d'},
|
---|
217 | "type|t=s" => \$opts{'t'},
|
---|
218 | "boot|b=s" => \$opts{'b'},
|
---|
219 | "version|V=s" => \$opts{'V'},
|
---|
220 | ) || pb_syntax(-1,0);
|
---|
221 |
|
---|
222 | if (defined $opts{'h'}) {
|
---|
223 | pb_syntax(0,1);
|
---|
224 | }
|
---|
225 | if (defined $opts{'man'}) {
|
---|
226 | pb_syntax(0,2);
|
---|
227 | }
|
---|
228 | if (defined $opts{'v'}) {
|
---|
229 | $pbdebug = $opts{'v'};
|
---|
230 | }
|
---|
231 | if (defined $opts{'q'}) {
|
---|
232 | $pbdebug=-1;
|
---|
233 | }
|
---|
234 | if (defined $opts{'l'}) {
|
---|
235 | open(pbLOG,"> $opts{'l'}") || die "Unable to log to $opts{'l'}: $!";
|
---|
236 | $pbLOG = \*pbLOG;
|
---|
237 | $pbdebug = 0 if ($pbdebug == -1);
|
---|
238 | }
|
---|
239 | pb_log_init($pbdebug, $pbLOG);
|
---|
240 | pb_log(1,"$appname Version $projectbuilderver-$projectbuilderrev\n");
|
---|
241 | my @date = pb_get_date();
|
---|
242 | my $pbdate = strftime("%Y-%m-%d %H:%M:%S", @date);
|
---|
243 |
|
---|
244 | pb_log(1,"Start: $pbdate\n");
|
---|
245 |
|
---|
246 | # Get VE name
|
---|
247 | $ENV{'PBV'} = $opts{'m'};
|
---|
248 |
|
---|
249 | #
|
---|
250 | # Initialize distribution info from pb conf file
|
---|
251 | #
|
---|
252 | my $pbos = pb_distro_get_context($ENV{'PBV'});
|
---|
253 | pb_log(0,"Starting boot media build for $pbos->{'name'}-$pbos->{'version'}-$pbos->{'arch'}\n");
|
---|
254 |
|
---|
255 | pb_env_init_pbrc(); # to get content of HOME/.pbrc
|
---|
256 |
|
---|
257 | # Global hash containing all the configuration information
|
---|
258 | my %mkbm;
|
---|
259 |
|
---|
260 | #
|
---|
261 | # Check target dir
|
---|
262 | # Create if not existent and use default if none given
|
---|
263 | #
|
---|
264 | $mkbm{'targetdir'} = shift @ARGV;
|
---|
265 |
|
---|
266 | #
|
---|
267 | # Check for command requirements
|
---|
268 | #
|
---|
269 | my ($req,$opt) = pb_conf_get_if("oscmd","oscmdopt");
|
---|
270 | pb_check_requirements($req,$opt,$appname);
|
---|
271 |
|
---|
272 | # After that we will need root access
|
---|
273 | die "$appname needs to be run as root" if ($EFFECTIVE_USER_ID != 0);
|
---|
274 |
|
---|
275 | #
|
---|
276 | # Where is our build target directory
|
---|
277 | #
|
---|
278 | if (not defined $mkbm{'targetdir'}) {
|
---|
279 | $mkbm{'targetdir'} = "/var/cache/pbmkbm";
|
---|
280 | my ($vestdpath) = pb_conf_get("mkbmpath");
|
---|
281 | $mkbm{'targetdir'} = "$vestdpath->{'default'}/$pbos->{'name'}/$pbos->{'version'}/$pbos->{'arch'}" if (defined $vestdpath->{'default'});
|
---|
282 | pb_log(1,"No target-dir specified, using $mkbm{'targetdir'}\n");
|
---|
283 | }
|
---|
284 |
|
---|
285 | # Point to the right subdir and create it if needed
|
---|
286 | pb_mkdir_p($mkbm{'targetdir'}) if (! -d $mkbm{'targetdir'});
|
---|
287 |
|
---|
288 | # Log information on our system
|
---|
289 | # TODO: this should be put in a subfunction
|
---|
290 | my ($logcmd) = pb_conf_get("logcmd");
|
---|
291 | my ($logopt) = pb_conf_get_if("logopt");
|
---|
292 | # check that the command is there first and then use it.
|
---|
293 | if ($logcmd->{$appname} ne "internal") {
|
---|
294 | $logcmd = pb_check_req($logcmd->{$appname},1);
|
---|
295 | if (not defined $logcmd) {
|
---|
296 | pb_log(1,"INFO: command $logcmd->{$appname} doesn't exist. No log report is available\n");
|
---|
297 | } else {
|
---|
298 | my $c = $logcmd->{$appname};
|
---|
299 | $c .= " $logopt->{$appname}" if (defined $logopt->{$appname});
|
---|
300 | pb_system("$c","Creating a log report of your system");
|
---|
301 | }
|
---|
302 | } else {
|
---|
303 | # We provide our own internal log reporter as a std one isn't found
|
---|
304 | my ($lcmds,$lfiles) = pb_conf_get_if("logcommands","logfiles");
|
---|
305 | pb_log(1,"------------------\n");
|
---|
306 | if (defined $lcmds->{$appname}) {
|
---|
307 | foreach my $c (split(/,/,$lcmds->{$appname})) {
|
---|
308 | my $lcmd = $c;
|
---|
309 | $lcmd =~ s/ .*$//;
|
---|
310 | $lcmd = pb_check_req($lcmd,1);
|
---|
311 | if (not defined $lcmd) {
|
---|
312 | pb_log(1,"INFO: command $c doesn't exist\n");
|
---|
313 | pb_log(1,"------------------\n");
|
---|
314 | next;
|
---|
315 | }
|
---|
316 | pb_log(1,"Execution of $c\n");
|
---|
317 | pb_log(1,"------------------\n");
|
---|
318 | pb_system($c,"",1);
|
---|
319 | pb_log(1,"------------------\n");
|
---|
320 | }
|
---|
321 | }
|
---|
322 | if (defined $lfiles->{$appname}) {
|
---|
323 | foreach my $f (split(/,/,$lfiles->{$appname})) {
|
---|
324 | if (! -e $f) {
|
---|
325 | pb_log(1,"INFO: $f doesn't exist\n");
|
---|
326 | pb_log(1,"------------------\n");
|
---|
327 | next;
|
---|
328 | }
|
---|
329 | if (! -r $f) {
|
---|
330 | pb_log(1,"INFO: $f isn't readable\n");
|
---|
331 | pb_log(1,"------------------\n");
|
---|
332 | next;
|
---|
333 | }
|
---|
334 | if ((-f $f) || (-l $f)) {
|
---|
335 | if (! open(FILE,$f)) {
|
---|
336 | pb_log(1,"INFO: Unable to open $f\n");
|
---|
337 | pb_log(1,"------------------\n");
|
---|
338 | next;
|
---|
339 | }
|
---|
340 | pb_log(1,"Content of $f\n");
|
---|
341 | pb_log(1,"------------------\n");
|
---|
342 | while (<FILE>) {
|
---|
343 | pb_log(1,$_);
|
---|
344 | }
|
---|
345 | close(FILE);
|
---|
346 | pb_log(1,"------------------\n");
|
---|
347 | } elsif (-d $f) {
|
---|
348 | my $dh;
|
---|
349 | if (! opendir($dh,$f)) {
|
---|
350 | pb_log(1,"INFO: Unable to opendir $f\n");
|
---|
351 | pb_log(1,"------------------\n");
|
---|
352 | next;
|
---|
353 | }
|
---|
354 | pb_log(1,"Content of directory $f\n");
|
---|
355 | pb_log(1,"----------------------------\n");
|
---|
356 | while (readdir $dh) {
|
---|
357 | my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,$blksize,$blocks) = stat("$f/$_");
|
---|
358 | my $str = sprintf("%10s %2s %5s %5s %10s %14s %s",$mode,$ino,$uid,$gid,$size,$mtime,$_);
|
---|
359 | pb_log(1,"$str\n");
|
---|
360 | }
|
---|
361 | closedir($dh);
|
---|
362 | pb_log(1,"------------------\n");
|
---|
363 | } else {
|
---|
364 | pb_log(1,"INFO: $f is special\n");
|
---|
365 | pb_log(1,"------------------\n");
|
---|
366 | }
|
---|
367 | }
|
---|
368 | }
|
---|
369 | }
|
---|
370 |
|
---|
371 | # Now the preparation is over, we need to do something useful :-)
|
---|
372 | # But it all depends on how we're asked to do it.
|
---|
373 | #
|
---|
374 | # First we need to copy into the target dir all the relevant content
|
---|
375 | pb_mkbm_create_content();
|
---|
376 |
|
---|
377 | # Then we need to package this content in the destination format
|
---|
378 | pb_mkbm_create_media();
|
---|
379 |
|
---|
380 | @date = pb_get_date();
|
---|
381 | $pbdate = strftime("%Y-%m-%d %H:%M:%S", @date);
|
---|
382 |
|
---|
383 | pb_log(1,"End: $pbdate\n");
|
---|
384 |
|
---|
385 | sub pb_mkbm_create_content {
|
---|
386 |
|
---|
387 | pb_log(1,"Creating boot media content\n");
|
---|
388 |
|
---|
389 | # If not defined use VE mode by default
|
---|
390 | $opts{'b'} = "ve" if (not defined $opts{'b'});
|
---|
391 |
|
---|
392 | # Hash of target content
|
---|
393 | # atribute could be, copy, remove, link, dir
|
---|
394 | my %targettree;
|
---|
395 |
|
---|
396 | if ($opts{'b'} eq "ve") {
|
---|
397 | # Use project-builder VE mecanism to create a good VE !
|
---|
398 | pb_ve_launch($ENV{'PBV'},1);
|
---|
399 | } elsif ($opts{'b'} eq "native") {
|
---|
400 | # Use native tools to create a good VE !
|
---|
401 | } elsif ($opts{'b'} eq "drakut") {
|
---|
402 | # Use drakut to create a good VE !
|
---|
403 | } elsif ($opts{'b'} eq "busybox") {
|
---|
404 | # Use busybox to create a good VE !
|
---|
405 | pb_mkbm_create_busybox_ve(\%targettree);
|
---|
406 | } else {
|
---|
407 | die "Unknown method $opts{'b'} used to create the media content";
|
---|
408 | }
|
---|
409 |
|
---|
410 | # Create the directory structure needed on the target dir
|
---|
411 | my ($tdirs,$bdirs,$bfiles,$bcmds) = pb_distro_get_param($pbos,pb_conf_get("mkbmtargetdirs","mkbmbootdirs","mkbmbootfiles","mkbmbootcmds"));
|
---|
412 | # Create empty dirs for these
|
---|
413 | foreach my $d (split(/,/,$tdirs)) {
|
---|
414 | $targettree{$d} = "emptydir";
|
---|
415 | }
|
---|
416 | # And copy dirs for those
|
---|
417 | foreach my $d (split(/,/,$bdirs)) {
|
---|
418 | if (-d $d) {
|
---|
419 | $targettree{$d} = "dir";
|
---|
420 | } elsif (-l $d) {
|
---|
421 | $targettree{$d} = "link";
|
---|
422 | } else {
|
---|
423 | pb_log(1,"INFO: Directory $d doesn't exist\n");
|
---|
424 | }
|
---|
425 | }
|
---|
426 | foreach my $f (split(/,/,$bfiles)) {
|
---|
427 | $targettree{$f} = "file";
|
---|
428 | }
|
---|
429 | pb_log(2,"INFO: Target Tree is now: ".Dumper(%targettree)."\n");
|
---|
430 | # Once the environment is made, add what is needed for this boot media to it.
|
---|
431 | # Keyboard
|
---|
432 | pb_mkbm_find_keyboard(\%targettree);
|
---|
433 | # Terminfo
|
---|
434 | # List of commands
|
---|
435 | # List of dependencies
|
---|
436 | # Kernel - We use 2 objects, the running kernel and the target kernel which could be different
|
---|
437 | my %rkernel;
|
---|
438 | my %tkernel;
|
---|
439 | pb_mkbm_find_kernel(\%rkernel);
|
---|
440 | # Initrd
|
---|
441 | # init
|
---|
442 | # BootLoader and its configuration
|
---|
443 | # Additional data files coming from a potential caller (MondoRescue/Mindi e.g. with fstab, LVM, mountlist, ...)
|
---|
444 | pb_log(1,"End of boot media creation\n");
|
---|
445 | }
|
---|
446 |
|
---|
447 | sub pb_mkbm_create_busybox_ve {
|
---|
448 |
|
---|
449 | my $tgtree = shift;
|
---|
450 |
|
---|
451 | pb_log(1,"Analyzing your busybox's configuration\n");
|
---|
452 | # First, check which are the supported command in that version of busybox
|
---|
453 | # and create the links for it in the target VE
|
---|
454 |
|
---|
455 | my $busycmd = pb_distro_get_param($pbos,pb_conf_get("ospathcmd-busybox"));
|
---|
456 | open(BUSY,"$busycmd |") || die "Unable to execute $busycmd";
|
---|
457 | my $cmdlist = 0;
|
---|
458 | while (<BUSY>) {
|
---|
459 | pb_log(3,"busybox line : $_");
|
---|
460 | chomp($_);
|
---|
461 | # After these words, we have the list of functions, so trigger their analysis
|
---|
462 | if ($_ =~ /defined functions:/) {
|
---|
463 | $cmdlist = 1;
|
---|
464 | next;
|
---|
465 | }
|
---|
466 | # Analyse the list of commands provided by that busybox (, separated)
|
---|
467 | if ($cmdlist == 1) {
|
---|
468 | pb_log(3,"Analyzing that busybox line\n");
|
---|
469 | foreach my $c (split(/,/,$_)) {
|
---|
470 | $c =~ s/\s*//g;
|
---|
471 | # skip empty strings
|
---|
472 | next if ($c =~ /^$/);
|
---|
473 | my $c1 = pb_check_req($c,0);
|
---|
474 | if (defined $c1) {
|
---|
475 | $tgtree->{$c1} = "link:$busycmd";
|
---|
476 | } else {
|
---|
477 | # When not found on the system, create the link under /usr/bin by default
|
---|
478 | $tgtree->{"/usr/bin/$c"} = "link:$busycmd";
|
---|
479 | }
|
---|
480 | }
|
---|
481 | }
|
---|
482 | }
|
---|
483 | pb_log(1,"Target Tree is now: ".Dumper($tgtree)."\n");
|
---|
484 | close(BUSY);
|
---|
485 | pb_log(1,"End of busybox analysis\n");
|
---|
486 | }
|
---|
487 |
|
---|
488 | sub pb_mkbm_find_keyboard {
|
---|
489 |
|
---|
490 | my $tgtree = shift;
|
---|
491 |
|
---|
492 | pb_log(1,"Analyzing your keyboard's configuration\n");
|
---|
493 | my $keyfile = pb_distro_get_param($pbos,pb_conf_get("ospathcmd-keyfile"));
|
---|
494 | die "Unable to read the keyfile $keyfile" if ((not defined $keyfile) || (! -r $keyfile));
|
---|
495 | my $keymapdir = pb_distro_get_param($pbos,pb_conf_get("ospathcmd-keymapdir"));
|
---|
496 | die "Unable to read the keymapdir $keymapdir" if ((not defined $keymapdir) || (! -d $keymapdir));
|
---|
497 | my $keymapre = pb_distro_get_param($pbos,pb_conf_get("ospathcmd-keymapre"));
|
---|
498 | die "Unable to read the keymapre $keymapre" if (not defined $keymapre);
|
---|
499 |
|
---|
500 | # if a direct keymap file is given as keyfile, use only the first existing one it and return
|
---|
501 | my $foundkmap = 0;
|
---|
502 | foreach my $f (split(/,/,$keyfile)) {
|
---|
503 | next if ($f !~ /\.gz$/);
|
---|
504 | $foundkmap = 1;
|
---|
505 | if (-l $f) {
|
---|
506 | $tgtree->{$f} = "link:$f";
|
---|
507 | pb_log(1,"Using Keymap file $f\n");
|
---|
508 | last;
|
---|
509 | } elsif (-r $f) {
|
---|
510 | $tgtree->{$f} = "file";
|
---|
511 | pb_log(1,"Using Keymap file $f\n");
|
---|
512 | last;
|
---|
513 | } else {
|
---|
514 | next;
|
---|
515 | }
|
---|
516 | }
|
---|
517 | return() if ($foundkmap eq 1);
|
---|
518 |
|
---|
519 | pb_log(1,"Using Keyfile $keyfile and Keymap directory $keymapdir\n");
|
---|
520 | my $locale="";
|
---|
521 | open(KEYMAP,"$keyfile") || die "Unable to read $keyfile";
|
---|
522 | # Depending on the format of the keymap we look for various strings
|
---|
523 | while (<KEYMAP>) {
|
---|
524 | $locale =~ $keymapre;
|
---|
525 | }
|
---|
526 | close(KEYMAP);
|
---|
527 | pb_log(1,"Found locale $locale\n");
|
---|
528 |
|
---|
529 | pb_log(1,"End of keyboard analysis\n");
|
---|
530 | }
|
---|
531 |
|
---|
532 | sub pb_mkbm_find_kernel {
|
---|
533 |
|
---|
534 | my $kernel = shift;
|
---|
535 |
|
---|
536 | pb_log(1,"Analyzing your kernel's configuration\n");
|
---|
537 | $kernel->{"is_xen"} = undef;
|
---|
538 | # See if we're booted from a Xen kernel
|
---|
539 | # From http://wiki.xensource.com/xenwiki/XenCommonProblems#head-26434581604cc8357d9762aaaf040e8d87b37752
|
---|
540 | if ( -f "/proc/xen/capabilities") {
|
---|
541 | # It's a Xen kernel
|
---|
542 | pb_log(2,"INFO: We found a Xen Kernel running\n");
|
---|
543 | $kernel->{"is_xen"} = 1;
|
---|
544 | }
|
---|
545 | $kernel->{"release"} = pb_get_osrelease();
|
---|
546 |
|
---|
547 | my $kfile = pb_distro_get_param($pbos,pb_conf_get_if("mkbmkernelfile"));
|
---|
548 | if ((defined $kfile) && ($kfile ne "")) {
|
---|
549 | pb_log(1,"INFO: You specified your kernel as $kfile, so using it\n");
|
---|
550 | $kernel->{"file"} = $kfile;
|
---|
551 | } else {
|
---|
552 | $kernel->{"dir"} = pb_distro_get_param($pbos,pb_conf_get("mkbmkerneldir"));
|
---|
553 | die "ERROR: The mkbmkerneldir content ($kernel->{'dir'}) doesn't refer to a directory\n" if (! -d $kernel->{"dir"});
|
---|
554 | pb_log(1,"INFO: Analyzing directory $kernel->{'dir'} to find your kernel\n");
|
---|
555 | $kernel->{"namere"} = pb_distro_get_param($pbos,pb_conf_get("mkbmkernelnamere"));
|
---|
556 |
|
---|
557 | # TODO: Look at a better way to find the name of the kernel we run
|
---|
558 | # look at /proc/sys/kernel/bootloader_type /proc/sys/kernel/bootloader_version
|
---|
559 | # to have a better guess
|
---|
560 | my $dh;
|
---|
561 | die "ERROR: Unable to open the mkbmkerneldir content ($kernel->{'dir'})\n" if (! opendir($dh,$kernel->{"dir"}));
|
---|
562 | while (readdir $dh) {
|
---|
563 | pb_log(3,"Potential kernel file: $_\n");
|
---|
564 | # Skip non-files
|
---|
565 | next if (! -f "$kernel->{'dir'}/$_");
|
---|
566 | # Skip files not correpsonding to the RE planned
|
---|
567 | next if ($_ !~ /$kernel->{"namere"}/);
|
---|
568 | # We now have a candidate. Analyze further
|
---|
569 | pb_log(3,"Potential kernel file 2: $_\n");
|
---|
570 | eval
|
---|
571 | {
|
---|
572 | require File::MimeInfo;
|
---|
573 | File::MimeInfo->import();
|
---|
574 | };
|
---|
575 | if ($@) {
|
---|
576 | # File::MimeInfo not found
|
---|
577 | die("ERROR: Install File::MimeInfo to handle kernel file detection\n");
|
---|
578 | }
|
---|
579 | my $mm = mimetype("$kernel->{'dir'}/$_");
|
---|
580 | # Skip symlinks
|
---|
581 | next if ($mm =~ /inode\/symlink/);
|
---|
582 | pb_log(2,"file $_ mimetype: $mm\n");
|
---|
583 | if ($mm =~ /\/x-gzip/) {
|
---|
584 | # on ia64 kernel are gzip compressed
|
---|
585 | }
|
---|
586 | next if (pb_get_content("$kernel->{'dir'}/$_") !~ /$kernel->{"release"}/);
|
---|
587 | pb_log(3,"Potential kernel file 3: $_\n");
|
---|
588 | $kernel->{"file"} = "$kernel->{'dir'}/$_";
|
---|
589 | #my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,$blksize,$blocks) = stat("$f/$_");
|
---|
590 | }
|
---|
591 | closedir($dh);
|
---|
592 | }
|
---|
593 | pb_log(1,"INFO: kernel is ".Dumper($kernel)."\n");
|
---|
594 | pb_log(1,"End of kernel analysis\n");
|
---|
595 | }
|
---|
596 |
|
---|
597 | sub pb_mkbm_create_media {
|
---|
598 |
|
---|
599 | }
|
---|
600 |
|
---|
601 | # Get the package list to download, store them in a cache directory
|
---|
602 | #
|
---|
603 | #my ($mkbmcachedir) = pb_conf_get_if("mkbmcachedir");
|
---|
604 | #my ($pkgs) = pb_distro_get_param($pbos,pb_conf_get("mkbmmindep"));
|
---|
605 |
|
---|
606 | #
|
---|
607 | # /proc needed
|
---|
608 | #
|
---|
609 | #pb_system("mount -o bind /proc $targetdir/proc","Mounting /proc");
|
---|
610 |
|
---|
611 | # Installed additional packages we were asked to
|
---|
612 | #if (defined $opts{'a'}) {
|
---|
613 | #$opts{'a'} =~ s/,/ /g;
|
---|
614 | #pb_system("chroot $targetdir /bin/bash -c \"$pbos->{'install'} $opts{'a'} \"","Adding packages to OS by running $pbos->{'install'} $opts{'a'}");
|
---|
615 | #}
|
---|
616 |
|
---|
617 | #
|
---|
618 | # Clean up
|
---|
619 | #
|
---|
620 | #pb_log(1,"Cleaning up\n");
|
---|
621 | #pb_system("umount $targetdir/proc","Unmounting /proc");
|
---|
622 |
|
---|
623 | # Executes post-install step if asked for
|
---|
624 | #if ($opts{'s'}) {
|
---|
625 | #pb_system("$opts{'s'} $targetdir","Executing the post-install script: $opts{'s'} $targetdir");
|
---|
626 | #}
|
---|