mirror of
https://github.com/libguestfs/libguestfs.git
synced 2026-03-21 22:53:37 +00:00
appliance: Change to using febootstrap 3.x supermin appliance.
This removes all support for building the ordinary / old style appliance using febootstrap 2.x, debootstrap, debirf, fakeroot and fakechroot. Instead this uses febootstrap 3.x to build the supermin appliance in a simpler cross-distro manner.
This commit is contained in:
13
.gitignore
vendored
13
.gitignore
vendored
@@ -2,21 +2,10 @@
|
||||
*.a
|
||||
ABOUT-NLS
|
||||
aclocal.m4
|
||||
appliance/debian/.bootstrap.log
|
||||
appliance/debian/.fakeroot-state.debirf-libguestfs
|
||||
appliance/debian/debirf-libguestfs*.cgz
|
||||
appliance/debian/root/
|
||||
appliance/debian/vmlinuz-*
|
||||
appliance/debian/debirf.conf
|
||||
appliance/initramfs.*.img
|
||||
appliance/kmod.whitelist
|
||||
appliance/make.sh
|
||||
appliance/packagelist
|
||||
appliance/stamp-debirf-modules
|
||||
appliance/stamp-supermin
|
||||
appliance/supermin.d
|
||||
appliance/update.sh
|
||||
appliance/vmlinuz.*
|
||||
autom4te.cache
|
||||
*.bak
|
||||
bindtests.tmp
|
||||
@@ -154,8 +143,6 @@ images/test.iso
|
||||
images/test-grep.txt.gz
|
||||
images/ubuntu.img
|
||||
images/windows.img
|
||||
initramfs
|
||||
initramfs.timestamp
|
||||
inspector/stamp-virt-inspector.pod
|
||||
inspector/virt-inspector
|
||||
inspector/virt-inspector.1
|
||||
|
||||
@@ -186,9 +186,6 @@ CLEANFILES = \
|
||||
pod2htm?.tmp \
|
||||
html/*.html
|
||||
|
||||
clean-local:
|
||||
rm -rf initramfs
|
||||
|
||||
# If you don't want to run all of the tests ('make check') then this
|
||||
# will just run libguestfs-test-tool for a quick check. Note this
|
||||
# is NOT a substitute for proper testing!
|
||||
|
||||
123
README
123
README
@@ -39,11 +39,10 @@ Requirements
|
||||
|
||||
- recent QEMU >= 0.12 with virtio-serial support
|
||||
|
||||
- febootstrap >= 2.10
|
||||
|
||||
- fakeroot
|
||||
|
||||
- fakechroot >= 2.9
|
||||
- febootstrap >= 3.0
|
||||
*NB*: febootstrap 2.x WILL NOT WORK
|
||||
febootstrap 3.x is distro-independent, and is required on
|
||||
Debian and other distros too
|
||||
|
||||
- XDR, rpcgen (on Linux these are provided by glibc)
|
||||
|
||||
@@ -135,40 +134,6 @@ this command as root:
|
||||
make install
|
||||
|
||||
|
||||
Fedora
|
||||
----------------------------------------------------------------------
|
||||
|
||||
We provide packages for Fedora >= 11 in Fedora. Use those, or build
|
||||
from our source RPMs - it's far simpler that way.
|
||||
|
||||
You can compile libguestfs on Fedora 10 but you cannot use it with the
|
||||
version of qemu in Fedora 10. You need to compile your own qemu, see
|
||||
section 'qemu' below.
|
||||
|
||||
|
||||
RHEL / EPEL / CentOS etc
|
||||
----------------------------------------------------------------------
|
||||
|
||||
We provide packages in EPEL which cover RHEL/CentOS >= 5. Use those
|
||||
or build from our source RPMs.
|
||||
|
||||
|
||||
Debian
|
||||
----------------------------------------------------------------------
|
||||
|
||||
libguestfs is now built as a package in Debian by Guido Gunther and
|
||||
the other Debian libvirt maintainers. See:
|
||||
|
||||
http://wiki.debian.org/Teams/DebianLibvirtTeam#Packages
|
||||
|
||||
You can build for Debian in two different ways, either building a
|
||||
Fedora-based appliance using febootstrap, yum, rpm, fakeroot,
|
||||
fakechroot (all packaged in Debian). However the recommended way is
|
||||
to build a Debian-based appliance using debootstrap and debirf.
|
||||
|
||||
Both ways are supported by the configure script.
|
||||
|
||||
|
||||
qemu
|
||||
----------------------------------------------------------------------
|
||||
|
||||
@@ -231,72 +196,9 @@ and removed all the other vmchannels and the SLIRP channel.
|
||||
Supermin appliance
|
||||
----------------------------------------------------------------------
|
||||
|
||||
If you configure with --enable-supermin then we will build a supermin
|
||||
appliance (supermin = super-minimized). This is a very specialized
|
||||
appliance which is built on-the-fly at runtime (specifically, when you
|
||||
call guestfs_launch).
|
||||
|
||||
The normal appliance is a self-contained Linux operating system, based
|
||||
on the Fedora/RHEL/CentOS Linux distro. So it contains a complete
|
||||
copy of all the libraries and programs needed, like kernel, libc,
|
||||
bash, coreutils etc etc.
|
||||
|
||||
The supermin appliance removes the kernel and all the executable
|
||||
libraries and programs from the appliance. That just leaves a
|
||||
skeleton of config files and some data files, which is obviously
|
||||
massively smaller than the normal appliance. At runtime we rebuild
|
||||
the appliance on-the-fly from the libraries and programs on the host
|
||||
(eg. pulling in the real /lib/libc.so, the real /bin/bash etc.)
|
||||
|
||||
Although this process of rebuilding the appliance each time sounds
|
||||
slow, it turns out to be faster than using the prebuilt appliance.
|
||||
(Most of the saving comes from not compressing the appliance - it
|
||||
transpires that decompressing the appliance is the slowest part of the
|
||||
whole boot sequence). On my machine, a new appliance can be built in
|
||||
under a fifth of a second, and the boot time is several seconds
|
||||
shorter.
|
||||
|
||||
The big advantage of the supermin appliance for distributions like
|
||||
Fedora is that it gets security fixes automatically from the host, so
|
||||
there is no need to rebuild the whole of libguestfs for a security
|
||||
update in some underlying library.
|
||||
|
||||
There are several DISADVANTAGES:
|
||||
|
||||
It won't work at all except in very narrow, controlled cases like the
|
||||
Fedora packaging case. We control the dependencies of the libguestfs
|
||||
RPM tightly to ensure that the required binaries are actually present
|
||||
on the host.
|
||||
|
||||
Furthermore there are certain unlikely changes in the packages on the
|
||||
host which could break a supermin appliance, eg. an updated library
|
||||
which depends on an additional data file.
|
||||
|
||||
Also supermin appliances are subjected to changes in the host kernel
|
||||
which might break compatibility with qemu -- these are, of course,
|
||||
real bugs in any case.
|
||||
|
||||
Lastly, supermin appliances really can't be moved between branches of
|
||||
distributions (eg. built on Fedora 12 and moved to Fedora 10) because
|
||||
they are not self-contained and they rely on certain libraries being
|
||||
around. You shouldn't do this anyway.
|
||||
|
||||
Use supermin appliances with caution.
|
||||
|
||||
|
||||
Notes on cross-architecture support
|
||||
----------------------------------------------------------------------
|
||||
|
||||
At the moment we basically don't support cross-architecture or
|
||||
32-on-64. This limits what is possible for some guests. Filesystem
|
||||
operations and FUSE will work fine, but running commands in guests may
|
||||
not be possible.
|
||||
|
||||
To enable this requires work for cross-architecture and 32-on-64
|
||||
support in febootstrap, fakeroot and fakechroot.
|
||||
|
||||
The daemon/ directory contains its own configure script. This is so
|
||||
that in future we will be able to cross-compile the daemon.
|
||||
In libguestfs >= 1.7.19 the supermin appliance is the default and only
|
||||
supported form of appliance. For more information see febootstrap
|
||||
(http://people.redhat.com/~rjones/febootstrap/).
|
||||
|
||||
|
||||
Mirroring tip
|
||||
@@ -327,15 +229,8 @@ distributions. Non-Linux ports are trickier, but we will accept
|
||||
patches if they aren't too invasive.
|
||||
|
||||
The main porting issues are with the dependencies needed to build the
|
||||
appliance. You will need to find or port the following packages
|
||||
first:
|
||||
|
||||
- fakeroot
|
||||
- fakechroot
|
||||
- python
|
||||
- rpm-python http://www.rpm.org/
|
||||
- yum http://yum.baseurl.org/
|
||||
- febootstrap http://people.redhat.com/~rjones/febootstrap/
|
||||
appliance. You will need to port the febootstrap first
|
||||
(http://people.redhat.com/~rjones/febootstrap/).
|
||||
|
||||
|
||||
Copyright and license information
|
||||
|
||||
@@ -18,46 +18,19 @@
|
||||
include $(top_srcdir)/subdir-rules.mk
|
||||
|
||||
EXTRA_DIST = \
|
||||
kmod.whitelist.in \
|
||||
packagelist.in \
|
||||
init \
|
||||
debian/modules/y0_install-guestfsd \
|
||||
debian/modules/z99_final-cleanups \
|
||||
debian/debirf.conf.in \
|
||||
make.sh.in
|
||||
|
||||
# Build the root filesystem (appliance).
|
||||
# Currently this is arch-dependent, so it seems like putting it in
|
||||
# $(libdir) is best. When we build cross-architecture filesystems we
|
||||
# should probably move them to $(datadir).
|
||||
fsdir = $(libdir)/guestfs
|
||||
superminfsdir = $(libdir)/guestfs/supermin.d
|
||||
|
||||
# These are the resulting output files from the whole process:
|
||||
# VMLINUZ kernel for the full appliance
|
||||
# INITRAMFSIMG initramfs (ie. root fs) for the full appliance
|
||||
# For details of the supermin appliance, read the README file.
|
||||
fs_DATA = $(INITRAMFSIMG) $(VMLINUZ)
|
||||
if SUPERMIN
|
||||
fs_DATA += kmod.whitelist
|
||||
fs_DATA =
|
||||
superminfs_DATA = \
|
||||
supermin.d/base.img \
|
||||
supermin.d/daemon.img \
|
||||
supermin.d/init.img \
|
||||
supermin.d/hostfiles
|
||||
endif
|
||||
|
||||
# Don't change these names - they must be the same as in '*.sh' scripts.
|
||||
INITRAMFSIMG = initramfs.$(host_cpu).img
|
||||
VMLINUZ = vmlinuz.$(host_cpu)
|
||||
|
||||
# This is for building the normal appliance:
|
||||
$(INITRAMFSIMG) $(VMLINUZ): $(top_builddir)/initramfs/fakeroot.log
|
||||
|
||||
$(top_builddir)/initramfs/fakeroot.log: make.sh kmod.whitelist packagelist
|
||||
mv $(INITRAMFSIMG) $(INITRAMFSIMG).bak 2>/dev/null; :
|
||||
mv $(VMLINUZ) $(VMLINUZ).bak 2>/dev/null; :
|
||||
if ! bash make.sh; then rm -f $@; exit 1; fi
|
||||
|
||||
# This used to be a configure-generated file (as is update.sh still).
|
||||
# However config.status always touches the destination file, which
|
||||
@@ -68,70 +41,35 @@ make.sh: make.sh.in
|
||||
chmod +x $@-t
|
||||
mv $@-t $@
|
||||
|
||||
$(INITRAMFSIMG): $(top_builddir)/initramfs/fakeroot.log $(top_builddir)/daemon/guestfsd init update.sh
|
||||
rm -f $@
|
||||
bash update.sh
|
||||
touch $@
|
||||
|
||||
kmod.whitelist: kmod.whitelist.in
|
||||
grep -v '^[[:space:]]*$$' < $< | grep -v '^#' > $@
|
||||
|
||||
packagelist: packagelist.in
|
||||
cpp -undef -D$(DIST)=1 < $< | \
|
||||
cpp -undef -D$(DISTRO)=1 < $< | \
|
||||
grep -v '^[[:space:]]*$$' | grep -v '^#' > $@
|
||||
|
||||
# This is for building the supermin appliance. It has to be enabled
|
||||
# specifically with './configure --enable-supermin'. You really need
|
||||
# to read the README file.
|
||||
|
||||
if SUPERMIN
|
||||
|
||||
supermin.d/base.img supermin.d/hostfiles: stamp-supermin
|
||||
stamp-supermin: $(INITRAMFSIMG)
|
||||
stamp-supermin: make.sh packagelist
|
||||
mkdir -p supermin.d
|
||||
rm -f $@ supermin.d/base.img supermin.d/hostfiles
|
||||
febootstrap-to-supermin $(top_builddir)/initramfs supermin.d/base.img supermin.d/hostfiles
|
||||
if grep -q /usr/share/augeas/lenses supermin.d/hostfiles; then \
|
||||
echo "./usr/share/augeas/lenses/*.aug" >> supermin.d/hostfiles; \
|
||||
fi
|
||||
./make.sh
|
||||
touch $@
|
||||
|
||||
supermin.d/daemon.img: $(INITRAMFSIMG)
|
||||
supermin.d/daemon.img: ../daemon/guestfsd
|
||||
mkdir -p supermin.d
|
||||
rm -f $@ $@-t
|
||||
(cd $(top_builddir)/initramfs && \
|
||||
echo -e "sbin\nsbin/guestfsd" | cpio --quiet -o -H newc ) > $@-t
|
||||
mkdir sbin
|
||||
cd sbin && ln ../../daemon/guestfsd
|
||||
echo -e "sbin\nsbin/guestfsd" | cpio --quiet -o -H newc > $@-t
|
||||
rm -r sbin
|
||||
mv $@-t $@
|
||||
|
||||
supermin.d/init.img: $(INITRAMFSIMG)
|
||||
supermin.d/init.img: init
|
||||
mkdir -p supermin.d
|
||||
rm -f $@ $@-t
|
||||
(cd $(top_builddir)/initramfs && \
|
||||
echo -e "init\n" | cpio --quiet -o -H newc ) > $@-t
|
||||
echo "init" | cpio --quiet -o -H newc > $@-t
|
||||
mv $@-t $@
|
||||
|
||||
endif
|
||||
|
||||
# Extra symlinks needed by the Debian appliance.
|
||||
debirf_symlinks = \
|
||||
a0_prep-root \
|
||||
install-kernel \
|
||||
z0_remove-aptitude \
|
||||
z0_remove-locales \
|
||||
z1_clean-root
|
||||
noinst_DATA = $(debirf_symlinks:%=debian/modules/%)
|
||||
$(debirf_symlinks:%=debian/modules/%): stamp-debirf-modules
|
||||
stamp-debirf-modules:
|
||||
mkdir -p debian/modules
|
||||
for f in $(debirf_symlinks); do \
|
||||
ln -sf /usr/share/debirf/modules/$$f debian/modules/$$f; \
|
||||
done
|
||||
touch $@
|
||||
|
||||
# Make clean.
|
||||
|
||||
CLEANFILES = packagelist kmod.whitelist
|
||||
CLEANFILES = packagelist
|
||||
|
||||
clean-local:
|
||||
rm -f supermin.d/*
|
||||
rm -rf $(top_builddir)/initramfs
|
||||
rm -rf supermin.d
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
DEBIRF_LABEL="debirf-libguestfs"
|
||||
DEBIRF_SUITE=@REPO@
|
||||
DEBIRF_MIRROR=@MIRROR@/${DEBIRF_DISTRO}
|
||||
DEBIRF_KERNEL_ARCH=@DEBIAN_KERNEL_ARCH@
|
||||
DEBIRF_METHOD=stupid_simple
|
||||
@@ -1 +0,0 @@
|
||||
/usr/share/debirf/modules/a0_prep-root
|
||||
@@ -1 +0,0 @@
|
||||
/usr/share/debirf/modules/install-kernel
|
||||
@@ -1,40 +0,0 @@
|
||||
#!/bin/bash -e
|
||||
# install guestfsd specific stuff
|
||||
|
||||
# Kernel modules take up nearly half of the image. Only include ones
|
||||
# which are on the whitelist.
|
||||
exec 5<../appliance/kmod.whitelist
|
||||
whitelist=
|
||||
while read kmod 0<&5; do
|
||||
whitelist="$whitelist -a -not -name $kmod"
|
||||
done
|
||||
exec 5<&-
|
||||
|
||||
echo "Module whitelist: $whitelist"
|
||||
find $DEBIRF_ROOT/lib/modules/*/kernel -name '*.ko' $whitelist -a -exec rm '{}' \;
|
||||
|
||||
# install additional packages from the package list, but
|
||||
# only ones which exist in the repository
|
||||
PKGLIST=
|
||||
for pkg in $(< packagelist); do
|
||||
if [ "$(debirf_exec apt-get -s install $pkg 3>&1 1>&2 2>&3 1>&- | grep '^E:' | wc -l)" -gt 0 ]; then
|
||||
echo "Ignoring package $pkg, because it was not found in this repository."
|
||||
else
|
||||
PKGLIST="$PKGLIST $pkg"
|
||||
fi
|
||||
done
|
||||
echo "Will add $PKGLIST"
|
||||
debirf_exec apt-get --assume-yes install $PKGLIST
|
||||
debirf_exec apt-get --assume-yes remove vim-tiny dhcp3-client iptables
|
||||
|
||||
debirf_exec mkdir -p --mode=0777 /sysroot
|
||||
|
||||
# cleanup some other heavy lifters:
|
||||
rm -rf "$DEBIRF_ROOT"/usr/share/doc/
|
||||
rm -rf "$DEBIRF_ROOT"/usr/share/zoneinfo/
|
||||
rm -rf "$DEBIRF_ROOT"/usr/share/man/
|
||||
|
||||
# Install the actual appliance:
|
||||
echo $PWD
|
||||
install -o root -g root -m 0755 ../daemon/guestfsd "$DEBIRF_ROOT"/sbin/guestfsd
|
||||
install -o root -g root -m 0755 init "$DEBIRF_ROOT"/sbin/init
|
||||
@@ -1 +0,0 @@
|
||||
/usr/share/debirf/modules/z0_remove-aptitude
|
||||
@@ -1 +0,0 @@
|
||||
/usr/share/debirf/modules/z0_remove-locales
|
||||
@@ -1 +0,0 @@
|
||||
/usr/share/debirf/modules/z1_clean-root
|
||||
@@ -1,3 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
rm -rf "$DEBIRF_ROOT"/var/lib/dpkg/info
|
||||
@@ -1,86 +0,0 @@
|
||||
# List of kernel modules that we leave in the appliance. This has to
|
||||
# include any dependencies needed by modules.
|
||||
|
||||
# Any kernel module not listed here is deleted from the appliance.
|
||||
|
||||
# Wildcards are permitted.
|
||||
|
||||
virtio*.ko
|
||||
|
||||
# We normally use virtio_net, but keep these in reserve.
|
||||
8390.ko
|
||||
ne2k-pci.ko
|
||||
|
||||
# drivers for QEMUs IDE/SCSI device emulation
|
||||
cdrom.ko
|
||||
i2c-piix4.ko
|
||||
i2c-core.ko
|
||||
ide-*.ko
|
||||
libata.ko
|
||||
piix.ko
|
||||
scsi_transport_spi.ko
|
||||
scsi_mod.ko
|
||||
sd_mod.ko
|
||||
sym53c8xx.ko
|
||||
ata_piix.ko
|
||||
sr_mod.ko
|
||||
|
||||
ext2.ko
|
||||
ext3.ko
|
||||
ext4*.ko
|
||||
|
||||
jbd.ko
|
||||
jbd2.ko
|
||||
mbcache.ko
|
||||
|
||||
fuse.ko
|
||||
|
||||
vfat.ko
|
||||
fat.ko
|
||||
|
||||
minix.ko
|
||||
|
||||
udf.ko
|
||||
nls_utf8.ko
|
||||
nls_cp437.ko
|
||||
nls_base.ko
|
||||
|
||||
isofs.ko
|
||||
zlib_inflate.ko
|
||||
|
||||
dm-*.ko
|
||||
|
||||
cramfs.ko
|
||||
squashfs.ko
|
||||
|
||||
hfs.ko
|
||||
hfsplus.ko
|
||||
ufs.ko
|
||||
exportfs.ko
|
||||
xfs.ko
|
||||
|
||||
reiserfs.ko
|
||||
|
||||
crc*.ko
|
||||
libcrc*.ko
|
||||
|
||||
loop.ko
|
||||
|
||||
gfs2.ko
|
||||
dlm.ko
|
||||
configfs.ko
|
||||
|
||||
# Used by dm-crypt. Probably many more crypto modules
|
||||
# should be added here.
|
||||
aes*.ko
|
||||
blkcipher.ko
|
||||
cbc.ko
|
||||
cryptd.ko
|
||||
crypto_blkcipher.ko
|
||||
gf128mul.ko
|
||||
padlock-aes.ko
|
||||
sha256*.ko
|
||||
sha512*.ko
|
||||
xor.ko
|
||||
xts.ko
|
||||
zlib.ko
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash -
|
||||
# @configure_input@
|
||||
# Copyright (C) 2009 Red Hat Inc.
|
||||
# Copyright (C) 2009-2010 Red Hat Inc.
|
||||
#
|
||||
# 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
|
||||
@@ -16,167 +16,46 @@
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
# This is called from the Makefile to build the initramfs.
|
||||
|
||||
unset CDPATH
|
||||
|
||||
set -e
|
||||
set -x
|
||||
|
||||
if [ "@DIST@" = "REDHAT" ]; then
|
||||
cd @top_builddir@
|
||||
# Decide on names for the final output. These have to match Makefile.am.
|
||||
output=appliance/initramfs.@host_cpu@.img
|
||||
koutput=appliance/vmlinuz.@host_cpu@
|
||||
rm -f $output
|
||||
rm -f $koutput
|
||||
# XXX Distro-dependent in future.
|
||||
excludes="--exclude '^perl' --exclude '^python' --exclude '^fedora-logos' --exclude '^redhat-logos' --exclude '^dracut' --exclude '^upstart' --exclude '^plymouth' --exclude '^systemd' --exclude '^linux-firmware' --exclude '^kbd-misc'"
|
||||
|
||||
# Create the basic initramfs.
|
||||
exec 5<appliance/packagelist
|
||||
packages=
|
||||
while read pkg 0<&5; do
|
||||
packages="$packages -i $pkg"
|
||||
done
|
||||
exec 5<&-
|
||||
|
||||
@FEBOOTSTRAP@ $packages -u @UPDATES@ @REPO@ initramfs @MIRROR@
|
||||
|
||||
# Create modules.dep. This is only used in the normal appliance
|
||||
# (not supermin).
|
||||
kversion=$(basename initramfs/lib/modules/*)
|
||||
@FEBOOTSTRAP_RUN@ initramfs -- /sbin/depmod -a $kversion
|
||||
|
||||
# /sysroot is where the guest root filesystem will be mounted.
|
||||
@FEBOOTSTRAP_RUN@ initramfs -- mkdir -p --mode=0777 /sysroot
|
||||
|
||||
# Create /tmp if it is missing.
|
||||
@FEBOOTSTRAP_RUN@ initramfs -- mkdir -p --mode=0777 /tmp
|
||||
|
||||
# Create /selinux if it is missing.
|
||||
@FEBOOTSTRAP_RUN@ initramfs -- mkdir -p --mode=0755 /selinux
|
||||
|
||||
# Nuke some stuff. The kernel pulls mkinitrd and plymouth which pulls in
|
||||
# all of Python. Sheez.
|
||||
(cd initramfs && find -name '*python*' -print0) |
|
||||
xargs -0 @FEBOOTSTRAP_RUN@ initramfs -- rm -rf
|
||||
(cd initramfs && find -name '*plymouth*' -print0) |
|
||||
xargs -0 @FEBOOTSTRAP_RUN@ initramfs -- rm -rf
|
||||
(cd initramfs && find -name 'libply-*' -print0) |
|
||||
xargs -0 @FEBOOTSTRAP_RUN@ initramfs -- rm -rf
|
||||
|
||||
# In Fedora >= 11, it pulls in all of Perl from somewhere. Nuke from orbit.
|
||||
@FEBOOTSTRAP_RUN@ initramfs -- rm -rf /usr/lib/perl5 /usr/lib64/perl5
|
||||
|
||||
# Anaconda? JPEG images?
|
||||
@FEBOOTSTRAP_RUN@ initramfs -- rm -rf /usr/lib/anaconda-runtime
|
||||
|
||||
# Don't need any firmware.
|
||||
@FEBOOTSTRAP_RUN@ initramfs -- rm -rf /lib/firmware
|
||||
|
||||
# Don't need any keyboard maps.
|
||||
@FEBOOTSTRAP_RUN@ initramfs -- rm -rf /lib/kbd
|
||||
|
||||
# Remove anything in home directory. Because of the potential for disaster
|
||||
# we don't put a slash before 'home'.
|
||||
(cd initramfs && echo home/*) |
|
||||
xargs @FEBOOTSTRAP_RUN@ initramfs -- rm -rf
|
||||
|
||||
# Remove /var/lib/yum stuff.
|
||||
@FEBOOTSTRAP_RUN@ initramfs -- rm -rf /var/lib/yum
|
||||
|
||||
# Remove some unreadable binaries which are incompatible with
|
||||
# the supermin appliance. Since these binaries can't be read
|
||||
# from the host filesystem, they cannot be added to the supermin
|
||||
# appliance at run time. XXX Need a better fix for this.
|
||||
# Probably we should change febootstrap-supermin-helper to just
|
||||
# ignore such files.
|
||||
@FEBOOTSTRAP_RUN@ initramfs -- rm -f \
|
||||
/usr/bin/chfn \
|
||||
/usr/bin/chsh \
|
||||
/usr/libexec/pt_chown \
|
||||
/usr/libexec/utempter/utempter \
|
||||
/usr/sbin/groupdel \
|
||||
/usr/sbin/groupadd \
|
||||
/usr/sbin/useradd \
|
||||
/usr/sbin/tzdata-update \
|
||||
/usr/sbin/userdel \
|
||||
/usr/sbin/usermod \
|
||||
/usr/sbin/groupmod \
|
||||
/usr/sbin/groupmems \
|
||||
/sbin/unix_update \
|
||||
/usr/sbin/tcpd \
|
||||
/usr/share/dbus-1/services/org.selinux.Restorecond.service \
|
||||
/lib/dbus-1/dbus-daemon-launch-helper \
|
||||
/lib64/dbus-1/dbus-daemon-launch-helper \
|
||||
/etc/passwd- \
|
||||
/etc/group- \
|
||||
/etc/gshadow \
|
||||
/etc/gshadow- \
|
||||
/etc/shadow \
|
||||
/etc/shadow- \
|
||||
/etc/securetty \
|
||||
/etc/sysconfig/iptables-config \
|
||||
/etc/default/useradd \
|
||||
/etc/security/opasswd \
|
||||
/etc/libaudit.conf \
|
||||
/var/log/tallylog \
|
||||
/var/log/maillog \
|
||||
/var/log/secure \
|
||||
/var/log/spooler \
|
||||
/var/log/messages \
|
||||
/var/log/btmp \
|
||||
/var/log/yum.log \
|
||||
$(cd initramfs && echo usr/sbin/glibc_post_upgrade.*)
|
||||
|
||||
# Remove all .*.hmac files (RHBZ#654638). These are not used unless
|
||||
# you are using FIPS, and they cause hard dependencies on files
|
||||
# which change whenever a library version is bumped.
|
||||
@FEBOOTSTRAP_RUN@ initramfs -- rm -f $(cd initramfs && find -name '.*.hmac')
|
||||
|
||||
# Kernel modules take up nearly half of the image. Only include ones
|
||||
# which are on the whitelist.
|
||||
exec 5<appliance/kmod.whitelist
|
||||
whitelist=
|
||||
while read kmod 0<&5; do
|
||||
whitelist="$whitelist -a -not -name $kmod"
|
||||
done
|
||||
exec 5<&-
|
||||
|
||||
(cd initramfs && \
|
||||
find lib/modules/*/kernel -name '*.ko' $whitelist -a -print0 ) |
|
||||
xargs -0 febootstrap-run initramfs -- rm
|
||||
|
||||
# Pull the kernel out into the current directory. We don't want it in
|
||||
# the initramfs image.
|
||||
cp initramfs/boot/vmlinuz* $koutput
|
||||
@FEBOOTSTRAP_RUN@ initramfs -- rm -rf boot
|
||||
|
||||
# Minimize the image.
|
||||
@FEBOOTSTRAP_MINIMIZE@ initramfs
|
||||
|
||||
# Add some missing configuration files.
|
||||
if [ ! -f initramfs/etc/hosts ]; then
|
||||
cat > hosts.new <<'__EOF__'
|
||||
127.0.0.1 guestfs localhost.localdomain localhost
|
||||
::1 localhost6.localdomain6 localhost6
|
||||
__EOF__
|
||||
@FEBOOTSTRAP_INSTALL@ initramfs hosts.new /etc/hosts 0644 root.root
|
||||
rm hosts.new
|
||||
fi
|
||||
|
||||
if [ ! -f initramfs/etc/fstab ]; then
|
||||
@FEBOOTSTRAP_RUN@ initramfs -- touch /etc/fstab
|
||||
fi
|
||||
|
||||
echo nameserver 169.254.2.3 > resolv.conf.new
|
||||
@FEBOOTSTRAP_INSTALL@ initramfs resolv.conf.new /etc/resolv.conf 0644 root.root
|
||||
rm resolv.conf.new
|
||||
|
||||
ls -lh $koutput
|
||||
|
||||
elif [ "@DIST@" = "DEBIAN" ]; then
|
||||
cd @top_builddir@/appliance
|
||||
debirf make -n debian
|
||||
mkdir -p @top_builddir@/initramfs
|
||||
touch @top_builddir@/initramfs/fakeroot.log
|
||||
# Run febootstrap on the package list.
|
||||
if [ -z "@PACKAGE_DIRECTORY@" ]; then
|
||||
@FEBOOTSTRAP@ -v -o supermin.d $excludes --names $(< packagelist )
|
||||
else
|
||||
@FEBOOTSTRAP@ -v -o supermin.d $excludes @PACKAGE_DIRECTORY@/*
|
||||
fi
|
||||
|
||||
# Remove some things that we don't want in the appliance. This is
|
||||
# copied from the old febootstrap-minimize. However minimization is
|
||||
# not so important now that we are caching the appliance.
|
||||
< supermin.d/hostfiles \
|
||||
grep -v '^/usr/lib/locale' |
|
||||
grep -v '^/usr/share/locale' |
|
||||
grep -v '^/usr/lib/gconv' |
|
||||
grep -v '^/usr/lib64/gconv' |
|
||||
grep -v '^/usr/bin/localedef' |
|
||||
grep -v '^/usr/sbin/build-locale-archive' |
|
||||
grep -v '^/usr/share/man/' |
|
||||
grep -v '^/usr/share/doc/' |
|
||||
grep -v '^/usr/share/info/' |
|
||||
grep -v '^/usr/share/gnome/help/' |
|
||||
grep -v '^/usr/share/cracklib/' |
|
||||
grep -v '^/usr/share/i18n/' > supermin.d/hostfiles-t
|
||||
|
||||
# XXX resolv.conf? The old script had:
|
||||
# echo nameserver 169.254.2.3 > resolv.conf
|
||||
if ! grep -q /etc/resolv.conf supermin.d/hostfiles-t; then
|
||||
echo /etc/resolv.conf >> supermin.d/hostfiles-t
|
||||
fi
|
||||
|
||||
# Include any Augeas lenses from the host.
|
||||
if grep -q /usr/share/augeas/lenses supermin.d/hostfiles-t; then
|
||||
echo "/usr/share/augeas/lenses/*.aug" >> supermin.d/hostfiles-t
|
||||
fi
|
||||
|
||||
mv supermin.d/hostfiles-t supermin.d/hostfiles
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
#!/bin/bash -
|
||||
# @configure_input@
|
||||
# Copyright (C) 2009 Red Hat Inc.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
# Update the init script or daemon inside an existing initramfs.
|
||||
# Avoids the timeconsuming rebuild.
|
||||
|
||||
unset CDPATH
|
||||
|
||||
set -e
|
||||
|
||||
if [ "@DIST@" = "REDHAT" ]; then
|
||||
cd @top_builddir@
|
||||
output=appliance/initramfs.@host_cpu@.img
|
||||
|
||||
# Create the init script.
|
||||
@FEBOOTSTRAP_INSTALL@ initramfs appliance/@top_srcdir@/appliance/init /init 0755 root.root
|
||||
|
||||
# Copy the daemon into the filesystem.
|
||||
@FEBOOTSTRAP_INSTALL@ initramfs daemon/guestfsd /sbin/guestfsd 0755 root.root
|
||||
|
||||
# Generate final image.
|
||||
@FEBOOTSTRAP_TO_INITRAMFS@ initramfs > $output-t
|
||||
mv $output-t $output
|
||||
ls -lh $output
|
||||
elif [ "@DIST@" = "DEBIAN" ]; then
|
||||
cd @top_builddir@/appliance
|
||||
|
||||
output=initramfs.@host_cpu@.img
|
||||
vmlinuz=vmlinuz.@host_cpu@
|
||||
|
||||
rm -f debian/debirf-libguestfs_@REPO@_.cgz
|
||||
ln -sf debian/debirf-libguestfs_@REPO@*.cgz $output
|
||||
ln -sf debian/vmlinuz-* $vmlinuz
|
||||
fi
|
||||
@@ -50,10 +50,11 @@ EXTRA_DIST += test-add-libvirt-dom.c
|
||||
TESTS_ENVIRONMENT = \
|
||||
SKIP_TEST_COMMAND=$(shell ldd test-command | grep -sq 'not a dynamic executable' || echo 1) \
|
||||
SKIP_TEST_COMMAND_LINES=$(shell ldd test-command | grep -sq 'not a dynamic executable' || echo 1) \
|
||||
SKIP_TEST_CHECKSUM_8=$(shell if test `find ../initramfs -name squashfs.ko | wc -l` -eq 0; then echo 1; fi) \
|
||||
LIBGUESTFS_PATH=$(top_builddir)/appliance \
|
||||
$(VG)
|
||||
|
||||
#SKIP_TEST_CHECKSUM_8=$(shell if test `find ../initramfs -name squashfs.ko | wc -l` -eq 0; then echo 1; fi)
|
||||
|
||||
tests_SOURCES = tests.c
|
||||
tests_CFLAGS = -I$(top_srcdir)/src -I$(top_builddir)/src \
|
||||
$(WARN_CFLAGS) $(WERROR_CFLAGS)
|
||||
|
||||
153
configure.ac
153
configure.ac
@@ -188,6 +188,44 @@ AC_ARG_ENABLE([appliance],
|
||||
AM_CONDITIONAL([ENABLE_APPLIANCE],[test "x$enable_appliance" = "xyes"])
|
||||
AC_MSG_RESULT([$enable_appliance])
|
||||
|
||||
if test "x$enable_appliance" = "xyes"; then
|
||||
dnl Check for febootstrap >= 3.0
|
||||
AC_CHECK_PROG([FEBOOTSTRAP],
|
||||
[febootstrap],[febootstrap],[no])
|
||||
test "x$FEBOOTSTRAP" = "xno" &&
|
||||
AC_MSG_ERROR([febootstrap must be installed])
|
||||
dnl febootstrap 2.x did not support the --version parameter
|
||||
$FEBOOTSTRAP --version >/dev/null 2>&1 ||
|
||||
AC_MSG_ERROR([febootstrap >= 3.0 must be installed, your version is too old])
|
||||
|
||||
dnl Build from local package files, used when building with no network
|
||||
dnl access, ie. under Koji.
|
||||
AC_MSG_CHECKING([if we should build the appliance from local packages])
|
||||
AC_ARG_WITH([local-package-directory],
|
||||
[AS_HELP_STRING([--with-local-package-directory],
|
||||
[build from local packages in dir @<:@default=no@:>@])],
|
||||
[local_package_directory=$withval],
|
||||
[local_package_directory=no])
|
||||
AC_MSG_RESULT([$local_package_directory])
|
||||
PACKAGE_DIRECTORY=
|
||||
test "x$local_package_directory" != "xno" &&
|
||||
PACKAGE_DIRECTORY="$local_package_directory"
|
||||
AC_SUBST([PACKAGE_DIRECTORY])
|
||||
|
||||
dnl Which distro?
|
||||
dnl
|
||||
dnl This used to be Very Important but is now just used to select
|
||||
dnl which packages to install in the appliance, since the package
|
||||
dnl names vary slightly across distros. (See appliance/packagelist.in)
|
||||
AC_MSG_CHECKING([which Linux distro for package names])
|
||||
DISTRO=REDHAT
|
||||
if test -f /etc/debian_version; then
|
||||
DISTRO=DEBIAN
|
||||
fi
|
||||
AC_MSG_RESULT([$DISTRO])
|
||||
AC_SUBST([DISTRO])
|
||||
fi
|
||||
|
||||
dnl Check for rpcgen and XDR library. rpcgen is optional.
|
||||
AC_CHECK_PROG([RPCGEN],[rpcgen],[rpcgen],[no])
|
||||
AM_CONDITIONAL([HAVE_RPCGEN],[test "x$RPCGEN" != "xno"])
|
||||
@@ -305,117 +343,6 @@ AC_ARG_WITH([net-if],
|
||||
[with_net_if=virtio-net-pci])
|
||||
AC_DEFINE_UNQUOTED([NET_IF],["$with_net_if"],[Default network interface.])
|
||||
|
||||
dnl Check for febootstrap etc.
|
||||
if test "x$enable_appliance" = "xyes"; then
|
||||
AC_CHECK_PROG([FEBOOTSTRAP],
|
||||
[febootstrap],[febootstrap],[no])
|
||||
if test "x$FEBOOTSTRAP" != "xno"; then
|
||||
AC_CHECK_PROG([FEBOOTSTRAP_RUN],
|
||||
[febootstrap-run],[febootstrap-run],[no])
|
||||
test "x$FEBOOTSTRAP_RUN" = "xno" && \
|
||||
AC_MSG_ERROR([febootstrap-run must be installed])
|
||||
AC_CHECK_PROG([FEBOOTSTRAP_INSTALL],
|
||||
[febootstrap-install],[febootstrap-install],[no])
|
||||
test "x$FEBOOTSTRAP_INSTALL" = "xno" && \
|
||||
AC_MSG_ERROR([febootstrap-install must be installed])
|
||||
AC_CHECK_PROG([FEBOOTSTRAP_MINIMIZE],
|
||||
[febootstrap-minimize],[febootstrap-minimize],[no])
|
||||
test "x$FEBOOTSTRAP_MINIMIZE" = "xno" && \
|
||||
AC_MSG_ERROR([febootstrap-minimize must be installed])
|
||||
AC_CHECK_PROG([FEBOOTSTRAP_TO_INITRAMFS],
|
||||
[febootstrap-to-initramfs],[febootstrap-to-initramfs],[no])
|
||||
test "x$FEBOOTSTRAP_TO_INITRAMFS" = "xno" && \
|
||||
AC_MSG_ERROR([febootstrap-to-initramfs must be installed])
|
||||
AC_CHECK_PROG([FEBOOTSTRAP_TO_SUPERMIN],
|
||||
[febootstrap-to-supermin],[febootstrap-to-supermin],[no])
|
||||
test "x$FEBOOTSTRAP_TO_SUPERMIN" = "xno" && \
|
||||
AC_MSG_ERROR([febootstrap-to-supermin must be installed])
|
||||
|
||||
dnl Check we have fakechroot >= 2.9 (it's an indirect requirement
|
||||
dnl of febootstrap, but old versions will fail with yum).
|
||||
AC_CHECK_PROG([FAKECHROOT],
|
||||
[fakechroot],[fakechroot],[no])
|
||||
test "x$FAKECHROOT" = "xno" && \
|
||||
AC_MSG_ERROR([fakechroot must be installed])
|
||||
|
||||
AC_MSG_CHECKING([fakechroot version])
|
||||
fakechroot_version=`$FAKECHROOT --version | awk '{print $3}'`
|
||||
if test -z "$fakechroot_version"; then
|
||||
AC_MSG_RESULT([failed])
|
||||
AC_MSG_WARN([fakechroot --version command failed, proceeding anyway])
|
||||
else
|
||||
AC_MSG_RESULT([$fakechroot_version])
|
||||
fakechroot_major=`echo "$fakechroot_version" | awk -F. '{print $1}'`
|
||||
fakechroot_minor=`echo "$fakechroot_version" | awk -F. '{print $2}'`
|
||||
if test "$fakechroot_major" -lt 2 || \
|
||||
( test "$fakechroot_major" -eq 2 && test "$fakechroot_minor" -lt 9 ); then
|
||||
AC_MSG_ERROR([fakechroot version must be >= 2.9])
|
||||
fi
|
||||
fi
|
||||
DIST="REDHAT"
|
||||
else
|
||||
# check for debootstrap and debirf
|
||||
AC_CHECK_PROG([DEBOOTSTRAP],
|
||||
[debootstrap],[debootstrap],[no])
|
||||
test "x$DEBOOTSTRAP" = "xno" && \
|
||||
AC_MSG_ERROR([Either febootstrap or debootstrap must be installed])
|
||||
AC_CHECK_PROG([DEBIRF],[debirf],[debirf],[no])
|
||||
test "x$DEBIRF" = "xno" &&
|
||||
AC_MSG_ERROR([debirf must be installed])
|
||||
DIST="DEBIAN"
|
||||
case "$host_cpu" in
|
||||
*86)
|
||||
DEBIAN_KERNEL_ARCH=486
|
||||
;;
|
||||
x86_64)
|
||||
DEBIAN_KERNEL_ARCH=amd64
|
||||
;;
|
||||
*)
|
||||
DEBIAN_KERNEL_ARCH=$host_cpu
|
||||
;;
|
||||
esac
|
||||
AC_SUBST(DEBIAN_KERNEL_ARCH)
|
||||
fi
|
||||
AC_SUBST(DIST)
|
||||
|
||||
dnl --with-updates to specify a Fedora updates repository.
|
||||
AC_ARG_WITH([updates],
|
||||
[AS_HELP_STRING([--with-updates],
|
||||
[set name of Fedora updates repository @<:@default=updates-released-f12@:>@])],
|
||||
[],
|
||||
[with_updates=updates-released-f12])
|
||||
UPDATES="$with_updates"
|
||||
AC_SUBST(UPDATES)
|
||||
|
||||
dnl --with-mirror to specify a local Fedora mirror.
|
||||
AC_ARG_WITH([mirror],
|
||||
[AS_HELP_STRING([--with-mirror],
|
||||
[set URI of a local Fedora mirror])],
|
||||
[],
|
||||
[with_mirror=])
|
||||
MIRROR="$with_mirror"
|
||||
AC_SUBST(MIRROR)
|
||||
fi
|
||||
|
||||
dnl --with-repo to specify a repository.
|
||||
AC_ARG_WITH([repo],
|
||||
[AS_HELP_STRING([--with-repo],
|
||||
[set name of Fedora repository @<:@default=fedora-13@:>@])],
|
||||
[],
|
||||
[with_repo=fedora-13])
|
||||
REPO="$with_repo"
|
||||
AC_SUBST(REPO)
|
||||
AC_DEFINE_UNQUOTED([REPO],["$REPO"],[Name of software repository.])
|
||||
|
||||
dnl Build the supermin appliance? Please see README file before
|
||||
dnl enabling this option.
|
||||
AC_ARG_ENABLE([supermin],
|
||||
[AS_HELP_STRING([--enable-supermin],
|
||||
[enable supermin appliance (see README) @<:@default=no@:>@])],
|
||||
[AC_DEFINE([ENABLE_SUPERMIN],[1],[Supermin appliance enabled.])],
|
||||
[enable_supermin=no])
|
||||
AM_CONDITIONAL([SUPERMIN],[test "x$enable_supermin" = "xyes"])
|
||||
|
||||
dnl Enable packet dumps when in verbose mode. This generates lots
|
||||
dnl of debug info, only useful for people debugging the RPC mechanism.
|
||||
AC_ARG_ENABLE([packet-dump],
|
||||
@@ -843,15 +770,12 @@ fi
|
||||
dnl Produce output files.
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
dnl http://www.mail-archive.com/automake@gnu.org/msg10204.html
|
||||
AC_CONFIG_FILES([appliance/update.sh],
|
||||
[chmod +x appliance/update.sh])
|
||||
AC_CONFIG_FILES([podwrapper.sh],
|
||||
[chmod +x podwrapper.sh])
|
||||
AC_CONFIG_FILES([Makefile
|
||||
generator/Makefile
|
||||
src/Makefile fish/Makefile po/Makefile.in examples/Makefile
|
||||
appliance/Makefile
|
||||
appliance/debian/debirf.conf
|
||||
images/Makefile
|
||||
capitests/Makefile
|
||||
regressions/Makefile
|
||||
@@ -905,7 +829,6 @@ echo -n "PHP bindings ........................ "
|
||||
if test "x$HAVE_PHP_TRUE" = "x"; then echo "yes"; else echo "no"; fi
|
||||
echo -n "virt-* tools ........................ "
|
||||
if test "x$HAVE_TOOLS_TRUE" = "x"; then echo "yes"; else echo "no"; fi
|
||||
echo "supermin appliance .................. $enable_supermin"
|
||||
echo "FUSE filesystem ..................... $enable_fuse"
|
||||
echo
|
||||
echo "If any optional component is configured 'no' when you expected 'yes'"
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
#include "guestfs-internal-actions.h"
|
||||
#include "guestfs_protocol.h"
|
||||
|
||||
/* Old-style appliance is going to be obsoleted. */
|
||||
static const char *kernel_name = "vmlinuz." host_cpu;
|
||||
static const char *initrd_name = "initramfs." host_cpu ".img";
|
||||
|
||||
@@ -48,13 +49,11 @@ static int find_path (guestfs_h *g, int (*pred) (guestfs_h *g, const char *pelem
|
||||
static int dir_contains_file (const char *dir, const char *file);
|
||||
static int dir_contains_files (const char *dir, ...);
|
||||
static int contains_ordinary_appliance (guestfs_h *g, const char *path, void *data);
|
||||
#if ENABLE_SUPERMIN
|
||||
static int contains_supermin_appliance (guestfs_h *g, const char *path, void *data);
|
||||
static char *calculate_supermin_checksum (guestfs_h *g, const char *supermin_path);
|
||||
static int check_for_cached_appliance (guestfs_h *g, const char *supermin_path, const char *checksum, char **kernel, char **initrd, char **appliance);
|
||||
static int build_supermin_appliance (guestfs_h *g, const char *supermin_path, const char *checksum, char **kernel, char **initrd, char **appliance);
|
||||
static int run_supermin_helper (guestfs_h *g, const char *supermin_path, const char *cachedir, size_t cdlen);
|
||||
#endif
|
||||
|
||||
/* Locate or build the appliance.
|
||||
*
|
||||
@@ -90,7 +89,6 @@ guestfs___build_appliance (guestfs_h *g,
|
||||
{
|
||||
int r;
|
||||
|
||||
#if ENABLE_SUPERMIN
|
||||
/* Step (1). */
|
||||
char *supermin_path;
|
||||
r = find_path (g, contains_supermin_appliance, NULL, &supermin_path);
|
||||
@@ -119,7 +117,6 @@ guestfs___build_appliance (guestfs_h *g,
|
||||
}
|
||||
free (supermin_path);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Step (5). */
|
||||
char *path;
|
||||
@@ -150,7 +147,6 @@ contains_ordinary_appliance (guestfs_h *g, const char *path, void *data)
|
||||
return dir_contains_files (path, kernel_name, initrd_name, NULL);
|
||||
}
|
||||
|
||||
#if ENABLE_SUPERMIN
|
||||
static int
|
||||
contains_supermin_appliance (guestfs_h *g, const char *path, void *data)
|
||||
{
|
||||
@@ -536,7 +532,6 @@ run_supermin_helper (guestfs_h *g, const char *supermin_path,
|
||||
perror ("execvp");
|
||||
_exit (EXIT_FAILURE);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Search elements of g->path, returning the first path element which
|
||||
* matches the predicate function 'pred'.
|
||||
|
||||
Reference in New Issue
Block a user