#!/usr/bin/perl -w use strict; use Getopt::Std; use POSIX qw(floor); sub mksysidcfg { my $locale="C"; my $term="vt100"; my $secpol="NONE"; my $domain; my $route; my $rootpw; my $iface; my $host=`uname -n`; my $nameservice; chomp $host; if (open(DOMAIN, "); close DOMAIN; } else { warn "Couldn't read /etc/defaultdomain ($!)\nTrying domainname.\n"; chomp($domain = `domainname`); } if (open(ROUTE, "); close ROUTE; } else { warn "Couldn't read /etc/defaultrouter ($!)\nTrying netstat -rn.\n"; open(ROUTE, "netstat -rn|"); while () { chomp; if (/^default ([0-9.]+)/) { $route = $1; last; } } close ROUTE; } if (open(SHADOW, ") { my @f = split(/:/); if ($f[0] eq 'root') { $rootpw=$f[1]; last; } } close SHADOW; } else { warn "Couldn't read /etc/shadow ($!)\n"; } if (open(RESOLV, ") { next if /^\s*$/; my @f = split(/\s+/); if ($f[0] eq 'nameserver') { push @{$d{ns}}, $f[1]; } elsif ($f[0] eq 'domain') { $d{domain} = $f[1]; } elsif ($f[0] eq 'search') { $d{search} = $f[1]; } } close RESOLV; $d{domain} ||= $domain; $nameservice = "DNS {"; $nameservice .= "domain_name=$d{domain} " if $d{domain}; $nameservice .= "name_server=".join(",",@{$d{ns}})." "; $nameservice .= "search=$d{search}" if $d{search}; $nameservice .= "}"; } else { warn "Couldn't read /etc/resolv.conf ($!)\n"; } if (open(IPCONF, "/usr/sbin/ifconfig -a|")) { my %d; my $cur_iface; while () { if (/^([\w\d]+):/) { # new interface last if defined $cur_iface; # we only grab the first one. next if $1 eq 'lo0'; # skip loopback; $cur_iface=$1; # store it; next; # don't want anything else on this line } next # Don't look if we don't have an interface unless defined $cur_iface; if (/inet (\S+) netmask (\S+)/) { $d{inet} = $1; $d{netmask} = $2; } } close IPCONF; for ($d{netmask}) { s/ff/255./g; } $iface = "PRIMARY {hostname="; $iface .= "$host "; $iface .= "ip_address=$d{inet} "; $iface .= "default_route=$route "; $iface .= "netmask=$d{netmask} "; $iface .= "protocol_ipv6=yes}"; } else { warn "Couldn't read ifconfig ($!)\n"; } my $timeserver="localhost"; return qq{system_locale=$locale timezone=$ENV{TZ} terminal=$term timeserver=$timeserver name_service=$nameservice root_password=$rootpw network_interface=$iface security_policy=$secpol }; } sub prep_partition { my $part = shift; my $cdrom = shift; my $mnt = shift; # prep the partition warn "Creating Filesystem on $part...\n"; system("/usr/sbin/newfs", "/dev/rdsk/$part") && die "Couldn't newfs partition: $!\n"; warn "Installing bootblock...\n"; system("/usr/sbin/installboot /usr/platform/`/usr/bin/uname -i`/lib/fs/ufs/bootblk /dev/rdsk/$part"); warn "Mounting...\n"; system("/usr/sbin/mount", "/dev/dsk/$part", $mnt) && die "Couldn't mount partition: $!\n"; unlink "$mnt/lost+found"; # copy the boot image to the new partition chdir($cdrom) || die "Couldn't cd to cdrom: $!\n"; warn "Copying bootable filesystem\n"; system("cd $cdrom; /usr/bin/find . .tmp_proto | cpio -pudm $mnt") && die "Couldn't copy cd image: $!\n"; # fix sysidcfg symlink unlink("$mnt/etc/sysidcfg"); symlink("../cdrom/sysidcfg", "$mnt/etc/sysidcfg"); system("touch", "$mnt/tmp/.preinstall"); } sub extract_vtoc { my $vtoc = shift; my $par; my $inf; my $sec_size; if($vtoc =~ m,(\d+) bytes/sector,s) { $sec_size = $1; } else { warn "Couldn't find sector size\n"; return ""; } for (split(/\n/,$vtoc)) { # We could us split here, but that wouldn't tell us if we # were looking at the right line if(m,^\s+(\d)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s*(\S*),) { # skip overlap next if $1 eq '2'; $inf = undef; $inf->{size} = floor($5 / (1048576/$sec_size)); $inf->{name} = $7 if $7 ne ''; # Partition is swap if it isn't mounted and is marked unmountable $inf->{name} = "swap" if $7 eq '' and $3 eq "01"; } if(ref $inf) { push @{$par},$inf; } } return $par; } sub set_largest_par { my $largest = 0; my $par = shift; my $max = $#{$par}; foreach(0..$max) { $largest = $_ if $par->[$largest]->{size} < $par->[$_]->{size}; } $par->[$largest]->{size} = "free"; } sub filesystems { my $disk = shift; my $vtoc = `/usr/sbin/prtvtoc $disk`; my @par; extract_vtoc($vtoc, \@par); return \@par; } sub install_jumpstart { my $mnt = shift; my $par = shift; my $journal = shift; # Create /cdrom dir in mounted partition mkdir("$mnt/cdrom",0755); # Copy jumpstart into place mkdir("$mnt/cdrom/.install_config",0755); if(open(RULE, ">$mnt/cdrom/.install_config/rules.ok")){ print RULE qq{any - - default postinst\n}; print RULE qq{# version=2 checksum=2197\n}; close RULE; } else { warn "Couldn't open rules.ok for writing ($!)\n"; } my @par = @{$par}; if(open(PROF, ">$mnt/cdrom/.install_config/default")){ print PROF qq{install_type flash_install\n}; print PROF qq{archive_location local_file /cdrom/default.flar\n}; print PROF qq{partitioning explicit\n}; print PROF join("\n", map{ my $a = defined $journal ? "\nfilesys ${journal}s$_ $par[$_]{size}" : ""; "filesys rootdisk.s$_ $par[$_]{size} $par[$_]{name}$a"} grep{defined $_ && $par[$_]->{size}} 0..$#par), "\n"; if(defined $journal) { print PROF qq{filesys rootdisk.s7 1\n}; print PROF qq{filesys ${journal}s7 1\n}; } close PROF; } else { warn "Couldn't open profile default for writing ($!)\n"; } if(open(POST, ">$mnt/cdrom/.install_config/postinst")){ print POST q{#!/bin/sh echo Post install here... for adm in exacct log passwd streams aculog spellhist utmpx wtmpx messages lastlog sulog do touch /a/var/adm/$adm done for log in authlog syslog do touch /a/var/log/$log done }; if(defined $journal) { if(open(DISK, ">$mnt/cdrom/.install_config/disksuite")){ while(<::DATA>) { s/%DISK1%/c1t0d0/g; s/%DISK2%/$journal/g; print DISK; } } else { warn "Failed creating disksuite setup script\n"; } } print POST q{ echo Installing disksuite setup cp /cdrom/.install_config/disksuite /a/etc/rc2.d/S78disksuite chmod +x /a/etc/rc2.d/S78disksuite touch /a/config.ods.1 }; close(POST); } else { warn "Couldn't open postinst for writing ($!)\n"; } if(open(SYSID, ">$mnt/cdrom/sysidcfg")) { print SYSID mksysidcfg(); close SYSID; } else { warn "Couldn't open sysidcfg for writing ($!)\n"; } } sub find_root_device { my $df = `/usr/bin/df -k /`; for($df) { return $1 if m,(/dev/\S+),s } } sub install_flar { my $mnt = shift; my $par = shift; my $find = q{/usr/bin/find %s \! -type D \! -type s -print \! -mount -prune | /usr/bin/fgrep -v -f /etc/flar_exclude >> %s/cdrom/filelist.txt}; # Get rid of any previous filelist unlink "$mnt/cdrom/filelist.txt"; # Make sure we have all the mountpoints system(qq{/sbin/mount | awk '{print \$1}' > $mnt/cdrom/filelist.txt}); # Create list of files foreach(0..$#{$par}) { next if $par->[$_]->{name} eq 'swap'; warn "Creating list of files for backup from ", $par->[$_]->{name},"...\n"; system(sprintf($find, $par->[$_]->{name}, $mnt)); } # Run flar system("flarcreate -n Archive -c -f $mnt/cdrom/filelist.txt -F $mnt/cdrom/default.flar"); } sub get_mounts { my @fs = @_; my $par; for(@fs) { my $df = [map{m,^(/dev\S+), && $1} qx{df -k $_}]->[1]; my $vtoc = qx{/usr/sbin/prtvtoc $df}; my $p = extract_vtoc($vtoc); if(exists $p->[0]->{name}) { $par = $p; last; } else { $p->[0]->{name} = $_; push @{$par}, $p->[0]; } } return $par; } sub main { my $usage = "$0 -p part [-b] [-d disk] [-c cdrom] [-m mountpoint]\n"; my %opt; getopts("f:d:p:c:m:bj:", \%opt); my $bootable = $opt{"b"} || 0; my $part = $opt{p}; my $disk = $opt{d}; my $cdrom = $opt{c} || "/cdrom"; my $mnt = $opt{"m"} || "/mnt"; my $fs = $opt{"f"}; my $journal = $opt{"j"}; my $par; if($< != 0) { die "You must be root.\n"; } if($bootable && !defined $mnt) { die $usage; } unless(defined $fs) { $disk ||= find_root_device(); $par = filesystems($disk); } else { $par = get_mounts(split (",", $fs)); } prep_partition($part, $cdrom, $mnt) unless $bootable; set_largest_par($par); install_jumpstart($mnt, $par, $journal); install_flar($mnt, $par); # make_iso($part); } main; __DATA__ #!/sbin/sh if test -f /config.ods.1 then /usr/sbin/metadb -a -f -c 2 %DISK1%s7 %DISK2%s7 echo "Preparing the / partition" /usr/sbin/metainit -f d10 1 1 %DISK1%s0 /usr/sbin/metainit d20 1 1 %DISK2%s0 /usr/sbin/metainit d0 -m d10 /usr/sbin/metaroot d0 echo "Preparing the swap partition" /usr/sbin/metainit -f d11 1 1 %DISK1%s1 /usr/sbin/metainit d21 1 1 %DISK2%s1 /usr/sbin/metainit d1 -m d11 echo "Preparing the /home partition" /usr/sbin/metainit -f d12 1 1 %DISK1%s3 /usr/sbin/metainit d22 1 1 %DISK2%s3 /usr/sbin/metainit d2 -m d12 echo "Preparing the /var partition" /usr/sbin/metainit -f d13 1 1 %DISK1%s4 /usr/sbin/metainit d23 1 1 %DISK2%s4 /usr/sbin/metainit d3 -m d13 echo "Preparing /etc/vfstab. Backup in /etc/vfstab.orig" cp /etc/vfstab /etc/vfstab.orig echo "#device device mount FS fsck mount mount #to mount to fsck point type pass at boot options # fd - /dev/fd fd - no - /proc - /proc proc - no - /dev/md/dsk/d1 - - swap - no - /dev/md/dsk/d0 /dev/md/rdsk/d0 / ufs 1 no logging /dev/md/dsk/d2 /dev/md/rdsk/d2 /home ufs 2 yes logging /dev/md/dsk/d3 /dev/md/rdsk/d3 /var ufs 1 no logging,nosuid swap - /tmp tmpfs - yes nosuid " > /etc/vfstab.meta lockfs -fa if [ -r /dev/md/dsk/d0 ]; then cp /etc/vfstab.meta /etc/vfstab fi touch /config.ods.2 rm /config.ods.1 reboot fi if test -f /config.ods.2 then echo"" echo "Meta Attaching ODS devices..." echo"" /usr/sbin/metattach d0 d20 /usr/sbin/metattach d1 d21 /usr/sbin/metattach d2 d22 /usr/sbin/metattach d3 d23 rm /config.ods.2 fi