1#!/bin/sh
2#-
3# Copyright (c) 2010 iXsystems, Inc.  All rights reserved.
4#
5# Redistribution and use in source and binary forms, with or without
6# modification, are permitted provided that the following conditions
7# are met:
8# 1. Redistributions of source code must retain the above copyright
9#    notice, this list of conditions and the following disclaimer.
10# 2. Redistributions in binary form must reproduce the above copyright
11#    notice, this list of conditions and the following disclaimer in the
12#    documentation and/or other materials provided with the distribution.
13#
14# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24# SUCH DAMAGE.
25#
26# $FreeBSD: releng/10.3/usr.sbin/pc-sysinstall/backend/functions-bsdlabel.sh 247735 2013-03-03 23:07:27Z jpaetzel $
27
28# Functions related to disk operations using bsdlabel
29
30# Check if we are are provided a geli password on the nextline of the config
31check_for_enc_pass()
32{
33  CURLINE="${1}"
34 
35  get_next_cfg_line "${CFGF}" "${CURLINE}" 
36  echo ${VAL} | grep -q "^encpass=" 2>/dev/null
37  if [ $? -eq 0 ] ; then
38    # Found a password, return it
39    get_value_from_string "${VAL}"
40    return
41  fi
42
43  export VAL=""
44  return
45};
46
47# On check on the disk-label line if we have any extra vars for this device
48get_fs_line_xvars()
49{
50  ACTIVEDEV="${1}"
51  LINE="${2}"
52
53  echo $LINE | cut -d ' ' -f 4 | grep -q '(' 2>/dev/null
54  if [ $? -ne 0 ] ; then return ; fi
55
56  # See if we are looking for ZFS specific options
57  echo $LINE | grep -q '^ZFS' 2>/dev/null
58  if [ $? -eq 0 ] ; then
59    ZTYPE="NONE"
60    ZFSVARS="`echo $LINE | cut -d ' ' -f 4-20 |cut -d '(' -f 2- | cut -d ')' -f 1 | xargs`"
61
62    echo $ZFSVARS | grep -qE "^(disk|file|mirror|raidz(1|2|3)?|spare|log|cache):" 2>/dev/null
63    if [ $? -eq 0 ] ; then
64       ZTYPE=`echo $ZFSVARS | cut -f1 -d:`
65       tmpVars=`echo $ZFSVARS | sed "s|$ZTYPE: ||g" | sed "s|$ZTYPE:||g"`
66       ZFSVARS=""
67       # make sure we have a '/dev' in front of the extra devices
68       for i in $tmpVars
69       do
70          echo $i | grep -q '/dev/'
71          if [ $? -ne 0 ] ; then
72             ZFSVARS="$ZFSVARS /dev/${i}"
73          else
74             ZFSVARS="$ZFSVARS $i"
75          fi
76       done
77    fi
78
79    # Return the ZFS options
80    if [ "${ZTYPE}" = "NONE" ] ; then
81      VAR="${ACTIVEDEV} ${ZFSVARS}"
82    else
83      VAR="${ZTYPE} ${ACTIVEDEV} ${ZFSVARS}"
84    fi
85    export VAR
86    return
87  fi # End of ZFS block
88
89  # See if we are looking for UFS specific newfs options
90  echo $LINE | grep -q '^UFS' 2>/dev/null
91  if [ $? -eq 0 ] ; then
92    FSVARS="`echo $LINE | cut -d '(' -f 2- | cut -d ')' -f 1 | xargs`"
93    VAR="${FSVARS}"
94    export VAR
95    return
96  fi
97
98  # If we got here, set VAR to empty and export
99  export VAR=""
100  return
101};
102
103# Init each zfs mirror disk with a boot sector so we can failover
104setup_zfs_mirror_parts()
105{
106  _nZFS=""
107
108  ZTYPE="`echo ${1} | awk '{print $1}'`"
109
110  # Using mirroring, setup boot partitions on each disk
111  _mirrline="`echo ${1} | sed 's|mirror ||g' | sed 's|raidz1 ||g' | sed 's|raidz2 ||g' | sed 's|raidz3 ||g' | sed 's|raidz ||g'`"
112  for _zvars in $_mirrline
113  do
114    echo "Looping through _zvars: $_zvars" >>${LOGOUT}
115    echo "$_zvars" | grep -q "${2}" 2>/dev/null
116    if [ $? -eq 0 ] ; then continue ; fi
117    if [ -z "$_zvars" ] ; then continue ; fi
118
119    is_disk "$_zvars" >/dev/null 2>/dev/null
120    if [ $? -eq 0 ] ; then
121      echo "Setting up ZFS disk $_zvars" >>${LOGOUT}
122      init_gpt_full_disk "$_zvars" >/dev/null 2>/dev/null
123      rc_halt "gpart add -a 4k -t freebsd-zfs ${_zvars}" >/dev/null 2>/dev/null
124      rc_halt "gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 ${_zvars}" >/dev/null 2>/dev/null
125      _nZFS="$_nZFS ${_zvars}p2"	
126    else
127      _nZFS="$_nZFS ${_zvars}"	
128    fi	
129  done
130  echo "$ZTYPE $2 `echo $_nZFS | tr -s ' '`"
131} ;
132
133# Function which creates a unique label name for the specified mount
134gen_glabel_name()
135{
136  MOUNT="$1"
137  TYPE="$2"
138  NUM="0"
139  MAXNUM="20"
140
141  if [ "$TYPE" = "ZFS" ] ; then
142    NAME="zpool"
143  elif [ "$MOUNT" = "/" ] ; then
144    NAME="rootfs"
145  else
146    # If doing a swap partition, also rename it
147    if [ "${TYPE}" = "SWAP" ]
148    then
149      NAME="swap"
150    else
151      NAME="`echo $MOUNT | sed 's|/||g' | sed 's| ||g'`"
152    fi
153  fi
154
155  # Loop through and break when we find our first available label
156  while
157  Z=1
158  do
159    glabel status | grep -q "${NAME}${NUM}" 2>/dev/null
160    if [ $? -ne 0 ]
161    then
162      break
163    else
164        NUM=$((NUM+1))
165    fi
166
167    if [ $NUM -gt $MAXNUM ]
168    then
169      exit_err "Cannot allocate additional glabel name for $NAME"
170      break
171    fi
172  done 
173   
174
175  export VAL="${NAME}${NUM}" 
176};
177
178# Function to determine the size we can safely use when 0 is specified
179get_autosize()
180{
181  # Disk tag to look for
182  dTag="$1"
183
184  # Total MB Avail
185  get_disk_mediasize_mb "$2"
186  local _aSize=$VAL
187
188  while read line
189  do
190    # Check for data on this slice
191    echo $line | grep -q "^${_dTag}-part=" 2>/dev/null
192    if [ $? -ne 0 ] ; then continue ; fi
193
194    get_value_from_string "${line}"
195    STRING="$VAL"
196
197    # Get the size of this partition
198    SIZE=`echo $STRING | tr -s '\t' ' ' | cut -d ' ' -f 2` 
199    if [ $SIZE -eq 0 ] ; then continue ; fi
200    _aSize=`expr $_aSize - $SIZE`
201  done <${CFGF}
202
203  # Pad the size a bit
204  _aSize=`expr $_aSize - 2`
205
206  VAL="$_aSize"
207  export VAL
208};
209
210# Function to setup partitions using gpart
211setup_gpart_partitions()
212{
213  local _dTag="$1"
214  local _pDisk="$2"
215  local _wSlice="$3"
216  local _sNum="$4"
217  local _pType="$5"
218  FOUNDPARTS="1"
219  USEDAUTOSIZE=0
220
221  # Lets read in the config file now and setup our partitions
222  if [ "${_pType}" = "gpt" ] ; then
223    CURPART="2"
224  elif [ "${_pType}" = "apm" ] ; then
225    CURPART="3"
226  else
227    PARTLETTER="a"
228    CURPART="1"
229    if [ "${_pType}" = "mbr" ] ; then
230      rc_halt "gpart create -s BSD ${_wSlice}"
231    fi
232  fi
233
234  while read line
235  do
236    # Check for data on this slice
237    echo $line | grep -q "^${_dTag}-part=" 2>/dev/null
238    if [ $? -eq 0 ]
239    then
240      FOUNDPARTS="0"
241      # Found a slice- entry, lets get the slice info
242      get_value_from_string "${line}"
243      STRING="$VAL"
244
245      # We need to split up the string now, and pick out the variables
246      FS=`echo $STRING | tr -s '\t' ' ' | cut -d ' ' -f 1` 
247      SIZE=`echo $STRING | tr -s '\t' ' ' | cut -d ' ' -f 2` 
248      MNT=`echo $STRING | tr -s '\t' ' ' | cut -d ' ' -f 3` 
249
250      # Check if we have a .eli extension on this FS
251      echo ${FS} | grep -q ".eli" 2>/dev/null
252      if [ $? -eq 0 ]
253      then
254        FS="`echo ${FS} | cut -d '.' -f 1`"
255        ENC="ON"
256        check_for_enc_pass "${line}"
257        if [ "${VAL}" != "" ] ; then
258          # We have a user supplied password, save it for later
259          ENCPASS="${VAL}" 
260        fi
261      else
262        ENC="OFF"
263      fi
264
265      # Check if the user tried to setup / as an encrypted partition
266      check_for_mount "${MNT}" "/"
267      if [ $? -eq 0 -a "${ENC}" = "ON" ]
268      then
269        export USINGENCROOT="0"
270      fi
271          
272      # Now check that these values are sane
273      case $FS in
274        UFS|UFS+S|UFS+J|UFS+SUJ|ZFS|SWAP) ;;
275       *) exit_err "ERROR: Invalid file system specified on $line" ;;
276      esac
277
278      # Check that we have a valid size number
279      expr $SIZE + 1 >/dev/null 2>/dev/null
280      if [ $? -ne 0 ]; then
281        exit_err "ERROR: The size specified on $line is invalid"
282      fi
283
284      # Check that the mount-point starts with /
285      echo "$MNT" | grep -qe "^/" -e "^none" 2>/dev/null
286      if [ $? -ne 0 ]; then
287        exit_err "ERROR: The mount-point specified on $line is invalid"
288      fi
289
290      if [ "$SIZE" = "0" ]
291      then
292	if [ $USEDAUTOSIZE -eq 1 ] ; then
293          exit_err "ERROR: You can not have two partitions with a size of 0 specified!"
294	fi
295        case ${_pType} in
296	  gpt|apm) get_autosize "${_dTag}" "$_pDisk" ;;
297	        *) get_autosize "${_dTag}" "$_wSlice" ;;
298        esac
299        SOUT="-s ${VAL}M"
300	USEDAUTOSIZE=1
301      else
302        SOUT="-s ${SIZE}M"
303      fi
304
305      # Check if we found a valid root partition
306      check_for_mount "${MNT}" "/"
307      if [ $? -eq 0 ] ; then
308        export FOUNDROOT="1"
309        if [ "${CURPART}" = "2" -a "$_pType" = "gpt" ] ; then
310          export FOUNDROOT="0"
311        fi
312        if [ "${CURPART}" = "3" -a "$_pType" = "apm" ] ; then
313          export FOUNDROOT="0"
314        fi
315        if [ "${CURPART}" = "1" -a "$_pType" = "mbr" ] ; then
316          export FOUNDROOT="0"
317        fi
318        if [ "${CURPART}" = "1" -a "$_pType" = "gptslice" ] ; then
319          export FOUNDROOT="0"
320        fi
321      fi
322
323      check_for_mount "${MNT}" "/boot"
324      if [ $? -eq 0 ] ; then
325        export USINGBOOTPART="0"
326        if [ "${CURPART}" != "2" -a "${_pType}" = "gpt" ] ; then
327            exit_err "/boot partition must be first partition"
328        fi
329        if [ "${CURPART}" != "3" -a "${_pType}" = "apm" ] ; then
330            exit_err "/boot partition must be first partition"
331        fi
332        if [ "${CURPART}" != "1" -a "${_pType}" = "mbr" ] ; then
333            exit_err "/boot partition must be first partition"
334        fi
335        if [ "${CURPART}" != "1" -a "${_pType}" = "gptslice" ] ; then
336            exit_err "/boot partition must be first partition"
337        fi
338
339        if [ "${FS}" != "UFS" -a "${FS}" != "UFS+S" -a "${FS}" != "UFS+J" -a "${FS}" != "UFS+SUJ" ] ; then
340          exit_err "/boot partition must be formatted with UFS"
341        fi
342      fi
343
344      # Generate a unique label name for this mount
345      gen_glabel_name "${MNT}" "${FS}"
346      PLABEL="${VAL}"
347
348      # Get any extra options for this fs / line
349      if [ "${_pType}" = "gpt" ] ; then
350        get_fs_line_xvars "${_pDisk}p${CURPART}" "${STRING}"
351      elif [ "${_pType}" = "apm" ] ; then
352        get_fs_line_xvars "${_pDisk}s${CURPART}" "${STRING}"
353      else
354        get_fs_line_xvars "${_wSlice}${PARTLETTER}" "${STRING}"
355      fi
356      XTRAOPTS="$VAR"
357
358      # Check if using zfs mirror
359      echo ${XTRAOPTS} | grep -q -e "mirror" -e "raidz"
360      if [ $? -eq 0 -a "$FS" = "ZFS" ] ; then
361        if [ "${_pType}" = "gpt" -o "${_pType}" = "gptslice" ] ; then
362       	  XTRAOPTS=$(setup_zfs_mirror_parts "$XTRAOPTS" "${_pDisk}p${CURPART}")
363        elif [ "${_pType}" = "apm" ] ; then
364       	  XTRAOPTS=$(setup_zfs_mirror_parts "$XTRAOPTS" "${_pDisk}s${CURPART}")
365        else
366       	  XTRAOPTS=$(setup_zfs_mirror_parts "$XTRAOPTS" "${_wSlice}${PARTLETTER}")
367        fi
368      fi
369
370      # Figure out the gpart type to use
371      case ${FS} in
372        ZFS) PARTYPE="freebsd-zfs" ;;
373        SWAP) PARTYPE="freebsd-swap" ;;
374        *) PARTYPE="freebsd-ufs" ;;
375      esac
376
377      # Create the partition
378      if [ "${_pType}" = "gpt" ] ; then
379	if [ "$CURPART" = "2" ] ; then
380	  # If this is GPT, make sure first partition is aligned to 4k
381          sleep 2
382          rc_halt "gpart add -a 4k ${SOUT} -t ${PARTYPE} ${_pDisk}"
383	else
384          sleep 2
385          rc_halt "gpart add ${SOUT} -t ${PARTYPE} ${_pDisk}"
386	fi
387      elif [ "${_pType}" = "gptslice" ]; then
388        sleep 2
389        rc_halt "gpart add ${SOUT} -t ${PARTYPE} ${_wSlice}"
390      elif [ "${_pType}" = "apm" ]; then
391        sleep 2
392        rc_halt "gpart add ${SOUT} -t ${PARTYPE} ${_pDisk}"
393      else
394        sleep 2
395        rc_halt "gpart add ${SOUT} -t ${PARTYPE} -i ${CURPART} ${_wSlice}"
396      fi
397
398      # Check if this is a root / boot partition, and stamp the right loader
399      for TESTMNT in `echo ${MNT} | sed 's|,| |g'`
400      do
401        if [ "${TESTMNT}" = "/" -a -z "${BOOTTYPE}" ] ; then
402           BOOTTYPE="${PARTYPE}" 
403        fi 
404        if [ "${TESTMNT}" = "/boot" ]  ; then
405           BOOTTYPE="${PARTYPE}" 
406        fi 
407      done 
408
409      # Save this data to our partition config dir
410      if [ "${_pType}" = "gpt" ] ; then
411	_dFile="`echo $_pDisk | sed 's|/|-|g'`"
412        echo "${FS}#${MNT}#${ENC}#${PLABEL}#GPT#${XTRAOPTS}" >${PARTDIR}/${_dFile}p${CURPART}
413
414        # Clear out any headers
415        sleep 2
416        dd if=/dev/zero of=${_pDisk}p${CURPART} count=2048 2>/dev/null
417
418        # If we have a enc password, save it as well
419        if [ -n "${ENCPASS}" ] ; then
420          echo "${ENCPASS}" >${PARTDIR}-enc/${_dFile}p${CURPART}-encpass
421        fi
422      elif [ "${_pType}" = "apm" ] ; then
423	_dFile="`echo $_pDisk | sed 's|/|-|g'`"
424        echo "${FS}#${MNT}#${ENC}#${PLABEL}#GPT#${XTRAOPTS}" >${PARTDIR}/${_dFile}s${CURPART}
425
426        # Clear out any headers
427        sleep 2
428        dd if=/dev/zero of=${_pDisk}s${CURPART} count=2048 2>/dev/null
429
430        # If we have a enc password, save it as well
431        if [ -n "${ENCPASS}" ] ; then
432          echo "${ENCPASS}" >${PARTDIR}-enc/${_dFile}s${CURPART}-encpass
433        fi
434      else
435	# MBR Partition or GPT slice
436	_dFile="`echo $_wSlice | sed 's|/|-|g'`"
437        echo "${FS}#${MNT}#${ENC}#${PLABEL}#MBR#${XTRAOPTS}#${IMAGE}" >${PARTDIR}/${_dFile}${PARTLETTER}
438        # Clear out any headers
439        sleep 2
440        dd if=/dev/zero of=${_wSlice}${PARTLETTER} count=2048 2>/dev/null
441
442        # If we have a enc password, save it as well
443        if [ -n "${ENCPASS}" ] ; then
444          echo "${ENCPASS}" >${PARTDIR}-enc/${_dFile}${PARTLETTER}-encpass
445        fi
446      fi
447
448
449      # Increment our parts counter
450      if [ "$_pType" = "gpt" -o "$_pType" = "apm" ] ; then 
451          CURPART=$((CURPART+1))
452        # If this is a gpt/apm partition, 
453        # we can continue and skip the MBR part letter stuff
454        continue
455      else
456          CURPART=$((CURPART+1))
457        if [ "$CURPART" = "3" ] ; then CURPART="4" ; fi
458      fi
459
460
461      # This partition letter is used, get the next one
462      case ${PARTLETTER} in
463        a) PARTLETTER="b" ;;
464        b) PARTLETTER="d" ;;
465        d) PARTLETTER="e" ;;
466        e) PARTLETTER="f" ;;
467        f) PARTLETTER="g" ;;
468        g) PARTLETTER="h" ;;
469        h) PARTLETTER="ERR" ;;
470        *) exit_err "ERROR: bsdlabel only supports up to letter h for partitions." ;;
471      esac
472
473    fi # End of subsection locating a slice in config
474
475    echo $line | grep -q "^commitDiskLabel" 2>/dev/null
476    if [ $? -eq 0 -a "${FOUNDPARTS}" = "0" ]
477    then
478
479      # If this is the boot disk, stamp the right gptboot
480      if [ ! -z "${BOOTTYPE}" -a "$_pType" = "gpt" ] ; then
481        case ${BOOTTYPE} in
482          freebsd-ufs) rc_halt "gpart bootcode -p /boot/gptboot -i 1 ${_pDisk}" ;;
483          freebsd-zfs) rc_halt "gpart bootcode -p /boot/gptzfsboot -i 1 ${_pDisk}" ;;
484        esac 
485      fi
486
487      # Make sure to stamp the MBR loader
488      if [ "$_pType" = "mbr" ] ; then
489	rc_halt "gpart bootcode -b /boot/boot ${_wSlice}"
490      fi
491
492      # Found our flag to commit this label setup, check that we found at least 1 partition
493      if [ "${CURPART}" = "1" ] ; then
494        exit_err "ERROR: commitDiskLabel was called without any partition entries for it!"
495      fi
496
497      break
498    fi
499  done <${CFGF}
500};
501
502# Reads through the config and sets up a BSDLabel for the given slice
503populate_disk_label()
504{
505  if [ -z "${1}" ]
506  then
507    exit_err "ERROR: populate_disk_label() called without argument!"
508  fi
509
510  # Set some vars from the given working slice
511  diskid="`echo $1 | cut -d ':' -f 1`" 
512  disk="`echo $1 | cut -d ':' -f 1 | sed 's|-|/|g'`" 
513  slicenum="`echo $1 | cut -d ':' -f 2`" 
514  type="`echo $1 | cut -d ':' -f 3`" 
515  
516  # Set WRKSLICE based upon format we are using
517  if [ "$type" = "mbr" ] ; then
518    wrkslice="${diskid}s${slicenum}"
519  fi
520  if [ "$type" = "apm" ] ; then
521    wrkslice="${diskid}s${slicenum}"
522  fi
523  if [ "$type" = "gpt" -o "$type" = "gptslice" ] ; then
524    wrkslice="${diskid}p${slicenum}"
525  fi
526
527  if [ ! -e "${SLICECFGDIR}/${wrkslice}" ] ; then
528    exit_err "ERROR: Missing SLICETAG data. This shouldn't happen - please let the developers know"
529  fi
530
531  disktag="`cat ${SLICECFGDIR}/${wrkslice}`"
532  slicedev="`echo $wrkslice | sed 's|-|/|g'`"
533  
534  # Setup the partitions with gpart
535  setup_gpart_partitions "${disktag}" "${disk}" "${slicedev}" "${slicenum}" "${type}"
536
537};
538
539# Function which reads in the disk slice config, and performs it
540setup_disk_label()
541{
542  # We are ready to start setting up the label, lets read the config and do the actions
543  # First confirm that we have a valid WORKINGSLICES
544  if [ -z "${WORKINGSLICES}" ]; then
545    exit_err "ERROR: No slices were setup! Please report this to the maintainers"
546  fi
547
548  # Check that the slices we have did indeed get setup and gpart worked
549  for i in $WORKINGSLICES
550  do
551    disk="`echo $i | cut -d '-' -f 1`" 
552    pnum="`echo $i | cut -d '-' -f 2`" 
553    type="`echo $i | cut -d '-' -f 3`" 
554    if [ "$type" = "mbr" -a ! -e "${disk}s${pnum}" ] ; then
555      exit_err "ERROR: The partition ${i} doesn't exist! gpart failure!"
556    fi
557    if [ "$type" = "gpt" -a ! -e "${disk}p${pnum}" ] ; then
558      exit_err "ERROR: The partition ${i} doesn't exist! gpart failure!"
559    fi
560    if [ "$type" = "apm" -a ! -e "${disk}s${pnum}" ] ; then
561      exit_err "ERROR: The partition ${i} doesn't exist! gpart failure!"
562    fi
563    if [ "$type" = "gptslice" -a ! -e "${disk}p${pnum}" ] ; then
564      exit_err "ERROR: The partition ${i} doesn't exist! gpart failure!"
565    fi
566  done
567
568  # Setup some files which we'll be referring to
569  export LABELLIST="${TMPDIR}/workingLabels"
570  rm $LABELLIST >/dev/null 2>/dev/null
571
572  # Set our flag to determine if we've got a valid root partition in this setup
573  export FOUNDROOT="-1"
574
575  # Check if we are using a /boot partition
576  export USINGBOOTPART="1"
577 
578  # Set encryption on root check
579  export USINGENCROOT="1"
580  
581  # Make the tmp directory where we'll store FS info & mount-points
582  rm -rf ${PARTDIR} >/dev/null 2>/dev/null
583  mkdir -p ${PARTDIR} >/dev/null 2>/dev/null
584  rm -rf ${PARTDIR}-enc >/dev/null 2>/dev/null
585  mkdir -p ${PARTDIR}-enc >/dev/null 2>/dev/null
586
587  for i in $WORKINGSLICES
588  do
589    populate_disk_label "${i}"
590  done
591
592  # Check if we made a root partition
593  if [ "$FOUNDROOT" = "-1" ]
594  then
595    exit_err "ERROR: No root (/) partition specified!!"
596  fi
597
598  # Check if we made a root partition
599  if [ "$FOUNDROOT" = "1" -a "${USINGBOOTPART}" != "0" ]
600  then
601    exit_err "ERROR: (/) partition isn't first partition on disk!"
602  fi
603
604  if [ "${USINGENCROOT}" = "0" -a "${USINGBOOTPART}" != "0" ]
605  then
606    exit_err "ERROR: Can't encrypt (/) with no (/boot) partition!"
607  fi
608};
609
610check_fstab_mbr()
611{
612  local SLICE
613  local FSTAB
614
615  if [ -z "$2" ]
616  then
617	return 1
618  fi
619
620  SLICE="$1"
621  FSTAB="$2/etc/fstab"
622
623  if [ -f "${FSTAB}" ]
624  then
625    PARTLETTER=`echo "$SLICE" | sed -E 's|^.+([a-h])$|\1|'`
626
627    cat "${FSTAB}" | awk '{ print $2 }' | grep -qE '^/$' 2>&1
628    if [ $? -eq 0 ]
629    then
630      if [ "${PARTLETTER}" = "a" ]
631      then
632        FOUNDROOT="0"
633      else
634        FOUNDROOT="1"
635      fi
636
637      ROOTIMAGE="1"
638
639      export FOUNDROOT
640      export ROOTIMAGE
641    fi
642
643    cat "${FSTAB}" | awk '{ print $2 }' | grep -qE '^/boot$' 2>&1
644    if [ $? -eq 0 ]
645    then
646      if [ "${PARTLETTER}" = "a" ]
647      then
648        USINGBOOTPART="0"
649      else 
650        exit_err "/boot partition must be first partition"
651      fi 
652      export USINGBOOTPART
653    fi
654
655    return 0
656  fi
657
658  return 1
659};
660
661check_fstab_gpt()
662{
663  local SLICE
664  local FSTAB
665
666  if [ -z "$2" ]
667  then
668	return 1
669  fi
670
671  SLICE="$1"
672  FSTAB="$2/etc/fstab"
673
674  if [ -f "${FSTAB}" ]
675  then
676    PARTNUMBER=`echo "${SLICE}" | sed -E 's|^.+p([0-9]*)$|\1|'`
677
678    cat "${FSTAB}" | awk '{ print $2 }' | grep -qE '^/$' 2>&1
679    if [ $? -eq 0 ]
680    then
681      if [ "${PARTNUMBER}" = "2" ]
682      then
683        FOUNDROOT="0"
684      else
685        FOUNDROOT="1"
686      fi
687
688      ROOTIMAGE="1"
689
690      export FOUNDROOT
691      export ROOTIMAGE
692    fi
693
694    cat "${FSTAB}" | awk '{ print $2 }' | grep -qE '^/boot$' 2>&1
695    if [ $? -eq 0 ]
696    then
697      if [ "${PARTNUMBER}" = "2" ]
698      then
699        USINGBOOTPART="0"
700      else 
701        exit_err "/boot partition must be first partition"
702      fi 
703      export USINGBOOTPART
704    fi
705
706    return 0
707  fi
708
709
710  return 1
711};
712
713check_disk_layout()
714{
715  local SLICES
716  local TYPE
717  local DISK
718  local RES
719  local F
720
721  DISK="$1"
722  TYPE="MBR"
723
724  if [ -z "${DISK}" ]
725  then
726	return 1
727  fi
728
729  SLICES_MBR=`ls /dev/${DISK}s[1-4]*[a-h]* 2>/dev/null`
730  SLICES_GPT=`ls /dev/${DISK}p[0-9]* 2>/dev/null`
731  SLICES_SLICE=`ls /dev/${DISK}[a-h]* 2>/dev/null`
732
733  if [ -n "${SLICES_MBR}" ]
734  then
735    SLICES="${SLICES_MBR}"
736    TYPE="MBR"
737    RES=0
738  fi
739  if [ -n "${SLICES_GPT}" ]
740  then
741    SLICES="${SLICES_GPT}"
742    TYPE="GPT"
743    RES=0
744  fi
745  if [ -n "${SLICES_SLICE}" ]
746  then
747    SLICES="${SLICES_SLICE}"
748    TYPE="MBR"
749    RES=0
750  fi
751  
752  for slice in ${SLICES}
753  do
754    F=1
755    mount ${slice} /mnt 2>/dev/null
756    if [ $? -ne 0 ]
757    then
758      continue
759    fi 
760
761    if [ "${TYPE}" = "MBR" ]
762    then
763	  check_fstab_mbr "${slice}" "/mnt"
764      F="$?"
765
766    elif [ "${TYPE}" = "GPT" ]
767    then
768	  check_fstab_gpt "${slice}" "/mnt"
769      F="$?"
770    fi 
771
772    if [ ${F} -eq 0 ]
773    then
774      umount /mnt
775      break 
776    fi
777
778    umount /mnt
779  done
780
781  return ${RES}
782};
783