#!/sbin/sh

################################################################################
#
#	Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
#	Use is subject to license terms.
#	Copyright 1992-95 AT&T Global Information Solutions
#
#pragma ident	"@(#)lumake.sh	5.17	05/10/25 SMI"
# 
# USAGE:        lumake [-l error_log] -t time -o outfile -n BE_Name [-m address]
#               lumake [-l error_log] [-o outfile] -n BE_Name
#           Internal interface :
#            lumake [-l error_log] [-u] -t time -o outfile -n BE_Name -i INODE_ICF
#            lumake [-l error_log] [-o outfile] [-u] -n BE_Name -i INODE_ICF
# MODIFICATIONS: added -u option to internal interface. specify -u to skip check
#                if update is complete.
#
# FUNCTION:     driver program to call lumk_iconf, lumkfs, lupop,
#		and lustat_set.
# INPUT:        logfile - file were errors will be logged
#		outfile - messages that are normally displayed on the tty
#			  are redirected to outfile if it is specified.
#		time - Schedule copy to be done at "time" (time is in at(1M)
#			format).
#		BE_Name - ASCII string for BE name (no ':' or '"' allowed)
#
# OUTPUT:
# DEV:          JKJ
#
#
# ALGORITHM:
# Check for "Copy Lock". If it exists, exit with error. 
# Dot in COPYLOCK contents
# verify the all required PBE file systems are mounted
# if '-t' option is specified, validate $TIME
# Call lumk_iconf to produce an ICF. 
# If '-t time' is specified, set up 'at(1)' job, change Copy lock 
#   status to "SCHEDULED", and exit 0
# Set "Copy Lock" to ACTIVE state.
# Mark the ABE as Not Complete.
# Call lumkfs to create file systems.
# Call lupop to populate file systems.
# Call lustat_set to update the BE status in the lutab.
# Remove copy lock.
#
# Note: performance testing has proven that "/sbin/sh" provides the best performance over
# /bin/sh and /bin/ksh.
#
################################################################################

LU_PROG_FULL_PATH="$0"
LU_PROG_NAME="`basename ${LU_PROG_FULL_PATH}`"; export LU_PROG_NAME
TMP_RESULT_FILE="/tmp/.lumake.results.tmp.$$"
FILTER_FILE="/tmp/.lumake.filter_one_.$$"
FS_SKIP_LIST="/tmp/.lumake.fs_skip_list.$$"

################################################################################
# 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 [ -X ] [ -l error_log ] [ -o outfile ] \
-n BE_name [ -t time [ -m email_address ] ]'`" "${LU_PROG_NAME}"
  ${LUPRINTF} -Ip2 "`gettext 'Any BE_name should be enclosed in single quotes.'`"
  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>
################################################################################

err_exit_script()
{
  ${LUPRINTF} -lp2D - "`gettext 'Removing copy lock.'`"
  rm -f $COPYLOCK
  exit_script "$1"
}

exit_script()
{
  # If external interface remove INODE_ICF
  if [ -z "${flag_i}" -a -n "${INODE_ICF}" ] ; then
    /bin/rm -f $INODE_ICF
  fi

  # Remove temporary files and directories
  /bin/rm -f "${TMP_RESULT_FILE}" "${FILTER_FILE}" "${TMP_MENU_LST}"
  /bin/rmdir "${TMP_MENU_MNT}" > /dev/null 2>&1

  # Remove the skip list file
  /bin/rm -f "${FS_SKIP_LIST}"

  # Determine the exit status code.

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

  exit "${retcode}"
}

####  get_ufs_options()
####  {
####    # Not used in Solaris because of no support.
####    UFS_TMP=/tmp/.ufs$$
####    CKYORN=/tmp/.ckyorn.$$
####  
####  	# If ufs compat info is already in the COPYLOCK, just return
####  	if grep "^UFS_COMPAT=" $COPYLOCK >/dev/null 2>&1
####  	then
####  		${LUPRINTF} -lp2D - "`gettext 'UFS_COMPAT has already been set in COPYLOCK.'`"
####  		return 0
####  	fi
####  
####  	if [ ! -s "${ICF}" ]; then
####  		return 1
####  	fi
####  
####  	awk -F: ' ($4 == "ufs") { printf("%s\n", $3) }' ${ICF} >$UFS_TMP
####  
####  	DEVICES=""
####  	for dev in `cat $UFS_TMP`
####  	do
####  	  if [ -n "${flag_Z}" ] ; then
####  		clear 2> /dev/null
####  	  fi
####  		# Get the Recommended Inode count for this file system from
####  		# $INODE_ICF file
####  
####  		mount_point=`nawk -v device=$dev -F: '($3 == device) {print $2}' ${ICF}`
####  		
####  		inode_count=`nawk -v mn_pt=$mount_point -F: '($1 == mn_pt) {print $2}'  $INODE_ICF`
####  
####  		# If inode_count > 64k, there is no point in asking for compat
####  		# or noncompat option for $dev.
####  
####  		[ $inode_count -gt 65536 ] && continue
####  		echo "You have specified that a ufs file system be created on $dev."
####  		ckyorn -Q -d y -p "\
####  Would you like to limit the number of inodes in the file system to a \
####  maximum of 64K to remain compatible with pre-System V Release 4 \
####  applications? " -h "\
####  This information will be used when creating a file system on the \
####  specified device.  See mkfs_ufs(1M) for more details." 2>&1 >$CKYORN
####  
####  		ans=`cat $CKYORN`
####  		rm -f "$CKYORN"
####  		echo
####  
####  		case "$ans" in
####  		y|Y) DEVICES="$dev $DEVICES";;
####  		esac
####  
####  	done
####  
####  	echo "UFS_COMPAT=\"$DEVICES\"" > $TMP_LOCK
####  	rm -f $UFS_TMP
####  	return 0
####  }

################################################################################
# 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

# Default global variables we expect to be set from /etc/default/lu.

LUBIN=${LUBIN:=/usr/lib/lu}
COPYLOCK=${COPYLOCK:=/etc/lu/COPY_LOCK}

# 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

trap "" 1 2 3 15

TIME=""
TIME_CHECK=/tmp/time_check.$$
TMP_LOCK=/etc/lu/tmp/COPY_LOCK.$$
BYPASS_ID="OFF"
ABE_NAME=""
INODE_ICF=""
ICF=""
MAILTO=""
TMP_MENU_LST="/etc/lu/lumake_menu_lst.$$"
TMP_MENU_MNT="/tmp/.lumake.mntpt.1.$$"

# Remove temporary files and directories
/bin/rm -f "${TMP_RESULT_FILE}" "${FILTER_FILE}" "${FS_SKIP_LIST}" "${TMP_MENU_LST}"
/bin/rmdir "${TMP_MENU_MNT}" > /dev/null 2>&1

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

# Reset all command line parse flags to default values.
flag_Z="" # -Z - fmli interface in use.
flag_b=""
flag_i=""
flag_l="" # -l f - log file path.
flag_m=""
flag_n=""
flag_o="" # -o f - output file path.
flag_s=""
flag_t=""
flag_x="" # -x n - set debug level to n (PRIVATE).

while [ $# -ne 0 ] ; do
  while getopts b:Ii:l:m:n:o:p:s:t:x:XZ c ; do
    case $c in
      b) lulib_cannot_duplicate_option "${flag_b}" "${OPTARG}" "-b"
	 flag_b="${OPTARG}"
	 BYPASS_ID=${OPTARG}
	 ;;

      i) # By-pass ID (-b id). Used to ensure two lumakes don't get run at the
	 # same time. But also allows scheduled lumake to run correctly.
	 lulib_cannot_duplicate_option "${flag_i}" "${OPTARG}" "-i"
	 flag_i="${OPTARG}"
	 INODE_ICF="${OPTARG}"
	 ;;

      l) # -l f - error log file path.
	 # This overrides the LU_ERROR_LOG_FILE setting read from /etc/default/lu
	 lulib_cannot_duplicate_option "${flag_l}" "${OPTARG}" "-l"
	 ${LUPRINTF} -lp2D - "`gettext 'Verifying that the error log file <%s> specified can be created and appended to.'`" "${OPTARG}"
	 ERRMSG="`${LUPRINTF} -c \"${OPTARG}\" 2>&1`"
	 if [ "$?" -ne 0 ] ; then
	   [ -n "${ERRMSG}" ] && ${LUPRINTF} -elp2 '%s' "${ERRMSG}"
	   ${LUPRINTF} -Eelp2 "`gettext 'Argument <%s> to -l option may not be created or appended to.'`" "${OPTARG}"
	   exit_script 3
	 fi
	 flag_l="${OPTARG}"
	 lulib_set_error_log_file "${flag_l}"
	 ;;

      m) lulib_cannot_duplicate_option "${flag_m}" "${OPTARG}" "-m"
	 flag_m="${OPTARG}"
	 MAILTO="${OPTARG}"
	 ;;

      n) lulib_cannot_duplicate_option "${flag_n}" "${OPTARG}" "-n"
	 flag_n="${OPTARG}"
	 ABE_NAME=${OPTARG}
	 ABE_OPT="-n \"$ABE_NAME\""
	 ;;

      o) # -o f - output file path.
	 # This overrides the LU_SESSION_LOG_FILE setting read from /etc/default/lu
	 lulib_cannot_duplicate_option "${flag_o}" "${OPTARG}" "-o"
	 ${LUPRINTF} -lp2D -  "`gettext 'Verifying that the session log file <%s> can be created and appended to.'`" "${OPTARG}"
	 ERRMSG="`${LUPRINTF} -c \"${OPTARG}\" 2>&1`"
	 if [ "$?" -ne 0 ] ; then
	   [ -n "${ERRMSG}" ] && ${LUPRINTF} -elp2 '%s' "${ERRMSG}"
	   ${LUPRINTF} -Eelp2 "`gettext 'Argument <%s> to -o option may not be created or appended to.'`" "${OPTARG}"
	   exit_script 3
	 fi
	 flag_o="${OPTARG}"
	 lulib_set_session_log_file "${flag_o}"
	 ;;

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

      s) lulib_cannot_duplicate_option "${flag_s}" "${OPTARG}" "-s"
	 flag_s="${OPTARG}"
	 PBE_NAME=${OPTARG}
	 ;;

      t) lulib_cannot_duplicate_option "${flag_t}" "${OPTARG}" "-t"
	 flag_t="${OPTARG}"
	 TIME="${OPTARG}"
	 ;;

      x) # -x n - set debug level to n (PRIVATE).
	 # This overrides the default setting read from /etc/default/lu
	 lulib_cannot_duplicate_option "${flag_x}" "${OPTARG}" "-x"
	 /bin/test "${OPTARG}" -ge 0 2>/dev/null
	 if [ "$?" -gt 1 ] ; then
	   ${LUPRINTF} -Eelp2 "`gettext 'Argument <%s> to -x option is not a number.'`" "${OPTARG}"
	   usage 3
	 fi
	 flag_x="${OPTARG}"
	 lulib_set_debug "${flag_x}"
	 ;;

      X) # -X - set XML output mode.
	 lulib_set_output_format 'xml'
	 ;;

      Z) # -Z - being run from the FMLI interface.
	 flag_Z="-Z"
	 ;;

      \?) usage 3
	 ;;
    esac
  done

  # Found either end of arguments, +option, or non-option argument; shift out
  # what has been processed so far; if a non-option argument is present
  # capture it and continue processing the command line arguments.
  shift `/bin/expr $OPTIND - 1`
  OPTIND=1
  if [ $# -ne 0 -a "$1" = '+X' ] ; then
      # +X - set TEXT output mode.
      lulib_set_output_format 'text'
      shift
  else
    break
  fi
done

# 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 1
fi

# Must specify a BE to make
lulib_must_have_option "${flag_n}" "" "-n"

# Determine the name of Current BE.
CURR_BE="`lulib_lucurr`"
if [ "$?" -ne "0" ] ; then
  ${LUPRINTF} -Eelp2 "`gettext 'Unable to determine the name of the current active BE.'`"
  err_exit_script 1
fi

# Determine that $ABE_NAME is not the current_be.
if [ "$CURR_BE" = "$ABE_NAME" ] ; then
  ${LUPRINTF} -Eelp2 "`gettext 'The boot environment <%s> is the current BE. You are not allowed to remake the file systems on the current active BE.'`" "${CURR_BE}"
  err_exit_script 1
fi

# check that necessary patches have been applied
lulib_check_patch
if [ "$?" -ne 0 ]; then
  ${LUPRINTF} -Eelp2 "`gettext 'Cannot make the boot environment.'`"
  err_exit_script 1
fi

# If no -s option specified, assume the current BE is the source.
if [ -z "${PBE_NAME}" ] ; then
  PBE_NAME="${CURR_BE}"
fi

### if [ "$TIME" != "" ] ; then
   ###		OUTFILE=/etc/lu/lu.log
   ###		OUT_OPT="-o $OUTFILE"
   ###		if [ "${LU_DEBUG}" -ne "0" ]
   ###		then
   ###			print_warn "The '-o outfile' was not specified"
   ###			print_warn "outfile set to /etc/lu/lu.log"
   ###		fi
   ###	else
   ###		OUTFILE=/dev/null
   ###	fi
### fi

if [ "$TIME" != "" ] ; then
  # if '-t' option is specified, validate $TIME
  $LUBIN/lutime_valid "$TIME"
  if [ "$?" -ne "0" ] ; then
    err_exit_script 1
  fi
fi

# Check for "Copy Lock". If it exists, exit with error. 
# Don't validate_lulock for internal use.
if [ "$INODE_ICF" = "" ] ; then
  lulib_validate_lulock
fi

if [ -f "$COPYLOCK" ] ; then
  # Dot in COPYLOCK contents
  . $COPYLOCK
  if [ "$CL_BYPASS_ID" != "$BYPASS_ID" ] ; then
    ${LUPRINTF} -lp2D - "`gettext 'A Copy Lock file <%s> exists: Status <%s> Source BE <%s> Target BE <%s>.'`" "${COPYLOCK}" "${CL_STATUS}" "${CL_SOURCE_BE}" "${CL_TARGET_BE}"
    ${LUPRINTF} -Eelp2 "`gettext 'Another Live Upgrade process is either running or scheduled...cannot continue.'`"
    exit_script 2
  fi
fi

# Validate the target BE; lulib_is_be_name_inuse returns:
# 0 - the be name is valid and is inuse (used by a BE).
# 1 - the be name is valid and is not inuse (not used by a BE).
# 2 - the be name could not be looked up.
lulib_is_be_name_inuse "${ABE_NAME}"
if [ "$?" -ne "0" ] ; then
  ${LUPRINTF} -Eelp2 "`gettext 'Unable to make file systems for boot environment <%s>.'`" "${ABE_NAME}"
  err_exit_script 1
fi

# The BE must not currently be mounted.
lulib_verify_be_unmounted "${ABE_NAME}"
if [ "$?" -ne "0" ] ; then
  ${LUPRINTF} -Eelp2 "`gettext 'Unable to make file systems for boot environment <%s>.'`" "${ABE_NAME}"
  err_exit_script 1
fi

# Print message to let user know we are working
${LUPRINTF} -lp1 "`gettext 'Creating configuration for boot environment <%s>.'`" "${ABE_NAME}"

# Print message to let user know the Source boot Environment
${LUPRINTF} -lp1 "`gettext 'Source boot environment is <%s>.'`" "${PBE_NAME}"

# Check for existence and non-zero size of lutab file.
if [ ! -f ${LU_LUTAB_FILE} -o ! -s ${LU_LUTAB_FILE} ] ; then
  ${LUPRINTF} -Eelp2 "`gettext 'No boot environments are configured on this system.'`"
  err_exit_script 1
fi

ABE_ID=`${LUETCBIN}/ludo get_be_id "$ABE_NAME"`
if [ "$?" -ne "0" ] ; then
  ${LUPRINTF} -Eelp2 '%s' "${ABE_ID}"
  ${LUPRINTF} -Eelp2 "`gettext 'Unable to make file systems for boot environment <%s>.'`" "${ABE_NAME}"
  err_exit_script 1
fi

ICF=/etc/lu/ICF.$ABE_ID

# Get the status of the ABE
BE_STAT="`${LUETCBIN}/ludo get_be_status_from_be_name \"$ABE_NAME\"`"
if [ "$?" -ne "0" ] ; then
  ${LUPRINTF} -Eelp2 "`gettext 'Unable to determine the target boot environment <%s> configuration.'`" "${ABE_NAME}"
  err_exit_script 1
fi

if [ "$BE_STAT" = "C" ] ; then
  # Create ICF using lumk_iconf
  ${LUPRINTF} -lp2D - "`gettext 'Creating ICF file for boot environment <%s>.'`" "${ABE_NAME}"
  # Obtain the name of the ICF file, forcing recreation so that the
  # current partition sizes for all file systems are determined.
  ICF="`$LUBIN/lumk_iconf -f -F \"$ABE_NAME\"`"
  if [ "$?" -ne "0" ] ; then
    ${LUPRINTF} -Eelp2 "`gettext 'Unable to determine disk partition configuration information for boot environment <%s>.'`" "${ABE_NAME}"
    err_exit_script 2
  fi
  # Call luupdall to copy the ICF file to all defined BEs.
  $LUBIN/luupdall ${ICF} 
  if [ "$?" -ne "0" ] ; then
    ${LUPRINTF} -Eelp2 "`gettext 'Unable to propagate the file <%s> to all boot environments.'`" "${ICF}"
    err_exit_script 2
  fi
else
  # Use the /etc/lu/ICF.{ID} file
  lulib_icf_validate "${ICF}"
  if [ "$?" -ne "0" ] ; then
    ${LUPRINTF} -Eelp2 "`gettext 'The boot environment <%s> is in an incomplete state and the internal configuration file <%s> is not valid.'`" "${ABE_NAME}" "${ICF}"
    err_exit_script 2
  fi
fi

# Make sure the PBE is mounted and that the OS support vxfs-root if the ABE
# file system type is "vxfs"
lulib_validate_be_for_copy "${PBE_NAME}"
if [ "$?" -ne "0" ] ; then 
  ${LUPRINTF} -Eelp2 "`gettext 'The source boot environment <%s> cannot be used to create the target BE <%s>.'`" "${PBE_NAME}" "${ABE_NAME}"
  err_exit_script 2
fi

# Call lucomp_size, if not internal interface (i.e not via lucreate)

if [ -z "${flag_i}" ] ; then
  # Inode file does not exist
  INODE_ICF="/tmp/inode_icf.$$"

  $LUBIN/lucomp_size -p $PBE_NAME -i ${ICF} -O $INODE_ICF -n $ABE_NAME
  if [ "$?" -ne "0" ] ; then
    # Size is not sufficient
    ${LUPRINTF} -Eelp2 "`gettext 'File systems on ABE <%s> have unsufficient space for repopulation from boot environment <%s>. It is recommended to delete this BE and create a fresh BE.'`" "${ABE_NAME}" "${PBE_NAME}"
    err_exit_script 1
  fi
fi

# Call get_ufs_options to ask ufs-specific questions. A variable
# "UFS_COMPAT" will be appended to the COPY_LOCK by get_ufs_options.
# Not used in Solaris because of no support.
#get_ufs_options || err_exit1

# If '-t time' is specified, we need to set up an 'at(1)' job to
# execute lumake at the specified time.

if [ "$TIME" != "" ] ; then
  BYPASS_ID=$$
  ${LUPRINTF} -lp1 "`gettext 'Scheduling the copy.'`"
  if [ "X${MAILTO}" != "X" ] ; then
	/bin/cat <<-EOF | /bin/at -s "$TIME" > /tmp/at.out$$ 2>&1
	  $LUBIN/lumake -b $BYPASS_ID $ABE_OPT 2>&1 >/tmp/lumake.log.$$
	  /bin/mailx -s "Live Upgrade Copy to $ABE_NAME on `uname -n` Completed" "$MAILTO" </tmp/lumake.log.$$
	  rm /tmp/lumake.log.$$
	EOF
  else
	/bin/cat <<-EOF | /bin/at -s -m "$TIME" > /tmp/at.out$$ 2>&1
		$LUBIN/lumake -b $BYPASS_ID $ABE_OPT
	EOF
  fi
  RET=$?
  # This gets the at job number and is flexible enough to handle
  # the out put from at(1) even if the at(1) output changes in
  # the future due to internationalization.
  AT_JOB_NUM=`/bin/awk '{ 
		for (i=0; i <= NF; i++)
		{
			if ( $i == "Job" || $i == "job" )
			{ 
				i++
				print $i 
				exit 0
			}
		}
	}' /tmp/at.out$$`

  /bin/grep INFO /tmp/at.out$$ > /dev/null 2>&1
  if [ "$?" -eq "0" ] ; then
    AT_JOB_TIME=`/bin/grep INFO /tmp/at.out$$ | /bin/cut -d" " -f6-`
  else
    /bin/grep -i job /tmp/at.out$$ > /dev/null 2>&1
    if [ "$?" -eq "0" ] ; then
      AT_JOB_TIME=`/bin/grep job /tmp/at.out$$ | /bin/cut -d" " -f4-`
    else
      AT_JOB_TIME="CANNOT DETERMINE"
    fi
  fi

   ###  if [ "$OUTFILE" != /dev/null -a "$OUTFILE" != "" ] ; then
   ###    cat /tmp/at.out$$ >> $OUTFILE
   ###  fi

  /bin/rm -f /tmp/at.out$$
  if [ $RET = 0 ] ; then
    # Change Copy lock status to "SCHEDULED"
    if [ -f $COPYLOCK ] ; then
      ${LUPRINTF} -lp2D - "`gettext 'Changing Copy Lock status to SCHEDULED.'`"
      /bin/grep -v "^CL_STATUS" $COPYLOCK | \
      /bin/grep -v "^CL_BYPASS_ID" >> $TMP_LOCK
    else
      ${LUPRINTF} -lp2D - "`gettext 'Creating Copy Lock and setting status to SCHEDULED.'`"
      echo "CL_SOURCE_BE=\"$PBE_NAME\"" >> $TMP_LOCK
      echo "CL_TARGET_BE=\"$ABE_NAME\"" >> $TMP_LOCK
      echo "CL_ICF=\"${ICF}\"" >> $TMP_LOCK
    fi
    echo "CL_STATUS=\"SCHEDULED\"" >> $TMP_LOCK
    echo "CL_EXEC_TIME=\"$AT_JOB_TIME\"" >> $TMP_LOCK
    echo "CL_AT_JOB_NUM=\"$AT_JOB_NUM\"" >> $TMP_LOCK
    echo "CL_BYPASS_ID=\"$BYPASS_ID\"" >> $TMP_LOCK
    /bin/mv $TMP_LOCK $COPYLOCK
    exit_script 0
  else
    ${LUPRINTF} -Eelp2 "`gettext 'Attempt to schedule lumake at the specified time <%s> failed.'`" "${TIME}"
    if [ "$BE_STAT" = "C" ] ; then
      # Remove ICF and COPYLOCK
      # DO NOT remove lutab entry or free devices.
      ${LUPRINTF} -lp2D - "`gettext 'Removing configuration file.'`"
      /bin/rm -f ${ICF}
    fi
    err_exit_script 1
  fi
else
  # Set "Copy Lock" to ACTIVE state.
  if [ -f $COPYLOCK ] ; then
    ${LUPRINTF} -lp2D - "`gettext 'Changing Copy Lock status to ACTIVE.'`"
    /bin/grep -v "^CL_STATUS" $COPYLOCK > $TMP_LOCK
  else
    ${LUPRINTF} -lp2D - "`gettext 'Creating Copy Lock and setting status to ACTIVE.'`"
    echo "CL_SOURCE_BE=\"$PBE_NAME\"" > $TMP_LOCK
    echo "CL_TARGET_BE=\"$ABE_NAME\"" >> $TMP_LOCK
    echo "CL_ICF=\"${ICF}\"" >> $TMP_LOCK
  fi
  echo "CL_STATUS=\"ACTIVE\"" >> $TMP_LOCK
  /bin/mv $TMP_LOCK $COPYLOCK
fi

#
# If being run from the FMLI interface, need to inform the user that there
# is no more user interaction that will be required.
#
if [ -n "${flag_Z}" ] ; then
  ${LUPRINTF} -lp1 ''
  ${LUPRINTF} -lp1 '%s' '**********************************************************************'
  ${LUPRINTF} -lp1 ''
  ${LUPRINTF} -lp1 "`gettext 'Beginning process of creating boot environment <%s>.'`" "${ABE_NAME}"
  ${LUPRINTF} -lp1 "`gettext 'No more user interaction is required until this process is complete.'`"
  ${LUPRINTF} -lp1 ''
  ${LUPRINTF} -lp1 '%s' '**********************************************************************'
  ${LUPRINTF} -lp1 ''
else
  ${LUPRINTF} -lp1 "`gettext 'Creating boot environment <%s>.'`" "${ABE_NAME}"
fi

# Mark the ABE as Not Complete.
${LUPRINTF} -lp2D - "Setting boot environmentE <%s> state to Not Complete." "${ABE_NAME}"
$LUBIN/lustat_set -n "$ABE_NAME" -s NC 
if [ "$?" -ne "0" ] ; then
  ${LUPRINTF} -Eelp2 "`gettext 'Unable to update the status of boot environment <%s> in the BE configuration.'`" "${ABE_NAME}"
  err_exit_script 1
fi

#
# On x86 only: Save GRUB menu (if any) that exist on ABE.
# This will be restored once fileystem is populated.
# NOTE: Do this after the ABE has been marked Not Complete
# so we don't try to propagate files to the ABE.
# We checked above that the ABE was not mounted,
# so it is safe to attempt a mount now.
#
/bin/rm -f "${TMP_MENU_LST}"
if [ "${LU_SYSTEM_ARCH}" = i386 ]; then
   ${LUPRINTF} -lp1 "`gettext 'Checking for GRUB menu on boot environment <%s>.'`" "${ABE_NAME}"
   output=`lulib_update_grub_slice`
   if [ "$?" -ne 0 -o -z "$output" ]; then
      ${LUPRINTF} -Eelp2 "`gettext 'Cannot determine GRUB slice.'`"
      err_exit_script 1
   fi

   logslice=`echo $output | cut -d'=' -f 2`
   logfstyp=`echo $output | cut -d'=' -f 3`
   logslice_blk=`echo $output | cut -d'=' -f 6`

   root_slice=`/bin/nawk -F: -v root="/" '{if ($2 == root) {printf("%s\n", $3); exit 10;}}' "$ICF"`
   ret="$?"
   if [ "$ret" -eq 10 -a "$root_slice" = "$logslice_blk" ]; then
      #
      # The ABE we are about to lumake has the GRUB menu. Save the GRUB menu
      #
      /bin/rm -f "${TMP_MENU_LST}"
      /bin/mkdir -p "${TMP_MENU_MNT}"

      /sbin/mount -F "$logfstyp" "$logslice_blk" "${TMP_MENU_MNT}" 2>/dev/null
      #
      # filesystems may not have been created yet. So don't complain if
      # if mount fails
      #
      if [ "$?" -eq 0 ] ; then
         if [ -f "${TMP_MENU_MNT}/${BOOT_MENU}" -a -s "${TMP_MENU_MNT}/${BOOT_MENU}" ]; then
            ${LUPRINTF} -lp1 "`gettext 'Saving GRUB menu on boot environment <%s>.'`" "${ABE_NAME}"
            /bin/cp -p "${TMP_MENU_MNT}/${BOOT_MENU}" "${TMP_MENU_LST}"
         fi

	/sbin/umount "${TMP_MENU_MNT}"
         if [ "$?" -ne 0 ] ; then
            ${LUPRINTF} -Eelp2 "`gettext 'Unable to unmount file system for boot environment <%s>.'`" "${ABE_NAME}"
            err_exit_script 1
         fi
      fi
      /bin/rmdir "${TMP_MENU_MNT}" > /dev/null 2>&1
   else
      ${LUPRINTF} -lp1 "`gettext 'The boot environment <%s> does not contain the GRUB menu.'`" "${ABE_NAME}"
   fi
fi


# Calls lumkfs to create file systems.

${LUPRINTF} -lp1 "`gettext 'Creating file systems on boot environment <%s>.'`" "${ABE_NAME}"
$LUBIN/lumkfs -i ${ICF} -s ${FS_SKIP_LIST}
if [ "$?" -ne "0" ] ; then
  ${LUPRINTF} -Eelp2 "`gettext 'Unable to create all required file systems for boot environment <%s>.'`" "${ABE_NAME}"
  err_exit_script 1
fi
	
# Mount the ABE file systems
${LUPRINTF} -lp1 "`gettext 'Mounting file systems for boot environment <%s>.'`" "${ABE_NAME}"
dest=`LU_OUTPUT_FORMAT=text $LUBIN/lumount -i ${ICF} 2>${TMP_RESULT_FILE}`
if [ "$?" -ne "0" ] ; then
  # About 1 in 1000 async ufs creations will leave the FS state
  # flag in superblock wrong. Do a fsck of the BE to try and fix this.
  [ -s "${TMP_RESULT_FILE}" ] && ${LUPRINTF} -elp2 '%R' < "${TMP_RESULT_FILE}"
  ${LUPRINTF} -Wlp1 "`gettext 'Attempting to correct problems detected with file systems for boot environment <%s>.'`" "${ABE_NAME}"

  $LUBIN/lufsck -i ${ICF}
  dest=`LU_OUTPUT_FORMAT=text $LUBIN/lumount -i ${ICF} 2>${TMP_RESULT_FILE}`
  if [ "$?" -ne "0" -o ! -d "${dest}" ] ; then
    [ -s "${TMP_RESULT_FILE}" ] && ${LUPRINTF} -elp2 '%R' < "${TMP_RESULT_FILE}"
    ${LUPRINTF} -Wlp1 "`gettext 'Unable to correct problems detected with file systems for boot environment <%s>.'`" "${ABE_NAME}"
    err_exit_script 1
  fi
fi

# After making the file system, verify that the ABE file systems
# have sufficient number of inodes.

${LUPRINTF} -lp1 "`gettext 'Calculating required sizes of file systems for boot environment <%s>.'`" "${ABE_NAME}"
errfile=/tmp/.lumake.inode_errs.$$
/bin/rm -f $errfile

/bin/awk -F: '{print $1" " $2}' $INODE_ICF | while read mount_pt inode_num
do
    # Determine the number of inodes that is present on ABE $mount_pt
    # file system.

  if [ "${mount_pt}" != "-" -a "${inode_num}" -gt "0" ] ; then
     tot_inode=`LANG=C LC_ALL=C /bin/df -t "${dest}${mount_pt}" | 
/bin/tail -1 | /bin/awk ' BEGIN {RS="[ \t\n]"}
{ print $4 }'`

     if [ "$tot_inode" -lt "$inode_num" ]
     then
	  /bin/touch $errfile
	  break
     fi
   fi
done

if [ -f "$errfile" ] ; then
  ${LUPRINTF} -Eelp2 "`gettext 'Insufficient number of inodes on the file systems of the boot environment <%s>. It is recommended to delete this BE and create a fresh BE.'`'`" "${ABE_NAME}"
fi

# unmount the ABE file systems
$LUBIN/luumount -f -i ${ICF} 2> /dev/null
if [ "$?" -ne "0" -o -f "$errfile" ] ; then
  /bin/rm -f $errfile
  err_exit_script 1
fi

/bin/rm -f $errfile

# Get filter file from global database.
FILTER_OPTION=""
${LUETCBIN}/ludo get_file_from_xml_db "${LU_DB_GLOBAL}" "${ABE_ID}" 'beFilterFile' \
'beFilterFileItem' > ${FILTER_FILE}
[ $? -eq 0 -a -s "${FILTER_FILE}" ] && FILTER_OPTION="-z ${FILTER_FILE}"

# Get integrity check override from global database.
INTEGRITY_CHECK_OPTION=""
SETTING="`${LUETCBIN}/ludo get_setting_from_xml_db \"${LU_DB_GLOBAL}\" \"${ABE_ID}\" \
'beFilterSpecifications' 'integrityCheck'`"
[ $? -eq 0 -a "${SETTING}" = 'no' ] && INTEGRITY_CHECK_OPTION="-I"

# Calls lupop to populate file systems.
${LUPRINTF} -lp1 "`gettext 'Populating file systems on boot environment <%s>.'`" "${ABE_NAME}"
$LUBIN/lupop -i "${ICF}" -p "${PBE_NAME}" -s ${FS_SKIP_LIST} ${FILTER_OPTION} ${INTEGRITY_CHECK_OPTION}
if [ "$?" -ne "0" ] ; then
  ${LUPRINTF} -Eelp2 "`gettext 'Unable to populate file systems on boot environment <%s>.'`" "${ABE_NAME}"
  err_exit_script 1
fi

# Calls lustat_set to update the BE status in the lutab.
${LUPRINTF} -lp2D - "Setting boot environment <%s> state to Complete." "${ABE_NAME}"
$LUBIN/lustat_set -n "$ABE_NAME" -s C 
if [ "$?" -ne "0" ] ; then
  ${LUPRINTF} -Eelp2 "`gettext 'Unable to update the status of the boot environment <%s> in the BE configuration.'`" "${ABE_NAME}"
  err_exit_script 1
fi

if [ "${LU_SYSTEM_ARCH}" = i386 -a -f "$TMP_MENU_LST" -a -s "$TMP_MENU_LST" ]; then
   ${LUPRINTF} -lp1 "`gettext 'Restoring GRUB menu.'`"
   output=`lulib_update_grub_slice`
   if [ "$?" -ne 0 -o -z "$output" ]; then
      ${LUPRINTF} -Eelp2 "`gettext 'Cannot determine GRUB slice.'`"
      err_exit_script 1
   fi

   logslice=`echo $output | cut -d'=' -f 2`
   logfstyp=`echo $output | cut -d'=' -f 3`
   logslice_blk=`echo $output | cut -d'=' -f 6`

   # Check if GRUB slice is already mounted
   mnted=""
   mntpt=`/sbin/mount | /bin/nawk -v dev="$logslice_blk" ' { if ($3 == dev) {printf("%s\n", $1); exit 7;}}'`
   if [ "$?" -ne 7 ] ; then
      /bin/mkdir -p "${TMP_MENU_MNT}"
      /sbin/mount -F "$logfstyp" "$logslice_blk" "${TMP_MENU_MNT}"
      if [ "$?" -ne 0 ]; then
         ${LUPRINTF} -Eelp2 "`gettext 'Cannot mount GRUB slice <%s>.'`" "$logslice_blk"
         err_exit_script 1
      fi
      mntpt="${TMP_MENU_MNT}"
      mnted=1
   fi

   # The GRUB slice is now mounted
   /bin/mkdir -p "${mntpt}/${BOOT_MENU_DIR}"
   /bin/cp -p "${TMP_MENU_LST}" "${mntpt}/${BOOT_MENU}"

   if [ -n "${mnted}" ]; then
      /sbin/umount "${logslice_blk}" 
      if [ "$?" -ne 0 ] ; then
         ${LUPRINTF} -Eelp2 "`gettext 'Unable to unmount GRUB slice <%s>.'`" "${logslice_blk}"
         err_exit_script 1
      fi
   fi
   /bin/rm -f "${TMP_MENU_LST}"
   /bin/rmdir "${TMP_MENU_MNT}" > /dev/null 2>&1

   ${LUPRINTF} -lp1 "`gettext 'The GRUB menu has been restored on device <%s>.'`" "$logslice_blk"
fi

# Call luupdall to copy the ICF files to all defined BEs.
ICF_FILES=`ls /etc/lu/ICF* 2>/dev/null`
if [ $? -eq 0 ]; then
  $LUBIN/luupdall ${ICF_FILES}
  if [ $? != 0 ] ; then
    ${LUPRINTF} -Eelp2 "`gettext 'Cannot propagate the files <%s> to all BEs.'`" "${ICF_FILES}"
    err_exit_script 1
  fi
fi

#
# Since we have changed the ABE, remove its entries (if any) from the GRUB menu
# Do this after we restore the menu.
#
if [ "${LU_SYSTEM_ARCH}" = i386 ]; then
   lulib_delete_menu_entry "${ABE_NAME}"
   if [ "$?" -ne 0 ] ; then
      ${LUPRINTF} -Eelp2 "`gettext 'Unable to delete GRUB menu entry for boot environment <%s>.'`" "${ABE_NAME}"
      err_exit_script 1
   fi
fi

# Remove copy lock.
/bin/rm -f $COPYLOCK

${LUPRINTF} -lp1 "`gettext 'Population of boot environment <%s> successful.'`" "${ABE_NAME}"

exit_script 0
