Use this script. You can add the e100 module to the boot floppy. I used it to create a custom boot floppy for pcmica network cards, since the laptops that I needed to install on had pcmcia floppy drives that disappeared upon boot. Ron On Wed, 2003-05-21 at 15:18, Anderson, Bill wrote: > I might be outta luck on this one, but here goes anyway... > > I've put the following into my ks.cfg just before the network line: > > device ethernet e100 --opts "e100_speed_duplex=4" > > However, when this file is read, the driver e100 can't be loaded because > it > is on the driver-floppy I'm going to insert in a matter of seconds. > When > the e100 driver is read off that floppy, the attempt to force to > full-duplex > is nullified. > > I realize that floppy-based kickstart is going the way of the dinosaur > and > eight-track tapes, but unfortunately for me, moving to CD-ROM based > kickstart isn't an option right now. I also realize that if I could set > the > switch I'm plugged into to auto-negotiate, then all would be fine and > dandy. > However, I have no control over the settings of the switches. > > I read a few threads ago about how to access a network based ks.cfg > w/out > DHCP, but I haven't had time to investigate that one yet. I also read a > while ago about suggestions for hacking the RH9 kickstart down to one > floppy; that doesn't work for me either. As for my original question, > I'm > just wondering if there's any hope for what I'm trying to do today. > Thanks > to all... > > Bill > > Bill Anderson > TDS Telecom ISS > > > _______________________________________________ > Kickstart-list mailing list > Kickstart-list@xxxxxxxxxx > https://www.redhat.com/mailman/listinfo/kickstart-list -- =========================== Ron Reed Unix Systems Administrator ARM SGP CART Site (580)388-4053 ron.reed@xxxxxxx
#!/usr/bin/perl -w # # Copyright (c) 2003 # Chris Adams <cmadams@xxxxxxxxxxxxxxxx> # ######################################################################## # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. ######################################################################## # # Add and/or delete modules from the base Red Hat Linux bootdisk (using the # drvnet and drvblock driver disks). This will also modify the PCI table so # that an alternate module is used (like replacing sym53c8xx with # sym53c8xx_2), and can optionally replace the kernel and modules with new # versions from a kernel-BOOT-*.rpm. # # Command line options: # -q - quiet mode # -a <module>[,<module>...] - module(s) to add # -d <module>[,<module>...] - module(s) to remove # -i <directory> - original disk image directory # -k <kernel-BOOT.rpm> - new kernel boot RPM to replace kernel/modules # -o <file> - output image file name # -r <omod=nmod>[,<omod2=nmod2>...] - replace omod with nmod in pcitable # -u <glob>[,<glob>...] - unlink files matching glob on bootdisk # # Requires: # coreutils # cpio # e2fsprogs # losetup # mount # perl # perl-Compress-Zlib # rpm # # History: # 1.0 - 2003-04-26 # initial version # # 1.1 - 2003-04-28 # when replacing kernel, rename module directory too # # 1.2 - 2003-05-01 # add error handling clean-ups # allow adding additional modules (like RAID) from supplied kernel RPM # add option to unlink files from bootdisk to make more space for initrd # make sure new initrd fits onto floppy # use Getopt::Std; use File::Temp qw(tempdir); use File::Copy; use File::Path; use Compress::Zlib; use POSIX qw(mkfifo); use Fcntl qw(:mode); use strict; # Get and check options die "Must be run as root\n" if ($> != 0); my $SIZE = 3000; use vars qw($opt_i $opt_a $opt_d $opt_o $opt_r $opt_k $opt_q $opt_u); $opt_i = "."; $opt_a = $opt_d = $opt_r = $opt_k = $opt_q = $opt_u = ""; $opt_o = "custom.img"; getopts ("i:a:d:o:r:k:qu:"); my @add = split (/,/, $opt_a); my @del = split (/,/, $opt_d); die "Nothing to add or delete\n" if (! @add && ! @del); die "Output image already exists\n" if (-e $opt_o); die "Can't find kernel update RPM\n" if ($opt_k && ! -e $opt_k); die "Can't find RHL images directory\n" if (! -e $opt_i); my $base = $opt_i . "/bootdisk.img"; my %drv = (); $drv{"net"} = $opt_i . "/drvnet.img"; $drv{"block"} = $opt_i . "/drvblock.img"; $drv{"pcmcia"} = $opt_i . "/pcmciadd.img"; die "Can't find RHL images\n" if (! (-e $base && -e $drv{"net"} && -e $drv{"block"} && -e $drv{"pcmcia"})); my %replace = (); foreach my $pair (split (/,/, $opt_r)) { my ($old, $new) = split (/=/, $pair); die "Invalid replace pair \"$pair\"\n" if (! $old || ! $new); $replace{$new} = $old; } # Variables to keep track of things to clean-up use vars qw(@mounts $tdir); @mounts = (); $tdir = ""; $SIG{"__DIE__"} = sub { warn @_; debug ("Cleaning up\n"); foreach my $mount (reverse @mounts) { debug ("Unmounting ", $mount, "\n"); umount ($mount); } debug ("Removing ", $tdir, "\n"); rmtree ($tdir) if ($tdir); debug ("Removing ", $opt_o, "\n"); unlink ($opt_o); exit 1; }; # Make a workspace and mount the bootdisk debug ("Mounting bootdisk\n"); copy ($base, $opt_o) or die "copy($base,$opt_o): $!\n"; $tdir = tempdir ("modXXXXXXXX"); my $bootmnt = $tdir . "/bootdisk"; mkdir ($bootmnt) or die "mkdir($bootmnt): $!\n"; mount ("-orw,loop", $opt_o, $bootmnt); # Remove the specified files if ($opt_u) { unlink (map { glob ($bootmnt . "/" . $_) } (split (/,/, $opt_u))); } # Uncompress the initrd image and make a copy of the tree my $initrd = $tdir . "/initrd.img"; system("cp $bootmnt/initrd.img $initrd.gz"); system("gunzip $initrd.gz"); #open (INITRD, "> $initrd") or die "open(>$initrd): $!\n"; #my $gz = gzopen ($bootmnt . "/initrd.img", "r") # or die "gzopen($bootmnt/initrd.img): $gzerrno\n"; #my $buf; #while ($gz->gzread ($buf)) { # print INITRD $buf; #} #close (INITRD); #$gz->gzclose; debug ("Mounting original initrd\n"); my $initmnt = $tdir . "/initrd"; mkdir ($initmnt) or die "mkdir($initmnt): $!\n"; mount ("-oro,loop", $initrd, $initmnt); debug ("Copying initrd\n"); my $newinit = $tdir . "/newinit"; mkdir ($newinit) or die "mkdir($newinit): $!\n"; copydir ($initmnt, $newinit); umount ($initmnt); rmdir ($initmnt); unlink ($initrd); debug ("Extracting initrd modules\n"); my $initmod = $tdir . "/mod-init"; mkdir ($initmod) or die "mkdir($initmod): $!\n"; cgzextract ($newinit . "/modules/modules.cgz", $initmod); # Mount the net and block driver images and extract the modules foreach my $d (qw(net block pcmcia)) { debug ("Mounting ", $d, " disk\n"); my $img = $drv{$d}; my $imgmnt = $tdir . "/drv" . $d; mkdir ($imgmnt) or die "mkdir($imgmnt): $!\n"; mount ("-oro,loop", $img, $imgmnt); debug ("Extracting ", $d, " modules\n"); my $imgmod = $tdir . "/mod-" . $d; mkdir ($imgmod) or die "mkdir($imgmod): $!\n"; cgzextract ($imgmnt . "/modules.cgz", $imgmod); } # Find the kernel version and inventory all the modules and dependencies opendir (IMOD, $initmod) or die "opendir($initmod): $!\n"; my $kver = ""; while (defined (my $e = readdir (IMOD))) { next if ($e =~ /^\.{1,2}$/); if ($e =~ /^\d+\.\d+\.\d+-\d+BOOT$/) { $kver = $e; last; } } closedir (IMOD); die "Can't figure kernel version\n" if (! $kver); debug ("Taking module inventory\n"); my %mods = (); foreach my $d (qw(init net block pcmcia)) { my $dir = $tdir . "/mod-" . $d . "/" . $kver; opendir (MOD, $dir) or die "opendir($dir) $!\n"; while (defined (my $e = readdir (MOD))) { my ($mod) = $e =~ /(.+)\.o$/; next if (! $mod); $mods{$mod} = $dir . "/" . $e; } closedir (MOD); } my %deps = my %info = my %pci = my %special = (); foreach my $d (qw(newinit/modules drvnet drvblock drvpcmcia)) { debug ("Reading module info in ", $d, "\n"); my $dir = $tdir . "/" . $d; open (DEP, "$dir/modules.dep") or die "open($dir/modules.dep): $!\n"; while (<DEP>) { chomp; my ($mod, $dep) = $_ =~ /^(\S+): (.+)$/; $deps{$mod} = $dep; } close (DEP); my $info = ""; foreach my $file (qw(modinfo module-info)) { my $f = $dir . "/" . $file; if (-f $f) { $info = $f; last; } } die "Can't find module info in $d\n" if (! $info); open (INFO, $info) or die "open($info): $!\n"; my $ver = <INFO>; chomp $ver; die "Unknown info version $ver\n" if ($ver ne "Version 0"); my $mod = ""; while (<INFO>) { if (/^\S/) { $mod = $_; chomp $mod; $info{$mod} = $_; } else { $info{$mod} .= $_; } } close (INFO); open (PCI, "$dir/pcitable") or die "open($dir/pcitable): $!\n"; while (<PCI>) { chomp; my ($id, $mod, $desc) = $_ =~ /^(.+\s+")([^"]+)("\s+".+")$/; $pci{$mod}{$id} = $desc; if ($d eq "newinit/modules") { $special{$mod} = 1; } } close (PCI); } foreach my $d (qw(net block pcmcia)) { debug ("Unmounting ", $d, "\n"); my $dir = $tdir . "/drv" . $d; umount ($dir); rmdir ($dir); } # Now actually add and remove modules and regenerate info files my $mdir = $tdir . "/mod-init/" . $kver; foreach my $mod (@del) { debug ("Removing ", $mod, "\n"); my $f = $mdir . "/" . $mod . ".o"; if (-e $f) { unlink ($f) or die "unlink($f): $!\n"; } else { warn "Can't remove $mod (doesn't exist) - skipping\n"; } } my %add = map { $_ => 1 } @add; foreach my $mod (@add) { next if (! $deps{$mod}); my @dep = split (/\s+/, $deps{$mod}); foreach my $dep (@dep) { my $f = $mdir . "/" . $dep . ".o"; next if (-e $f); $add{$dep} = 1; debug ("Adding dependency on ", $dep, "\n"); } } @add = sort keys %add; my @toadd = (); foreach my $mod (@add) { debug ("Adding ", $mod, "\n"); my $f = $mdir . "/" . $mod . ".o"; if (! $mods{$mod}) { if ($opt_k) { # Module may be found in new kernel RPM warn "Skipping $mod - will look in kernel RPM\n"; push @toadd, $mod; next; } die "Unknown module $mod\n"; } if (-e $f) { warn "Skipping adding $mod - already exists\n"; } else { my ($atime, $mtime) = (stat ($mods{$mod}))[8,9]; copy ($mods{$mod}, $f) or die "copy($mods{$mod},$f): $!\n"; utime ($atime, $mtime, $f); } } my @mods = (); opendir (MDIR, $mdir) or die "opendir($mdir): $!\n"; while (defined (my $e = readdir (MDIR))) { next if ($e =~ /^\.{1,2}$/); my ($mod) = $e =~ /^(.+)\.o$/; push @mods, $mod; } closedir (MDIR); debug ("Creating new modules.dep\n"); open (DEP, ">$newinit/modules/modules.dep") or die "open(>$newinit/modules/modules.dep): $!\n"; foreach my $mod (sort @mods) { if (defined ($deps{$mod})) { print DEP $mod, ": ", $deps{$mod}, "\n"; } } close (DEP); debug ("Creating new module-info\n"); open (INFO, ">$newinit/modules/module-info") or die "open(>$newinit/modules/module-info): $!\n"; print INFO "Version 0\n"; foreach my $mod (sort @mods) { if (defined ($info{$mod})) { print INFO $info{$mod}; } } close (INFO); debug ("Creating new pcitable\n"); open (PCI, ">$newinit/modules/pcitable") or die "open(>$newinit/modules/pcitable): $!\n"; foreach my $mod (sort (keys %special, @mods)) { my $m = $mod; $m = $replace{$mod} if ($replace{$mod}); foreach my $id (sort keys %{$pci{$m}}) { print PCI $id, $mod, $pci{$m}{$id}, "\n"; } } close (PCI); debug ("Removing original module trees\n"); rmtree ($tdir . "/mod-net") or die "rmtree($tdir/mod-net): $!\n"; rmtree ($tdir . "/mod-block") or die "rmtree($tdir/mod-block): $!\n"; rmtree ($tdir . "/mod-pcmcia") or die "rmtree($tdir/mod-pcmcia): $!\n"; # If there is a new kernel to use, replace the files now if ($opt_k) { debug ("Extracting new kernel RPM\n"); my $kdir = $tdir . "/kern"; mkdir ($kdir) or die "mkdir($kdir): $!\n"; die "fork(rpm): $!\n" unless defined (my $pid = open (RPM, "-|")); if (! $pid) { open (STDIN, "</dev/null"); open (STDERR, ">/dev/null"); exec "/usr/bin/rpm2cpio", $opt_k or die "exec(rpm): $!\n"; } die "fork(cpio): $!\n" unless defined ($pid = open (CPIO, "-|")); if (! $pid) { chdir ($kdir); open (STDIN, "<&RPM") or die "dup(RPM): $!\n"; open (STDERR, ">&STDOUT") or die "dup(STDOUT): $!\n"; exec "/bin/cpio", "-dumi" or die "exec(cpio): $!\n"; } close (RPM); my $res = join ("", <CPIO>); close (CPIO); die "rpm2cpio failed: \"$res\"\n" if (($? >>8) != 0); debug ("Taking inventory of new kernel modules\n"); my $nkmod = $kdir . "/lib/modules"; opendir (NK, $nkmod) or die "opendir($nkmod): $!\n"; my $nkver = ""; while (defined (my $e = readdir (NK))) { next if ($e =~ /^\.{1,2}$/); if ($e =~ /^\d+\.\d+\.\d+-[a-zA-Z0-9\.]+$/) { $nkver = $e; last; } } closedir (NK); die "Can't figure new kernel version\n" if (! $nkver); $nkmod .= "/" . $nkver . "/kernel"; # Find all the module files in the new kernel tree and replace them in # the modules tree use File::Find; my %nmod= (); find ({"wanted" => sub { $nmod{$1} = $_ if (/([^\/]+)\.o$/) }, "no_chdir" => 1}, $nkmod); debug ("Replacing modules\n"); foreach my $mod (@mods) { die "Can't find new module \"$mod\"\n" if (! $nmod{$mod}); my $mfile = $mdir . "/" . $mod . ".o"; copy ($nmod{$mod}, $mfile) or die "copy($nmod{$mod},$mfile): $!\n"; } if (@toadd) { debug ("Adding modules from kernel RPM\n"); foreach my $mod (@toadd) { die "Unknown module $mod\n" if (! $nmod{$mod}); my $mfile = $mdir . "/" . $mod . ".o"; copy ($nmod{$mod}, $mfile) or die "copy($nmod{$mod},$mfile): $!\n"; push @mods, $mod; } } debug ("Replacing kernel\n"); my $nkern = $kdir . "/boot/vmlinuz-" . $nkver; my $okern = $bootmnt . "/vmlinuz"; copy ($nkern, $okern) or die "copy($nkern,$okern): $!\n"; debug ("Removing new kernel RPM tree\n"); rmtree ($kdir) or die "rmtree($kdir): $!\n"; my $nmdir = $tdir . "/mod-init/" . $nkver; rename ($mdir, $nmdir) or die "rename($mdir,$nmdir): $!\n"; $kver = $nkver; $mdir = $nmdir; } # Make the new modules.cgz debug ("Building modules.cgz\n"); my $cgz = gzopen ($newinit . "/modules/modules.cgz", "w9") or die "gzopen($newinit/modules/modules.cgz): $gzerrno\n"; pipe (FILELIST, TOCPIO) or die "pipe: $!\n"; die "fork(cpio): $!\n" unless defined (my $pid = open (SUB, "-|")); if (! $pid) { chdir ($tdir . "/mod-init"); open (STDIN, "<&FILELIST") or die "dup(FILELIST): $!\n"; close (FILELIST); close (TOCPIO); open (STDERR, ">/dev/null"); exec "/bin/cpio", "-oa", "-Hcrc" or die "exec(cpio): $!\n"; } close (FILELIST); print TOCPIO map { $kver . "/" . $_ . ".o\n" } @mods; close (TOCPIO); my $cbuf; while (sysread (SUB, $cbuf, 4096)) { $cgz->gzwrite ($cbuf); } close (SUB); die "cpio failed\n" if (($? >> 8) != 0); $cgz->gzclose; debug ("Removing new module tree\n"); rmtree ($tdir . "/mod-init") or die "rmtree($tdir/mod-init): $!\n"; # Make the new initrd debug ("Creating new initrd\n"); my $lodev = `echo findlodev | /sbin/nash --quiet`; chomp $lodev; die "Can't find available loopback device\n" if (! $lodev); my $lofile = $tdir . "/newinit.img"; open (LO, ">$lofile") or die "open(>$lofile): $!\n"; print LO "\0" x ($SIZE * 1024); close (LO); die "fork(losetup): $!\n" unless defined ($pid = open (SUB, "-|")); if (! $pid) { open (STDERR, ">&STDOUT") or die "dup: $!\n"; exec "/sbin/losetup", $lodev, $lofile or die "exec(losetup): $!\n"; } my $res = join ("", <SUB>); close (SUB); die "losetup failed: \"$res\"\n" if (($? >> 8) != 0); pipe (YES, TOMKFS) or die "pipe: $!\n"; die "fork(mke2fs): $!\n" unless defined ($pid = open (SUB, "-|")); if (! $pid) { open (STDIN, "<&YES") or die "dup(FILELIST): $!\n"; close (YES); close (TOMKFS); open (STDERR, ">&STDOUT") or die "dup: $!\n"; exec "/sbin/mke2fs", $lodev, $SIZE or die "exec(mke2fs): $!\n"; } close (YES); print TOMKFS "y\n"; close (TOMKFS); $res = join ("", <SUB>); close (SUB); die "mke2fs failed: \"$res\"\n" if (($? >> 8) != 0); die "fork(tune2fs): $!\n" unless defined ($pid = open (SUB, "-|")); if (! $pid) { open (STDERR, ">&STDOUT") or die "dup: $!\n"; exec "/sbin/tune2fs", "-i0", "-c0", $lodev or die "exec(tune2fs): $!\n"; } $res = join ("", <SUB>); close (SUB); die "tune2fs failed: \"$res\"\n" if (($? >> 8) != 0); my $lomnt = $tdir . "/newinit-mnt"; mkdir ($lomnt) or die "mkdir($lomnt): $!\n"; mount ("-text2", "-orw", $lodev, $lomnt); rmdir ($newinit . "/lost+found"); copydir ($newinit, $lomnt); rmtree ($newinit) or die "rmtree($newinit): $!\n"; umount ($lomnt); rmdir ($lomnt); die "fork(losetup): $!\n" unless defined ($pid = open (SUB, "-|")); if (! $pid) { open (STDERR, ">&STDOUT") or die "dup: $!\n"; exec "/sbin/losetup", "-d", $lodev or die "exec(losetup): $!\n"; } $res = join ("", <SUB>); close (SUB); die "losetup failed: \"$res\"\n" if (($? >> 8) != 0); debug ("Compressing new initrd\n"); my $newimg = $tdir . "/initrd.img"; my $igz = gzopen ($newimg, "w9") or die "gzopen($newimg): $gzerrno\n"; open (LO, "$lofile") or die "open($lofile): $!\n"; my $ibuf; while (sysread (LO, $ibuf, 4096)) { $igz->gzwrite ($ibuf); } close (LO); $igz->gzclose; unlink ($lofile); debug ("new initrd size: ", (stat ($newimg))[7], "\n"); copy ($newimg, $bootmnt . "/initrd.img") or die "copy($newimg,$bootmnt/initrd.img): $!\n"; unlink ($newimg); debug ("Cleaning up\n"); umount ($bootmnt); rmdir ($bootmnt); rmdir ($tdir); # Print debug messages sub debug { print STDERR @_ if (! $opt_q); } # Call out to mount, die on failure sub mount { use vars qw($mount_bin); if (! $mount_bin) { # Find it foreach my $d (qw(/usr/sbin /sbin /usr/bin /bin)) { if (-e $d . "/mount") { $mount_bin = $d . "/mount"; last; } } die "Can't find mount\n" if (! $mount_bin); } local (*SUB); die "fork(mount): $!\n" unless defined (my $pid = open (SUB, "-|")); if (! $pid) { open (STDERR, ">&STDOUT") or die "dup: $!\n"; exec $mount_bin, @_ or die "exec(mount): $!\n"; } my $out = join ("", <SUB>); close (SUB); die "mount failed: \"$out\"\n" if (($? >> 8) != 0); push @mounts, $_[$#_]; } # Call out to umount, die on failure sub umount { use vars qw($umount_bin); if (! $umount_bin) { # Find it foreach my $d (qw(/usr/sbin /sbin /usr/bin /bin)) { if (-e $d . "/umount") { $umount_bin = $d . "/umount"; last; } } die "Can't find umount\n" if (! $umount_bin); } # Need to take this dir out of list first in case we die my $dir = $_[$#_]; @mounts = grep { $_ ne $dir } @mounts; local (*SUB); die "fork(umount): $!\n" unless defined (my $pid = open (SUB, "-|")); if (! $pid) { open (STDERR, ">&STDOUT") or die "dup: $!\n"; exec $umount_bin, @_ or die "exec(umount): $!\n"; } my $out = join ("", <SUB>); close (SUB); die "umount failed: \"$out\"\n" if (($? >> 8) != 0); } # Copy a directory tree from one place to another sub copydir { my $src = shift; my $dst = shift; my %inodes; local (*SRC); opendir (SRC, $src) or die "opendir($src): $!\n"; while (defined (my $e = readdir (SRC))) { next if ($e =~ /^\.{1,2}$/); my $s = $src . "/" . $e; my $d = $dst . "/" . $e; my ($dev, $ino, $mode, $uid, $gid, $rdev, $atime, $mtime) = (lstat $s)[0,1,2,4,5,6,8,9]; if (defined ($inodes{$dev}{$ino})) { link ($inodes{$dev}{$ino}, $d) or die "link($d): $!\n"; } elsif (S_ISREG ($mode)) { copy ($s, $d) or die "copy($s,$d): $!\n"; chmod ($mode, $d) or die "chmod($d): $!\n"; chown ($uid, $gid, $d) or die "chown($d): $!\n"; utime ($atime, $mtime, $d) or die "utime($d): $!\n"; } elsif (S_ISDIR ($mode)) { mkdir ($d, $mode) or die "mkdir($d): $!\n"; chown ($uid, $gid, $d) or die "chown($d): $!\n"; copydir ($s, $d); utime ($atime, $mtime, $d) or die "utime($d): $!\n"; } elsif (S_ISFIFO ($mode)) { mkfifo ($d); chmod ($mode, $d) or die "chmod($d): $!\n"; chown ($uid, $gid, $d) or die "chown($d): $!\n"; utime ($atime, $mtime, $d) or die "utime($d): $!\n"; } elsif (S_ISLNK ($mode)) { my $lnk = readlink ($s); symlink ($lnk, $d) or die "symlink($d): $!\n"; lchown ($uid, $gid, $d); } elsif (S_ISBLK ($mode)) { mknod ($d, "b", $rdev >> 8, $rdev & 0xff); chmod ($mode, $d) or die "chmod($d): $!\n"; chown ($uid, $gid, $d) or die "chown($d): $!\n"; utime ($atime, $mtime, $d) or die "utime($d): $!\n"; } elsif (S_ISCHR ($mode)) { mknod ($d, "c", $rdev >> 8, $rdev & 0xff); chmod ($mode, $d) or die "chmod($d): $!\n"; chown ($uid, $gid, $d) or die "chown($d): $!\n"; utime ($atime, $mtime, $d) or die "utime($d): $!\n"; } else { die "copydir: can't handle type for $s\n"; } } closedir (SRC); } # Make a device node sub mknod { use vars qw($mknod_bin); if (! $mknod_bin) { # Find it foreach my $d (qw(/usr/sbin /sbin /usr/bin /bin)) { if (-e $d . "/mknod") { $mknod_bin = $d . "/mknod"; last; } } die "Can't find mknod\n" if (! $mknod_bin); } local (*SUB); die "fork(mknod): $!\n" unless defined (my $pid = open (SUB, "-|")); if (! $pid) { open (STDERR, ">&STDOUT") or die "dup: $!\n"; exec $mknod_bin, @_ or die "exec(mknod): $!\n"; } my $out = join ("", <SUB>); close (SUB); die "mknod failed: \"$out\"\n" if (($? >> 8) != 0); } # Change ownership on a symlink sub lchown { my $uid = shift; my $gid = shift; local (*SUB); die "fork(chown): $!\n" unless defined (my $pid = open (SUB, "-|")); if (! $pid) { open (STDERR, ">&STDOUT") or die "dup: $!\n"; exec "/bin/chown", "-h", $uid . ":" . $gid, @_ or die "exec(chown): $!\n"; } my $out = join ("", <SUB>); close (SUB); die "chown failed: \"$out\"\n" if (($? >> 8) != 0); } # Extract a cgz file to a given directory sub cgzextract { my $cgz = shift; my $dir = shift; my $gz = gzopen ($cgz, "r") or die "gzopen($cgz): $gzerrno\n"; local (*SUB); die "fork(cpio): $!\n" unless defined (my $pid = open (SUB, "|-")); if (! $pid) { chdir ($dir); open (STDOUT, ">/dev/null"); open (STDERR, ">/dev/null"); exec "/bin/cpio", "-dumi" or die "exec(cpio): $!\n"; } my $buf; while ($gz->gzread ($buf)) { print SUB $buf; } $gz->gzclose; close (SUB); die "cpio failed\n" if (($? >> 8) != 0); }