New installer backend

News and Announcements related to GhostBSD
Post Reply
kraileth
Posts: 312
Joined: Sun Sep 04, 2016 12:30 pm

New installer backend

Post by kraileth »

Lately, we've more than once been talking about pc-sysinstall which GhostBSD uses as the installer backend. I intended to take a closer look at it and see if I can get GELI installation to work. However nobody seems to be really fond of this program and there were thoughts about replacing it some day. I took a brief look at it and I can understand where the wish to get rid of it comes from: It's just overly complex for us. We simply don't need a lot of the features it has.

So I decided to try to write a simple replacement that would not try to feature creep. It's only a start but after one day of work, I thought that I should probably share it early so others can comment on it. It's also shell based but I decided against "copying the good parts" and for rewriting an installer from scratch. Well, it bears the name "installer", but to be honest, it does currently not do any installations. On the contrary - I started out with destroying existing installations. Sure thing: The cleanest solution is definitely to spill /dev/zero all over the drive. But people probably don't want to wait that long.

The only functionality that it currently has is to wipe a drive clean of previous installations. I successfully wiped installations with old BSD-style disklables in "dangerously dedicated" mode as well as ordinary MBR installations. I then tried to create some crazy partitioning combinations and it all worked out well. I also implemented wiping away extended MBR containers and successfully cleaned a Linux test installation from my drive (this being the first time this year that I installed Linux on real hardware - and it lasted only minutes :P).

Handling GPT (and corrupted GPT), too, is next. Currently the installer does not know about ZFS, GELI, gmirror or any other GEOM classes. Those need to be handled as well. And then it has to be tested against OpenBSD, NetBSD, DragonFly, Illumos - and Windows. The newest Windows version that I own being XP, I hope that somebody steps up to test that for me. If not I'll have to see if I can get Win7 or something from a friend.

Once that works, the focus will shift from destroying partitions to creating and populating them with filesystems. And then the actual installation. But I think properly destroying things is interesting enough for now! :mrgreen:

Here's the very first "write only" version of the code (no license, no refactoring/polishing whatsoever - I just wrote it and added to it when needed):

Code: Select all

#!/bin/sh

###################
 # INTERNAL VARS #
###################

# !Do not change!
MYNAME=${0}
HAVE_LOG=0
RECURSIVE=0

#############
 # GLOBALS #
#############

TMP_DIR="/tmp/.gbi"
LOG_FILE="/tmp/.gbi/installer.log"
CFG_FILE="./gbsd.cfg"
VERBOSITY=1								# 0 = quiet, 1 = info, 2 = debug
LOGGING=0

###############
 # FUNCTIONS #
###############

show_help() {
  echo -e "\nUsage: ${MYNAME} COMMAND [FLAGS]\n"
  echo -e "COMMANDS:\n"
  echo "help         Display this help text"
  echo "wipe         Wipe disk of existing installation(s)"
  echo -e "\nFLAGS:\n"
  echo "-l           Enable logging"
  echo "-q           Quiet mode (no output)"
  echo -e "-v           Be verbose (use twice for debug level verbosity)\n"
}

die() {
  echo -e "\n${1}\n"
  [ ${HAVE_LOG} -eq 1 ] && echo -e "\n${1}\n" >> ${LOG_FILE}
  exit 1
}

print_msg() {
  echo -e "${1}"
  [ ${HAVE_LOG} -eq 1 ] && echo -e "${1}" >> ${LOG_FILE}
}

check_arg_count_valid() {
  [ ${1} -lt 1 ] && die "ERROR: No arguments given!\nUse \"${MYNAME} help\" for help."
  [ ${1} -gt 4 ] && die "ERROR: Too many arguments given!\nUse \"${MYNAME} help\" for help."
}

check_cmd_valid() {
  case ${1} in
    "wipe"|"WIPE")
    ;;
    *)
    die "ERROR: Unknown command \"${1}\"!\nUse \"${MYNAME} help\" for help."
    ;;
  esac
}

parse_args() {
  [ ${1} == "-l" -o ${1} == "-L" ] && LOGGING=1 && return
  if [ ${1} == "-q" -o ${1} == "-Q" ] ; then
    [ ${VERBOSITY} -eq 1 ] && VERBOSITY=0 && return
    die "ERROR: Cannot be verbose and quiet at the same time!"
  fi
  if [ ${1} == "-v" -o ${1} == "-V" ] ; then
    [ ${VERBOSITY} -eq 0 ] && VERBOSITY=1 && return
    [ ${VERBOSITY} -eq 1 ] && VERBOSITY=2
    return
  fi
  die "ERROR: Unknown argument \"${1}\"!\nUse \"${MYNAME} help\" for help."
}

prepare_tmp_dir() {
  mkdir -p ${TMP_DIR}
  [ -d ${TMP_DIR} ] && return
  die "ERROR: Could not create directory \"${TMP_DIR}\"! Aborting..."
}

prepare_log() {
  echo -n > ${LOG_FILE}
  [ -f ${LOG_FILE} -a ! -s ${LOG_FILE} ] && HAVE_LOG=1 && return
  die "ERROR: Logging requested but cannot write to logfile \"${LOG_FILE}\"! Aborting..."
}

check_priv() {
  [ ${VERBOSITY} -gt 1 ] && print_msg "DEBUG: Checking for sufficient privileges..."
  [ `id -u` -eq 0 ] && return
  die "ERROR: Root privileges needed! Cannot run as user \"`id -un`\". Aborting..."
}

check_exists_cfg_file() {
  [ ${VERBOSITY} -gt 1 ] && print_msg "DEBUG: Checking if config file exists..."
  [ -f ${CFG_FILE} ] && return
  die "ERROR: Config file (\"${CFG_FILE}\") not found! Aborting..."
}

check_vars_set() {
  [ ${VERBOSITY} -gt 1 ] && print_msg "DEBUG: Check if all needed cfg variables are set..."
  [ -z ${disk} ] && die "ERROR: \"disk\" not set in ${CFG_FILE}! Aborting..."
}

check_exists_disk() {
  [ ${VERBOSITY} -gt 1 ] && print_msg "DEBUG: Check if disk \"${disk}\" exists..."
  for _DRIVE in `sysctl -n kern.disks` ; do
    [ ${disk} == ${_DRIVE} ] && return
  done
  die "ERROR: Disk \"${disk}\" does not exist! Aborting..."
}

scan_partition_table() {
  if [ `gpart show ${1} 2>&1 | head -n 1 | grep -c "No such geom:"` -gt 0 ] ; then
    PARTITION_TYPE="None"
    [ ${VERBOSITY} -gt 1 ] && print_msg "DEBUG: Disk ${1} seems to not be partitioned."
    return
  fi
  
  PARTITION_TYPE="`gpart show ${1} | head -n 1 | cut -d"(" -f1 | rev | cut -c3- | cut -d" " -f1 | rev`"
  
  case ${PARTITION_TYPE} in
    "BSD")
    [ ${VERBOSITY} -gt 1 ] && print_msg "DEBUG: Disk ${1} has a BSD partition scheme."
    ;;
    "EBR")
    [ ${VERBOSITY} -gt 1 ] && print_msg "DEBUG: Disk ${1} is an extended MBR container."
    ;;
    "GPT")
    [ ${VERBOSITY} -gt 1 ] && print_msg "DEBUG: Disk ${1} has a GPT partition scheme."
    ;;
    "MBR")
    [ ${VERBOSITY} -gt 1 ] && print_msg "DEBUG: Disk ${1} has an MBR partition scheme."
    ;;
    *)
    die "ERROR: Unknown partition scheme \"${PARTITION_TYPE}\" found on ${1}! Cowardly aborting now..."
    ;;
  esac
}

backup_partition_table() {
  gpart backup ${1} > ${TMP_DIR}/partition_table.${1}
  [ -f ${TMP_DIR}/partition_table.${1} ] || die "ERROR: Backing up existing partition table failed!"
  [ ${VERBOSITY} -gt 1 -a ${HAVE_LOG} -gt 0 ] && echo -e "----------\n${1}\n" >> ${LOG_FILE} && cat ${TMP_DIR}/partition_table.${1} >> ${LOG_FILE} && echo "----------" >> ${LOG_FILE}
}

delete_partition() {
  [ ${VERBOSITY} -gt 0 ] && print_msg "INFO: Deleting partition/slice #${2} on ${1}..."
  gpart delete -i ${2} ${1} > /dev/null 2>&1
  [ ${?} -eq 0 ] && return
  die "ERROR: Failed to delete partition #${2} on ${1}!\n\nYou may want to restore the partition table backup e.g. by executing:\n\n  cat ${TMP_DIR}/partition_table.${1} | gpart restore -F ${1}\n\nAnd don't forget that you might need to restore the bootcode, too!"
}

destroy_disklabel() {
  if [ ${_TMP} -gt 1 ] ; then 		# at least one partition present (-gt is correct!)
    for n in `seq 2 ${_TMP}` ; do
      delete_partition ${1} `sed -n ${n}p ${TMP_DIR}/partition_table.${1} | cut -d" " -f1`
    done
  fi

  [ ${VERBOSITY} -gt 0 ] && print_msg "INFO: Destroying disklabel on ${1}..."
  gpart destroy ${1} > /dev/null 2>&1
  [ ${?} -eq 0 ] || die "ERROR: Could not destroy BSD disklabel ${1}! Aborting..."
}

destroy_ebr() {
  if [ ${_TMP} -gt 1 ]; then        # at least one partition present (-gt is correct!)
    for n in `seq 2 ${_TMP}` ; do
      delete_partition ${1} `sed -n ${n}p ${TMP_DIR}/partition_table.${1} | cut -d" " -f1`
    done
  fi

  [ ${VERBOSITY} -gt 0 ] && print_msg "INFO: Destroying extended MBR container on ${1}..."
  gpart destroy ${1} > /dev/null 2>&1
  [ ${?} -eq 0 ] || die "ERROR: Could not destroy EBR container ${1}! Aborting..."
}

destroy_mbr() {
  if [ ${_TMP} -gt 1 ] ; then       # at least one partition present (-gt is correct!)
    for n in `seq 2 ${_TMP}` ; do
      _LABEL_INSIDE_MBR="${1}s`sed -n ${n}p ${TMP_DIR}/partition_table.${1} | cut -d" " -f1`"
      scan_partition_table ${_LABEL_INSIDE_MBR}
      [ ${PARTITION_TYPE} != "None" ] && backup_partition_table ${_LABEL_INSIDE_MBR}
      [ ${PARTITION_TYPE} != "None" ] && delete_partitions ${_LABEL_INSIDE_MBR}
      scan_partition_table ${1}
    done
  fi

  _TMP="`cat ${TMP_DIR}/partition_table.${1} | wc -l`" # lines = partitions + 1
  for n in `seq 2 ${_TMP}` ; do
    delete_partition ${1} `sed -n ${n}p ${TMP_DIR}/partition_table.${1} | cut -d" " -f1`
  done

  [ ${VERBOSITY} -gt 0 ] && print_msg "INFO: Destroying MBR on ${1}..."
  gpart destroy ${1} > /dev/null 2>&1
  [ ${?} -eq 0 ] || die "ERROR: Could not destroy MBR on ${1}! Aborting..."
}

delete_partitions() {
  _TMP="`cat ${TMP_DIR}/partition_table.${1} | wc -l`" # lines = partitions + 1
  [ ${VERBOSITY} -gt 1 ] && print_msg "DEBUG: `echo ${_TMP} | xargs expr -- -1 +` ${PARTITION_TYPE} partition(s) found on ${1}."
  
  case ${PARTITION_TYPE} in
    "BSD")
      destroy_disklabel ${1}
    ;;
    "EBR")
    ;;
    "MBR")
      destroy_mbr ${1}
    ;;
    *)
      die "Not yet supported!"
    ;;
  esac
}

nuke_disk() {
  scan_partition_table ${disk}
  [ ${PARTITION_TYPE} == "None" -a ${VERBOSITY} -gt 1 ] && print_msg "INFO: ${disk} not partitioned." && return
  [ ${PARTITION_TYPE} != "None" ] && backup_partition_table ${disk}
  [ ${PARTITION_TYPE} != "None" ] && delete_partitions ${disk}
}

##########
 # MAIN #
##########

echo
check_arg_count_valid ${#}
[ ${1} == "help" -o ${1} == "HELP" ] && show_help && exit 0
check_cmd_valid ${1}
[ ${#} -gt 1 ] && parse_args ${2}
[ ${#} -gt 2 ] && parse_args ${3}
[ ${#} -gt 3 ] && parse_args ${4}
prepare_tmp_dir
[ ${LOGGING} -gt 0 ] && prepare_log

check_priv
check_exists_cfg_file
. ${CFG_FILE}

check_vars_set
check_exists_disk
nuke_disk

echo
User avatar
ericbsd
Developer
Posts: 2052
Joined: Mon Nov 19, 2012 7:54 pm

Re: New installer backend

Post by ericbsd »

Might not be a good idea to start spend lot of time that. Because after 11.1 release and 10.4, intending to change the installer to only install GhostBSD and having user setting and system configuration at the first boot. My plan is not replace pc-sysinstall fork it, remove the junk and fix the problem.
kraileth
Posts: 312
Joined: Sun Sep 04, 2016 12:30 pm

Re: New installer backend

Post by kraileth »

ericbsd wrote:Because after 11.1 release and 10.4, intending to change the installer to only install GhostBSD and having user setting and system configuration at the first boot. My plan is not replace pc-sysinstall fork it, remove the junk and fix the problem.
I agree with the idea to setup users etc on first boot. Configuration is actually something that I want moved out of the installer, too. But things like partitioning choices and filesystems remain to be made before the actual installation. And those are things that I currently try to take care of: A minimal installer that does just what is needed for a clean, fresh install. No updates, no installations to existing filesystems, no configuration of hostname, timezone, etc. In short: No nonesense.

------------

In the current version wiping GPT is now also supported and work on implementing disk preparation has started. A basic check is in place that ensures that if i.e. "part4" is defined, all consecutive variables from "part0" up to "part3" are also defined. Sanity checking of values is what needs to be done next. Then the partitions can be created, formated, mounted and a fstab assembled. The script currently has ~300 lines of code including logging capability, verbosity levels, etc. Some of that could be deleted after "battle testing":

Code: Select all

#!/bin/sh

###################
 # INTERNAL VARS #
###################

# !Do not change!
MYNAME=${0}
HAVE_LOG=0
RECURSIVE=0

#############
 # GLOBALS #
#############

TMP_DIR="/tmp/.gbi"
LOG_FILE="/tmp/.gbi/installer.log"
CFG_FILE="./gbsd.cfg"
VERBOSITY=1								# 0 = quiet, 1 = info, 2 = debug
LOGGING=0

###############
 # FUNCTIONS #
###############

show_help() {
  echo -e "\nUsage: ${MYNAME} COMMAND [FLAGS]\n"
  echo -e "COMMANDS:\n"
  echo "help         Display this help text"
  echo "prepare      Prepare disk for installation"
  echo "wipe         Wipe disk of existing installation(s)"
  echo -e "\nFLAGS:\n"
  echo "-l           Enable logging"
  echo "-q           Quiet mode (no output)"
  echo -e "-v           Be verbose (use twice for debug level verbosity)\n"
}

die() {
  echo -e "\n${1}\n"
  [ ${HAVE_LOG} -eq 1 ] && echo -e "\n${1}\n" >> ${LOG_FILE}
  exit 1
}

print_msg() {
  echo -e "${1}"
  [ ${HAVE_LOG} -eq 1 ] && echo -e "${1}" >> ${LOG_FILE}
}

check_arg_count_valid() {
  [ ${1} -lt 1 ] && die "ERROR: No arguments given!\nUse \"${MYNAME} help\" for help."
  [ ${1} -gt 4 ] && die "ERROR: Too many arguments given!\nUse \"${MYNAME} help\" for help."
}

check_cmd_valid() {
  case ${1} in
    "wipe"|"WIPE")
    ;;
    "prepare"|"PREPARE")
    ;;
    *)
    die "ERROR: Unknown command \"${1}\"!\nUse \"${MYNAME} help\" for help."
    ;;
  esac
}

parse_args() {
  [ ${1} == "-l" -o ${1} == "-L" ] && LOGGING=1 && return
  if [ ${1} == "-q" -o ${1} == "-Q" ] ; then
    [ ${VERBOSITY} -eq 1 ] && VERBOSITY=0 && return
    die "ERROR: Cannot be verbose and quiet at the same time!"
  fi
  if [ ${1} == "-v" -o ${1} == "-V" ] ; then
    [ ${VERBOSITY} -eq 0 ] && VERBOSITY=1 && return
    [ ${VERBOSITY} -eq 1 ] && VERBOSITY=2
    return
  fi
  die "ERROR: Unknown argument \"${1}\"!\nUse \"${MYNAME} help\" for help."
}

prepare_tmp_dir() {
  mkdir -p ${TMP_DIR}
  [ -d ${TMP_DIR} ] && return
  die "ERROR: Could not create directory \"${TMP_DIR}\"! Aborting..."
}

prepare_log() {
  echo -n > ${LOG_FILE}
  [ -f ${LOG_FILE} -a ! -s ${LOG_FILE} ] && HAVE_LOG=1 && return
  die "ERROR: Logging requested but cannot write to logfile \"${LOG_FILE}\"! Aborting..."
}

check_priv() {
  [ ${VERBOSITY} -gt 1 ] && print_msg "DEBUG: Checking for sufficient privileges..."
  [ `id -u` -eq 0 ] && return
  die "ERROR: Root privileges needed! Cannot run as user \"`id -un`\". Aborting..."
}

check_exists_cfg_file() {
  [ ${VERBOSITY} -gt 1 ] && print_msg "DEBUG: Checking if config file exists..."
  [ -f ${CFG_FILE} ] && return
  die "ERROR: Config file (\"${CFG_FILE}\") not found! Aborting..."
}

check_vars_set() {
  [ ${VERBOSITY} -gt 1 ] && print_msg "DEBUG: Check if all needed cfg variables are set..."
  [ -z ${disk} ] && die "ERROR: \"disk\" not set in ${CFG_FILE}! Aborting..."
  [ -z ${part_scheme} ] && die "ERROR: \"part_scheme\" not set in ${CFG_FILE}! Aborting..."
  
  for n in `jot 11 10 0` ; do
    _TMP="`eval echo \"\\${part${n}+set}\"`"
    [ ! -z ${_TMP} ] && _PART_COUNT="${n}" && break
  done
  [ ${VERBOSITY} -gt 1 ] && print_msg "DEBUG: ${_PART_COUNT} partitions defined in cfg"
  
  [ ${_PART_COUNT} -lt 1 ] && die "ERROR: No partitions defined in ${CFG_FILE}! Aborting..."
  for n in `seq 0 ${_PART_COUNT}` ; do
    [ -z `eval echo \\${part${n}}` ] && die "ERROR: \"part${n}\" not set in ${CFG_FILE}! Aborting..."
  done
}

check_exists_disk() {
  [ ${VERBOSITY} -gt 1 ] && print_msg "DEBUG: Check if disk \"${disk}\" exists..."
  for _DRIVE in `sysctl -n kern.disks` ; do
    [ ${disk} == ${_DRIVE} ] && return
  done
  die "ERROR: Disk \"${disk}\" does not exist! Aborting..."
}

check_scheme_valid() {
  case ${part_scheme} in
    "bsd"|"BSD")
    ;;
    "mbr"|"MBR")
    ;;
    "gpt"|"GPT")
    ;;
    *)
      die "ERROR: Invalid partitioning scheme \"${part_scheme}\"! Aborting..."
    ;;
  esac
}

check_partitions_valid() {
  die "Incomplete!!"
}

check_vars_sane() {
  check_exists_disk
  check_scheme_valid
  check_partitions_valid
}

scan_partition_table() {
  if [ `gpart show ${1} 2>&1 | head -n 1 | grep -c "No such geom:"` -gt 0 ] ; then
    PARTITION_TYPE="None"
    [ ${VERBOSITY} -gt 1 ] && print_msg "DEBUG: Disk ${1} seems to not be partitioned."
    return
  fi
  
  PARTITION_TYPE="`gpart show ${1} | head -n 1 | cut -d"(" -f1 | rev | cut -c3- | cut -d" " -f1 | rev`"
  
  case ${PARTITION_TYPE} in
    "BSD")
    [ ${VERBOSITY} -gt 1 ] && print_msg "DEBUG: Disk ${1} has a BSD partition scheme."
    ;;
    "EBR")
    [ ${VERBOSITY} -gt 1 ] && print_msg "DEBUG: Disk ${1} is an extended MBR container."
    ;;
    "GPT")
    [ ${VERBOSITY} -gt 1 ] && print_msg "DEBUG: Disk ${1} has a GPT partition scheme."
    ;;
    "MBR")
    [ ${VERBOSITY} -gt 1 ] && print_msg "DEBUG: Disk ${1} has an MBR partition scheme."
    ;;
    *)
    die "ERROR: Unknown partition scheme \"${PARTITION_TYPE}\" found on ${1}! Cowardly aborting now..."
    ;;
  esac
}

backup_partition_table() {
  gpart backup ${1} > ${TMP_DIR}/partition_table.${1}
  [ -f ${TMP_DIR}/partition_table.${1} ] || die "ERROR: Backing up existing partition table failed!"
  [ ${VERBOSITY} -gt 1 -a ${HAVE_LOG} -gt 0 ] && echo -e "----------\n${1}\n" >> ${LOG_FILE} && cat ${TMP_DIR}/partition_table.${1} >> ${LOG_FILE} && echo "----------" >> ${LOG_FILE}
}

delete_partition() {
  [ ${VERBOSITY} -gt 0 ] && print_msg "INFO: Deleting partition/slice #${2} on ${1}..."
  gpart delete -i ${2} ${1} > /dev/null 2>&1
  [ ${?} -eq 0 ] && return
  die "ERROR: Failed to delete partition #${2} on ${1}!\n\nYou may want to restore the partition table backup e.g. by executing:\n\n  cat ${TMP_DIR}/partition_table.${1} | gpart restore -F ${1}\n\nAnd don't forget that you might need to restore the bootcode, too!"
}

destroy_disklabel() {
  if [ ${_TMP} -gt 1 ] ; then 		# at least one partition present (-gt is correct!)
    for n in `seq 2 ${_TMP}` ; do
      delete_partition ${1} `sed -n ${n}p ${TMP_DIR}/partition_table.${1} | cut -d" " -f1`
    done
  fi

  [ ${VERBOSITY} -gt 0 ] && print_msg "INFO: Destroying disklabel on ${1}..."
  gpart destroy ${1} > /dev/null 2>&1
  [ ${?} -eq 0 ] || die "ERROR: Could not destroy BSD disklabel ${1}! Aborting..."
}

destroy_ebr() {
  # Only destroy the container - FreeBSD does not handle EBR partitions well
  [ ${VERBOSITY} -gt 0 ] && print_msg "INFO: Destroying extended MBR container on ${1}..."
  gpart destroy -F ${1} > /dev/null 2>&1
  [ ${?} -eq 0 ] || die "ERROR: Could not destroy EBR container ${1}! Aborting..."
}

destroy_mbr() {
  if [ ${_TMP} -gt 1 ] ; then       # at least one partition present (-gt is correct!)
    for n in `seq 2 ${_TMP}` ; do
      _LABEL_INSIDE_MBR="${1}s`sed -n ${n}p ${TMP_DIR}/partition_table.${1} | cut -d" " -f1`"
      scan_partition_table ${_LABEL_INSIDE_MBR}
      [ ${PARTITION_TYPE} != "None" ] && backup_partition_table ${_LABEL_INSIDE_MBR}
      [ ${PARTITION_TYPE} != "None" ] && delete_partitions ${_LABEL_INSIDE_MBR}
      scan_partition_table ${1}
    done
  fi

  _TMP="`cat ${TMP_DIR}/partition_table.${1} | wc -l`" # lines = partitions + 1
  for n in `seq 2 ${_TMP}` ; do
    delete_partition ${1} `sed -n ${n}p ${TMP_DIR}/partition_table.${1} | cut -d" " -f1`
  done

  [ ${VERBOSITY} -gt 0 ] && print_msg "INFO: Destroying MBR on ${1}..."
  gpart destroy ${1} > /dev/null 2>&1
  [ ${?} -eq 0 ] || die "ERROR: Could not destroy MBR on ${1}! Aborting..."
}

destroy_gpt() {
  if [ ${_TMP} -gt 1 ] ; then       # at least one partition present (-gt is correct!)
    for n in `seq 2 ${_TMP}` ; do
      delete_partition ${1} `sed -n ${n}p ${TMP_DIR}/partition_table.${1} | cut -d" " -f1`
    done
  fi
  
  [ ${VERBOSITY} -gt 0 ] && print_msg "INFO: Destroying GPT on ${1}..."
  gpart destroy ${1} > /dev/null 2>&1
  [ ${?} -eq 0 ] || die "ERROR: Could not destroy GPT on ${1}! Aborting..."
}

delete_partitions() {
  _TMP="`cat ${TMP_DIR}/partition_table.${1} | wc -l`" # lines = partitions + 1
  [ ${VERBOSITY} -gt 1 ] && print_msg "DEBUG: `echo ${_TMP} | xargs expr -- -1 +` ${PARTITION_TYPE} partition(s) found on ${1}."
  
  case ${PARTITION_TYPE} in
    "BSD")
      destroy_disklabel ${1}
    ;;
    "EBR")
      destroy_ebr ${1}
    ;;
    "MBR")
      destroy_mbr ${1}
    ;;
    "GPT")
      destroy_gpt ${1}
    ;;
    *)
      die "This should not happen!!"
    ;;
  esac
}

create_part_scheme() {
  [ ${VERBOSITY} -gt 0 ] && print_msg "INFO: Creating partitioning scheme \"${part_scheme}\" on ${1}"
  [ ${part_scheme} != "mbr" ] && gpart create -s ${part_scheme} ${1}
  # missing: mbr needs embedded bsd disklabel
  [ ${?} -eq 0 ] || die "ERROR: Could not create scheme \"${part_scheme}\" on ${1}! Aborting..."
}

prepare_disk() {
  scan_partition_table ${disk}
  [ ${PARTITION_TYPE} == "None" ] || die "ERROR: Disk not clean! Use \"wipe\" before \"prepare\". Aborting..."
  create_part_scheme ${disk}
}

nuke_disk() {
  scan_partition_table ${disk}
  [ ${PARTITION_TYPE} == "None" -a ${VERBOSITY} -gt 1 ] && print_msg "INFO: ${disk} not partitioned." && return
  [ ${PARTITION_TYPE} != "None" ] && backup_partition_table ${disk}
  [ ${PARTITION_TYPE} != "None" ] && delete_partitions ${disk}
}

##########
 # MAIN #
##########

echo
check_arg_count_valid ${#}
[ ${1} == "help" -o ${1} == "HELP" ] && show_help && exit 0
check_cmd_valid ${1}
[ ${#} -gt 1 ] && parse_args ${2}
[ ${#} -gt 2 ] && parse_args ${3}
[ ${#} -gt 3 ] && parse_args ${4}
prepare_tmp_dir
[ ${LOGGING} -gt 0 ] && prepare_log

check_priv
check_exists_cfg_file
. ${CFG_FILE}

check_vars_set
check_vars_sane

[ ${1} == "prepare" -o ${1} == "PREPARE" ] && prepare_disk
[ ${1} == "wipe" -o ${1} == "WIPE" ] && nuke_disk
echo
Post Reply