#!/sbin/sh
#
#
# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
# Use is subject to license terms.
#
# Copyright 1992-95 AT&T Global Information Solutions
#
#ident	"@(#)lumkfs.sh	5.16	09/07/28 SMI"
#
# This utility is not for public use; the interface is subject to change 
# without notice.
#
# USAGE:        lumkfs -i <internal_config_file>
# FUNCTION:     makes ABE file systems according to ICF
# INPUT:        Internal Config File
# OUTPUT:
# DEV:          WLH
#
# ALGORITHM:
# 1. Determine bdevice and fstyp of each ABE file system
# 2. Execute mkfs on each file system
#
###############################################################################
#
# Set to disable device in use checking during newfs/mkfs
NOINUSE_CHECK=1; export NOINUSE_CHECK

LU_PROG_FULL_PATH="$0"
LU_PROG_NAME="`basename ${LU_PROG_FULL_PATH}`"; export LU_PROG_NAME

#################################################################################################
# Name:		interruptHandler
# Description:	Handle an armed shell "trap"
# Local Prefix:	<none>
# Arguments:	<none>
# Example:      trap "interruptHandler" 1 2 3 9 15
# Returns:	call script cleanup function with exit code "4"
#################################################################################################

interruptHandler()
{
  # Reset all traps to be ignored so that termination can take place
  # without further interrupts.

  # 1- SIGHUP (hangup).
  # 2- SIGINT (user interrupt).
  # 3- SIGQUIT (user quit).
  # 9- SIGKILL (kill process - can not be caught or ignored :).
  # 15- SIGTERM (software termination request).
  trap "" 1 2 3 9 15

  # Output indication of interrupt processed.
  ${LUPRINTF} -Ilp2 "`gettext 'Interrupted (Signal received): cleaning up...'`"

  # Cause the script to exit.
  exit_script 1
}

#################################################################################################
# Name:		usage
# Description:	output command line usage information; then call exit_script to terminate execution.
# Local Prefix:	<none>
# Arguments:	$1 = exit code for script ("" defaults to "3").
# Example:	usage 3
# Returns:	<none> 
#################################################################################################

usage()
{
  ${LUPRINTF} -p2 "`gettext 'USAGE: %s [-p mountpt] [-s skip-file] -i <internal_config_file> -n <PBE name>'`" "${LU_PROG_NAME}"
  if [ -z "$1" ] ; then
    exit_script 3 
  fi
  exit_script "$1"
}

#################################################################################################
# Name:		exit_script
# Description:	Perform cleanup operations and exit this script.
# Local Prefix:	<none>
# Arguments:	$1 = optional exit value for script ("" or none is = "0")
# Example:      exit_script "0"
# Returns:	<none>
#################################################################################################

exit_script()
{
  # Determine the exit status code.

  retcode="0"
  if [ -n "$1" ] ; then
    retcode="$1"
  fi

  exit "${retcode}"
}

#################################################################################################
# Name:		<main>
# Description:	Main code (outside of any function definitions) - executed at script startup.
# Local Prefix:	<none>
# Arguments:	$0...$n = All arguments specified by user on command line that invoked this script.
#################################################################################################

# Dot the defaults file.

if [ ! -s /etc/default/lu ] ; then
  echo "${LU_PROG_NAME}: ""`gettext 'ERROR: Live Upgrade not installed properly (/etc/default/lu not found).'`"
  exit 1
fi
. /etc/default/lu

LUBIN=${LUBIN:=/usr/lib/lu}

# Dot the Live Upgrade library functions.

if [ ! -s $LUBIN/lulib ] ; then
  echo "${LU_PROG_NAME}: ""`gettext 'ERROR: The Live Upgrade product is not installed properly (${LUBIN}/lulib not found).'`"
  exit 1
fi

. $LUBIN/lulib

# Check for existence and non-zero size of lutab file.

if [ ! -f /etc/lutab -o ! -s /etc/lutab ] ; then
  ${LUPRINTF} -Eelp2 "`gettext 'No BEs are configured on this system.'`"
  exit 1
fi

  ######################################################################################
  ##################### Command line option and argument processing ####################
  ######################################################################################

# Reset all command line parse flags to default values.
flag_i="" # -i n - abe icf file to use.
flag_s="" # -s f - file system skip file (PRIVATE).

# file system skip list file name
FS_SKIP_LIST="" 

while getopts i:n:p:s: c
do
    case $c in
      i) # -i abe_icf_file
	 lulib_cannot_duplicate_option "${flag_i}" "${OPTARG}" "-i"
	 flag_i="${OPTARG}"
	 ICF="${OPTARG}"
	 ;;

      n) # -i pbe name
	 lulib_cannot_duplicate_option "${flag_n}" "${OPTARG}" "-n"
	 flag_n="${OPTARG}"
	 PBE_NAME="${OPTARG}"
	 ;;

      p) # -p f - preserve mount point (PRIVATE).
	 if [ ! -d "$OPTARG" -a "$OPTARG" != "-" ] ; then
	   ${LUPRINTF} -Eelp2 "`gettext 'Argument <%s> to -p option is not a directory.'`" "${OPTARG}"
	   exit_script
	 fi
	 [ -z "${FS_SKIP_LIST}" ] && FS_SKIP_LIST="/tmp/.lukfs.fs_skip_list.$$"
	 ${LUPRINTF} +X -a "${FS_SKIP_LIST}" '%s' "${OPTARG}"
	 ;;

      s) # -s f - file system skip file (PRIVATE).
	 lulib_cannot_duplicate_option "${flag_s}" "${OPTARG}" "-s"
	 ERRMSG="`${LUPRINTF} -c \"${OPTARG}\" 2>&1`"
	 if [ $? -ne 0 ] ; then
	   [ -n "${ERRMSG}" ] && ${LUPRINTF} -elp2 '%s' "${ERRMSG}"
	   ${LUPRINTF} -Eelp2 "`gettext 'Argument <%s> to -s option may not be created or appended to.'`" "${OPTARG}"
	   exit_script 3
	 fi
	 flag_s="${OPTARG}"
	 ;;

      \?) # unknown - option.
	  usage 3
    esac
done
shift `/bin/expr $OPTIND - 1`

# Fixup debug, session log, and error log settings
lulib_fixup_startup_settings

  ######################################################################################
  ############ Validate all command line arguments and options as possible #############
  ######################################################################################

# If any command line arguments provided, exit with error.
if [ "$#" -ne "0" ] ; then
  ${LUPRINTF} -Eelp2 "`gettext 'Command line arguments <%s> not allowed.'`" "$*"
  usage 3
fi

# If -p and -s were used we created our own skip list file; merge them.
if [ -n "$flag_s" ]; then
    if [ -n "$FS_SKIP_LIST" -a "$flag_s" != "$FS_SKIP_LIST" ] ; then
	# append contents of FS_SKIP_LIST file to flag_s file
	$LUPRINTF +X -a "$flag_s" '%R' < "$FS_SKIP_LIST"
    fi
    FS_SKIP_LIST="$flag_s"
fi

# Make sure that an internal configuration file name was specified.

if [ -z "${ICF}" ]; then
  ${LUPRINTF} -Eelp2 "`gettext 'You must use the <-i> option to specify the ICF file of the ABE to make file systems on.'`"
  usage 3
fi

# Validate the ICF file.

lulib_icf_validate "${ICF}"
if [ "$?" -ne "0" ] ; then
  ${LUPRINTF} -Eelp2 "`gettext 'The file <%s> specified by the <-i> option is not a valid ICF file.'`" "${ICF}"
  usage 3
fi

# signal handling for cleanup.
# 1- SIGHUP (hangup)
# 2- SIGINT (user interrupt)
# 3- SIGQUIT (user quit)
# 9- SIGKILL (kill process - can not be caught or ignored :)
# 15- SIGTERM (software termination request)
trap "interruptHandler" 1 2 3 9 15

# if PBE name is not defined - use the current BE
PBE_is_empty=""
if [ "x$PBE_NAME" = "x-" ]; then
	PBE_NAME=`lulib_lucurr`
	PBE_is_empty="yes"
elif [ -z "$PBE_NAME" ] ; then
	PBE_NAME=`lulib_lucurr`
fi
if [ "$?" -ne "0" -o -z "${PBE_NAME}" ] ; then
    ${LUPRINTF} -Eelp2 "`gettext 'Unable to determine the name of the PBE.'`"
    exit_script 1
fi

PBE_ICF="`$LUBIN/lumk_iconf -F \"$PBE_NAME\"`"
if [ "$?" -ne "0" -o -z "${PBE_ICF}" ] ; then
  ${LUPRINTF} -Eelp2 "`gettext 'Unable to determine disk partition configuration information for boot environment <%s>.'`" "${PBE_NAME}"
  exit_script 1
fi

# if ABE root is ZFS then determine whether the file systems need to be
# explicitly created or whether they can be simply cloned
#
#	UFS -> ZFS (explicitly create the file systems)
#	ZFS -> ZFS [same pool] (snapshot/clone existing file systems)
#	ZFS -> ZFS [different pool] (explicitly create the file systems)
#
abe_root_fstyp=`lulib_get_root_fstyp_from_icf $ICF`

if [ "$abe_root_fstyp" = "zfs" ] ; then
	cbe_root_fstyp=`lulib_get_root_fstyp_from_icf $PBE_ICF`

	if [ "$cbe_root_fstyp" = "zfs" ] ; then
		abe_rpn=`lulib_get_root_pool_name_from_icf $ICF`
		cbe_rpn=`lulib_get_root_pool_name_from_icf $PBE_ICF`
		if [ "$cbe_rpn" = "$abe_rpn" -a -z "$PBE_is_empty" ] ; then
			exit_script 0
		fi
	fi
fi

# 1. Determine cdevice and fstyp of each ABE file system and run mkfs

(
SAVEIFS="$IFS"
${LUETCBIN}/ludo filter_shared_and_swap $PBE_ICF $ICF |
while IFS=: read be_name mntpt bdevice fstyp blocks zonename; do

  #    When looking up the mount point, file system type, and block size of
  #    a file system, the ICF file is scanned - its format is:
  #	be_name:mount_point:device_path:fs_type:block_size[:zonename]

  IFS="$SAVEIFS"
	
  if [ -z "$bdevice" -o -z "$fstyp" -o -z "$blocks" -o -z "$mntpt" ]; then
    ${LUPRINTF} -Eelp2 "`gettext 'The ICF file <%s> for the ABE contains invalid contents.'`" "${ICF}"
    exit 1
  fi
 
  if [ "$fstyp" != "zfs" -a ! -b "$bdevice" ]; then
    ${LUPRINTF} -Eelp2 "`gettext 'The device <%s> for mount point <%s> from the ICF file <%s> is not a block device.'`" "${bdevice}" "${mntpt}" "${ICF}"
    exit 1
  fi
  
  cdevice=`echo $bdevice | /bin/sed 's/\/dsk\//\/rdsk\//g'`
  case "$fstyp" in
    ufs) COMMAND="/usr/sbin/newfs $cdevice < /dev/null";;
    vxfs) COMMAND="/usr/sbin/mkfs -F vxfs -o largefiles $cdevice";;
    zfs) COMMAND="/usr/sbin/zfs create -o canmount=noauto -p $bdevice";;
    *) COMMAND="/usr/sbin/mkfs -F $fstyp $cdevice $blocks";;
  esac

  # If this entry is already in the skip fs list file, then skip it
  # Note: we support skip lists for the global zone *only*.
  if [ -n "$FS_SKIP_LIST" -a -s "$FS_SKIP_LIST" -a "$zonename" = "" ] ; then
    while read line ; do
      if [ "${line}" = "${mntpt}" ] ; then
        exit 1
      fi
    done < ${FS_SKIP_LIST}
    if [ $? -eq 1 ] ; then
      ${LUPRINTF} -lp1 "`gettext 'Preserving <%s> file system for <%s> on <%s>.\n'`" "${fstyp}" "${mntpt}" "${bdevice}"
      continue
    fi
  fi

  if [ "$zonename" = "" ]; then
      zonename=global
  fi

  ${LUPRINTF} -lp2D - "`gettext 'Executing file system creation command: <%s>.'`" "$COMMAND"
  ${LUPRINTF} -lp1 \
      "`gettext 'Creating <%s> file system for <%s> in zone <%s> on <%s>.'`" \
      $fstyp $mntpt $zonename $bdevice
  
  ERRMSG="`/sbin/sh -c \"$COMMAND\" 2>&1`"

  if [ $? -ne 0 ]; then
    ${LUPRINTF} -Eelp2 '%s' "${ERRMSG}"
    ${LUPRINTF} -Eelp2 "`gettext 'Unable to create <%s> file system for <%s> \
in zone <%s> on <%s>.'`" $fstyp $mntpt $zonename $bdevice
    exit 1
  fi
  ${LUPRINTF} -lp2D - '%s' "${ERRMSG}"

  if [ "$fstyp" = "zfs" ]; then
    #If the pbe dataset has mountpoint=legacy, set it same for ABE dataset
    pbe_fstyp=`cat $PBE_ICF | /bin/nawk -F: -v MP=$mntpt '$2==MP {print $4}'`
    if [ $pbe_fstyp != "zfs" ] ; then
        continue
    fi
    pbe_dev=`/bin/nawk -F: -v MP=$mntpt '$2==MP {print $3}' < "$PBE_ICF"`
    mountprop=`/sbin/zfs get -Ho value mountpoint "$pbe_dev"`
    if [ $? -ne 0 ] ; then
        ${LUPRINTF} -Eelp2 "`gettext 'Unable get mountpoint property for <%s>'`" \
        "$pbe_dev"
    fi
    if [ $mountprop = "legacy" ] ; then
	/sbin/zfs set mountpoint=legacy "$bdevice"
    fi

  fi

done

#
# if the abe is a ZFS pool ensure that it is configured properly
#
if [ "$abe_root_fstyp" = "zfs" ] ; then
    	# For an empty source BE, we need to generate an etc directory
	root_ds=`awk -F: '$2=="/" {print $3}' < $ICF`
    	if [ -n "$PBE_is_empty" ] ; then
        	tx_mntpt="/tmp/.alt.lumkfs.$$"
        	/sbin/zfs set mountpoint="$tx_mntpt" "$root_ds"
        	/sbin/zfs mount "$root_ds"
        	/bin/mkdir -p "$tx_mntpt/etc"
        	/sbin/zfs umount "$root_ds"
   	fi
	abe_rpn=`lulib_get_root_pool_name_from_icf $ICF`
	lulib_swap_zvol_defined $abe_rpn
	if [ $? -eq 0 ] ; then
		# Create swap zvol
		lulib_create_swap_zvol $PBE_ICF $abe_rpn
	fi
	lulib_dump_zvol_defined $abe_rpn
	if [ $? -eq 0 ] ; then
		# Create dump zvol
		lulib_create_dump_zvol $PBE_NAME $abe_rpn
	fi
	abe_bootfs=`/sbin/zpool get bootfs "$abe_rpn" | tail -1 | awk '{print $3}'`
	if [ "x$abe_bootfs" = "x-" ]; then
		# This is overridden during luactivate; it just needs to
		# be set to *something* here.
		/sbin/zpool set bootfs="$abe_rpn" "$abe_rpn"
	fi
fi

exit 0
)

res="$?"
exit_script $res
