rc.initdiskless revision 110942
150565Sphk#!/bin/sh
250565Sphk#
350565Sphk# Copyright (c) 1999  Matt Dillion
450565Sphk# All rights reserved.
550565Sphk#
650565Sphk# Redistribution and use in source and binary forms, with or without
750565Sphk# modification, are permitted provided that the following conditions
850565Sphk# are met:
950565Sphk# 1. Redistributions of source code must retain the above copyright
1050565Sphk#    notice, this list of conditions and the following disclaimer.
1150565Sphk# 2. Redistributions in binary form must reproduce the above copyright
1250565Sphk#    notice, this list of conditions and the following disclaimer in the
1350565Sphk#    documentation and/or other materials provided with the distribution.
1450565Sphk#
1550565Sphk# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1651111Sjulian# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1750565Sphk# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1850565Sphk# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1950565Sphk# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2050565Sphk# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2150728Sphk# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2250565Sphk# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2350565Sphk# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2450565Sphk# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2550565Sphk# SUCH DAMAGE.
2650565Sphk#
2750565Sphk# $FreeBSD: head/etc/rc.initdiskless 110942 2003-02-15 16:29:20Z jhay $
2850565Sphk#
2950565Sphk# PROVIDE: initdiskless
3050565Sphk# KEYWORD: FreeBSD
3150565Sphk
3251215Sphk 
3350565Sphk# On entry to this script the entire system consists of a read-only root
3450565Sphk# mounted via NFS.  We use the contents of /conf to create and populate
3550565Sphk# memory filesystems.  The kernel has run BOOTP and configured an interface
3651198Sphk# (otherwise it would not have been able to mount the NFS root!)
3751198Sphk#
3850565Sphk# The following directories are scanned.  Each sucessive directory overrides
3951198Sphk# (is merged into) the previous one.
4051215Sphk#
4151215Sphk#	/conf/base		universal base
4251215Sphk#	/conf/default		modified by a secondary universal base
4351215Sphk#	/conf/${ipba}		modified based on the assigned broadcast IP
4451215Sphk#	/conf/${ip}		modified based on the machine's assigned IP
4551215Sphk#
4651215Sphk# Each of these directories may contain any number of subdirectories which
4750565Sphk# represent directories in / on the diskless machine.  The existance of
4850565Sphk# these subdirectories causes this script to create a MEMORY FILESYSTEM for
4953437Sjkh# /<sub_directory_name>.  For example, if /conf/base/etc exists then a
5053437Sjkh# memory filesystem will be created for /etc.
5151243Sphk#
5251198Sphk# If a subdirectory contains the file 'diskless_remount' the contents of
5350565Sphk# the file is used to remount the subdirectory prior to it being copied to
5450565Sphk# the memory filesystem.  For example, if /conf/base/etc/diskless_remount
5550565Sphk# contains the string 'my.server.com:/etc' then my.server.com:/etc will be
5652917Sphk# mounted in place of the subdirectory.  This allows you to avoid making
5751215Sphk# duplicates of system directories in /conf.
5850565Sphk#
5950565Sphk# If a subdirectory contains the file 'md_size', the contents of the
6050565Sphk# file is used to determine the size of the memory filesystem, in 512
6150728Sphk# byte sectors.  The default is 8192 (4MB).  You only have to specify an
6250728Sphk# md_size if the default doesn't work for you (i.e. if it is too big or
6350728Sphk# too small).  Note that in -current the default is 4096 (2MB).  For
6450728Sphk# example, /conf/base/etc/md_size might contain '16384'.
6550728Sphk#
6650728Sphk# If /conf/<special_dir>/SUBDIR.cpio.gz exists, the file is cpio'd into
6750728Sphk# the specified /SUBDIR (and a memory filesystem is created for /SUBDIR
6850728Sphk# if necessary).
6950728Sphk#
7050728Sphk# If /conf/<special_dir>/SUBDIR.remove exists, the file contains a list
7150728Sphk# of paths which are rm -rf'd relative to /SUBDIR.
7250728Sphk#
7350728Sphk# You will almost universally want to create a /conf/base/etc containing
7450728Sphk# a diskless_remount and possibly an md_size file.  You will then almost
7550728Sphk# universally want to override rc.conf, rc.local, and fstab by creating
7650728Sphk# /conf/default/etc/{rc.conf,rc.local,fstab}.  Your fstab should be sure
7750728Sphk# to mount a /usr... typically an NFS readonly /usr.
7850728Sphk#
7950728Sphk# NOTE!  rc.diskless2 will create /var, /tmp, and /dev.  Those filesystems
8050728Sphk# should not be specified in /conf.  At least not yet.
8150728Sphk
8250728Sphkdlv=`/sbin/sysctl -n vfs.nfs.diskless_valid 2> /dev/null`
8350728Sphk[ ${dlv:=0} -eq 0 ] && exit 0
8450728Sphk
8550728Sphk# chkerr:
8650728Sphk#
8750728Sphk# Routine to check for error
8850728Sphk#
8950728Sphk#	checks error code and drops into shell on failure.
9050728Sphk#	if shell exits, terminates script as well as /etc/rc.
9150728Sphk#
9250728Sphkchkerr() {
9350728Sphk    case $1 in
9450565Sphk    0)
9550565Sphk	;;
9650565Sphk    *)
9750565Sphk	echo "$2 failed: dropping into /bin/sh"
9850565Sphk	/bin/sh
9950565Sphk	# RESUME
10050728Sphk	;;
10150728Sphk    esac
10250728Sphk}
10350728Sphk
10450565Sphk# Create a generic memory disk
10550565Sphk#
10650565Sphkmount_md() {
10750565Sphk    /sbin/mdmfs -i 4096 -s $1 -M md $2
10850565Sphk}
10950565Sphk
11050565Sphk# Create the memory filesystem if it has not already been created
11150728Sphk#
11250565Sphkcreate_md() {
11350728Sphk    if [ "x`eval echo \\$md_created_$1`" = "x" ]; then
11450565Sphk	if [ "x`eval echo \\$md_size_$1`" = "x" ]; then
11550565Sphk	    md_size=4096
11650565Sphk	else
11750728Sphk	    md_size=`eval echo \\$md_size_$1`
11852917Sphk	fi
11952917Sphk	mount_md $md_size /$1
12054815Sphk	/bin/chmod 755 /$1
12154815Sphk	eval md_created_$1=created
12254815Sphk    fi
12352917Sphk}
12452917Sphk
12552917Sphk# DEBUGGING
12651860Sphk#
12751878Ssos# set -v
12851878Ssos
12951826Sphk# Figure out our interface and IP.
13051860Sphk#
13151826Sphkbootp_ifc=""
13251826Sphkbootp_ipa=""
13351826Sphkbootp_ipbca=""
13450728Sphkiflist=`ifconfig -l`
13550728Sphkfor i in ${iflist} ; do
13651826Sphk    set `ifconfig ${i}`
13751826Sphk    while [ $# -ge 1 ] ; do
13851826Sphk        if [ "${bootp_ifc}" = "" -a "$1" = "inet" ] ; then
13950728Sphk            bootp_ifc=${i} ; bootp_ipa=${2} ; shift
14050728Sphk        fi
14152917Sphk        if [ "${bootp_ipbca}" = "" -a "$1" = "broadcast" ] ; then
14250728Sphk            bootp_ipbca=$2; shift
14352917Sphk        fi
14450565Sphk        shift
14550728Sphk    done
14651924Sphk    if [ "${bootp_ifc}" != "" ] ; then
14752917Sphk        break
14852917Sphk    fi
14952917Sphkdone
15052917Sphkecho "Interface ${bootp_ifc} IP-Address ${bootp_ipa} Broadcast ${bootp_ipbca}"
15152917Sphk
15252917Sphk# Resolve templates in /conf/base, /conf/default, /conf/${bootp_ipbca},
15350728Sphk# and /conf/${bootp_ipa}.  For each subdirectory found within these 
15450565Sphk# directories:
15550565Sphk#
15650565Sphk# - calculate memory filesystem sizes.  If the subdirectory (prior to
15750565Sphk#   NFS remounting) contains the file 'md_size', the contents specified
15850565Sphk#   in 512 byte sectors will be used to size the memory filesystem.  Otherwise
15950565Sphk#   8192 sectors (4MB) is used.
16050565Sphk#
16150565Sphk# - handle NFS remounts.  If the subdirectory contains the file
16250565Sphk#   diskless_remount, the contents of the file is NFS mounted over
16350565Sphk#   the directory.  For example /conf/base/etc/diskless_remount
16450565Sphk#   might contain 'myserver:/etc'.  NFS remounts allow you to avoid
16551822Sphk#   having to dup your system directories in /conf.  Your server must
16651826Sphk#   be sure to export those filesystems -alldirs, however.
16751924Sphk#
16851826Sphkfor i in base default ${bootp_ipbca} ${bootp_ipa} ; do
16950565Sphk    for j in /conf/$i/* ; do
17050565Sphk	# memory filesystem size specification
17150565Sphk	#
17250565Sphk	subdir=${j##*/}
17350565Sphk	if [ -d $j -a -f $j/md_size ]; then
17450565Sphk	    eval md_size_$subdir=`cat $j/md_size`
17550565Sphk	fi
17650565Sphk
17750565Sphk	# NFS remount
17850565Sphk	#
17950565Sphk	if [ -d $j -a -f $j/diskless_remount ]; then
18050565Sphk	    nfspt=`/bin/cat $j/diskless_remount`
18151860Sphk	    mount_nfs $nfspt $j
18250565Sphk	    chkerr $? "mount_nfs $nfspt $j"
18350565Sphk	fi
18451860Sphk    done
18551860Sphkdone
18651860Sphk
18750565Sphk# - Create all required MFS filesystems and populate them from
18850565Sphk#   our templates.  Support both a direct template and a dir.cpio.gz
18950565Sphk#   archive.  Support dir.remove files containing a list of relative
19050565Sphk#   paths to remove.
19150565Sphk#
19250565Sphk# TODO:
19350565Sphk#   + find a way to assign a 'group' identifier to a machine
19450565Sphk#	so we can use group-specific configurations;
19550565Sphk
19655763Sphkfor i in base default ${bootp_ipbca} ${bootp_ipa} ; do
19750565Sphk    for j in /conf/$i/* ; do
19850565Sphk	subdir=${j##*/}
19950565Sphk	if [ -d $j ]; then
20050565Sphk	    create_md $subdir
20151215Sphk	    cp -Rp $j/* /$subdir
20250565Sphk	fi
20350565Sphk    done
20450565Sphk    for j in /conf/$i/*.cpio.gz ; do
20550565Sphk	subdir=${j%*.cpio.gz}
20650565Sphk	subdir=${subdir##*/}
20750565Sphk	if [ -f $j ]; then
20850565Sphk	    create_md $subdir
20950565Sphk	    echo "Loading /$subdir from cpio archive $j"
21050565Sphk	    (cd / ; /stand/gzip -d < $j | /stand/cpio --extract -d )
21150565Sphk	fi
21250565Sphk    done
21350565Sphk    for j in /conf/$i/*.remove ; do
21450565Sphk	subdir=${j%*.remove}
21551215Sphk	subdir=${subdir##*/}
21650565Sphk	if [ -f $j ]; then
21750565Sphk	    # doubly sure it is a memory disk before rm -rf'ing
21850565Sphk	    create_md $subdir
21950565Sphk	    (cd /$subdir; rm -rf `/bin/cat $j`)
22050565Sphk	fi
22150565Sphk    done
22250565Sphkdone
22350728Sphk
22450565Sphk