1209513Simp#!/bin/sh
2209513Simp#-
3209552Simp# Copyright (c) 2010 iXsystems, Inc.  All rights reserved.
4209513Simp#
5209513Simp# Redistribution and use in source and binary forms, with or without
6209513Simp# modification, are permitted provided that the following conditions
7209513Simp# are met:
8209513Simp# 1. Redistributions of source code must retain the above copyright
9209513Simp#    notice, this list of conditions and the following disclaimer.
10209513Simp# 2. Redistributions in binary form must reproduce the above copyright
11209513Simp#    notice, this list of conditions and the following disclaimer in the
12209513Simp#    documentation and/or other materials provided with the distribution.
13209513Simp#
14209513Simp# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15209513Simp# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16209513Simp# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17209513Simp# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18209513Simp# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19209513Simp# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20209513Simp# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21209513Simp# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22209513Simp# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23209513Simp# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24209513Simp# SUCH DAMAGE.
25209513Simp#
26209513Simp# $FreeBSD$
27209513Simp
28209513Simp# Functions which perform the extraction / installation of system to disk
29209513Simp
30209513Simp. ${BACKEND}/functions-mountoptical.sh
31209513Simp
32209513Simp# Performs the extraction of data to disk from a uzip or tar archive
33209513Simpstart_extract_uzip_tar()
34209513Simp{
35209513Simp  if [ -z "$INSFILE" ]
36209513Simp  then
37209513Simp    exit_err "ERROR: Called extraction with no install file set!"
38209513Simp  fi
39209513Simp
40209513Simp  # Check if we have a .count file, and echo it out for a front-end to use in progress bars
41209513Simp  if [ -e "${INSFILE}.count" ]
42209513Simp  then
43209513Simp    echo "INSTALLCOUNT: `cat ${INSFILE}.count`"
44209513Simp  fi
45209513Simp
46209513Simp  # Check if we are doing an upgrade, and if so use our exclude list
47209513Simp  if [ "${INSTALLMODE}" = "upgrade" ]
48209513Simp  then
49209513Simp   TAROPTS="-X ${PROGDIR}/conf/exclude-from-upgrade"
50209513Simp  else
51209513Simp   TAROPTS=""
52209513Simp  fi
53209513Simp
54209513Simp  echo_log "pc-sysinstall: Starting Extraction"
55209513Simp
56209513Simp  case ${PACKAGETYPE} in
57211730Simp    uzip)
58225657Sjpaetzel      if ! kldstat -v | grep -q "geom_uzip" ; then
59225657Sjpaetzel	exit_err "Kernel module geom_uzip not loaded"
60225657Sjpaetzel      fi
61225657Sjpaetzel
62211730Simp	  # Start by mounting the uzip image
63211730Simp      MDDEVICE=`mdconfig -a -t vnode -o readonly -f ${INSFILE}`
64211730Simp      mkdir -p ${FSMNT}.uzip
65211730Simp      mount -r /dev/${MDDEVICE}.uzip ${FSMNT}.uzip
66220059Sjpaetzel      if [ $? -ne 0 ]
67211730Simp      then
68211730Simp        exit_err "ERROR: Failed mounting the ${INSFILE}"
69211730Simp      fi
70211730Simp      cd ${FSMNT}.uzip
71209513Simp
72211730Simp      # Copy over all the files now!
73211730Simp      tar cvf - . 2>/dev/null | tar -xpv -C ${FSMNT} ${TAROPTS} -f - 2>&1 | tee -a ${FSMNT}/.tar-extract.log
74220059Sjpaetzel      if [ $? -ne 0 ]
75211730Simp      then
76211730Simp        cd /
77214189Simp        echo "TAR failure occurred:" >>${LOGOUT}
78211730Simp        cat ${FSMNT}/.tar-extract.log | grep "tar:" >>${LOGOUT}
79211730Simp        umount ${FSMNT}.uzip
80211730Simp        mdconfig -d -u ${MDDEVICE}
81211730Simp        exit_err "ERROR: Failed extracting the tar image"
82211730Simp      fi
83209513Simp
84211730Simp      # All finished, now lets umount and cleanup
85211730Simp      cd /
86211730Simp      umount ${FSMNT}.uzip
87211730Simp      mdconfig -d -u ${MDDEVICE}
88211730Simp       ;;
89211730Simp    tar)
90211730Simp	  tar -xpv -C ${FSMNT} -f ${INSFILE} ${TAROPTS} >&1 2>&1
91220059Sjpaetzel      if [ $? -ne 0 ]
92211730Simp      then
93211730Simp        exit_err "ERROR: Failed extracting the tar image"
94211730Simp      fi
95211730Simp      ;;
96209513Simp  esac
97209513Simp
98209513Simp  # Check if this was a FTP download and clean it up now
99209513Simp  if [ "${INSTALLMEDIUM}" = "ftp" ]
100209513Simp  then
101209513Simp    echo_log "Cleaning up downloaded archive"
102209513Simp    rm ${INSFILE} 
103209513Simp    rm ${INSFILE}.count >/dev/null 2>/dev/null 
104209513Simp    rm ${INSFILE}.md5 >/dev/null 2>/dev/null
105209513Simp  fi
106209513Simp
107209513Simp  echo_log "pc-sysinstall: Extraction Finished"
108209513Simp
109209513Simp};
110209513Simp
111209513Simp# Performs the extraction of data to disk from a directory with split files
112209513Simpstart_extract_split()
113209513Simp{
114209513Simp  if [ -z "${INSDIR}" ]
115209513Simp  then
116209513Simp    exit_err "ERROR: Called extraction with no install directory set!"
117209513Simp  fi
118209513Simp
119209513Simp  echo_log "pc-sysinstall: Starting Extraction"
120209513Simp
121209513Simp  # Used by install.sh
122209513Simp  DESTDIR="${FSMNT}"
123209513Simp  export DESTDIR
124209513Simp
125209513Simp  HERE=`pwd`
126209513Simp  DIRS=`ls -d ${INSDIR}/*|grep -Ev '(uzip|kernels|src)'`
127209513Simp  for dir in ${DIRS}
128209513Simp  do
129211730Simp    cd "${dir}"
130211730Simp    if [ -f "install.sh" ]
131211730Simp    then
132211730Simp      echo_log "Extracting" `basename ${dir}`
133209513Simp      echo "y" | sh install.sh >/dev/null
134220059Sjpaetzel      if [ $? -ne 0 ]
135209513Simp      then
136209513Simp        exit_err "ERROR: Failed extracting ${dir}"
137209513Simp      fi
138209513Simp    else
139209513Simp      exit_err "ERROR: ${dir}/install.sh does not exist"
140209513Simp    fi
141209513Simp  done
142209513Simp  cd "${HERE}"
143209513Simp  
144209513Simp  KERNELS=`ls -d ${INSDIR}/*|grep kernels`
145209513Simp  cd "${KERNELS}"
146209513Simp  if [ -f "install.sh" ]
147209513Simp  then
148211730Simp    echo_log "Extracting" `basename ${KERNELS}`
149209513Simp    echo "y" | sh install.sh generic >/dev/null
150220059Sjpaetzel    if [ $? -ne 0 ]
151209513Simp    then
152209513Simp      exit_err "ERROR: Failed extracting ${KERNELS}"
153209513Simp    fi
154213650Simp    rm -rf "${FSMNT}/boot/kernel"
155211730Simp    mv "${FSMNT}/boot/GENERIC" "${FSMNT}/boot/kernel"
156209513Simp  else
157209513Simp    exit_err "ERROR: ${KERNELS}/install.sh does not exist"
158209513Simp  fi
159209513Simp  cd "${HERE}"
160209513Simp
161209513Simp  SOURCE=`ls -d ${INSDIR}/*|grep src`
162209513Simp  cd "${SOURCE}"
163209513Simp  if [ -f "install.sh" ]
164209513Simp  then
165211730Simp    echo_log "Extracting" `basename ${SOURCE}`
166209513Simp    echo "y" | sh install.sh all >/dev/null
167220059Sjpaetzel    if [ $? -ne 0 ]
168209513Simp    then
169209513Simp      exit_err "ERROR: Failed extracting ${SOURCE}"
170209513Simp    fi
171209513Simp  else
172209513Simp    exit_err "ERROR: ${SOURCE}/install.sh does not exist"
173209513Simp  fi
174209513Simp  cd "${HERE}"
175209513Simp
176209513Simp  echo_log "pc-sysinstall: Extraction Finished"
177209513Simp};
178209513Simp
179209513Simp# Function which will attempt to fetch the install file before we start
180209513Simp# the install
181209513Simpfetch_install_file()
182209513Simp{
183209513Simp  get_value_from_cfg ftpPath
184209513Simp  if [ -z "$VAL" ]
185209513Simp  then
186209513Simp    exit_err "ERROR: Install medium was set to ftp, but no ftpPath was provided!" 
187209513Simp  fi
188209513Simp
189209513Simp  FTPPATH="${VAL}"
190209513Simp  
191209513Simp  # Check if we have a /usr partition to save the download
192209513Simp  if [ -d "${FSMNT}/usr" ]
193209513Simp  then
194209513Simp    OUTFILE="${FSMNT}/usr/.fetch-${INSFILE}"
195209513Simp  else
196209513Simp    OUTFILE="${FSMNT}/.fetch-${INSFILE}"
197209513Simp  fi
198209513Simp
199209513Simp  # Do the fetch of the archive now
200209513Simp  fetch_file "${FTPPATH}/${INSFILE}" "${OUTFILE}" "1"
201209513Simp
202209513Simp  # Check to see if there is a .count file for this install
203209513Simp  fetch_file "${FTPPATH}/${INSFILE}.count" "${OUTFILE}.count" "0"
204209513Simp
205209513Simp  # Check to see if there is a .md5 file for this install
206209513Simp  fetch_file "${FTPPATH}/${INSFILE}.md5" "${OUTFILE}.md5" "0"
207209513Simp
208209513Simp  # Done fetching, now reset the INSFILE to our downloaded archived
209220059Sjpaetzel  export INSFILE="${OUTFILE}"
210209513Simp
211209513Simp};
212209513Simp
213211486Simp# Function which will download freebsd install files
214211486Simpfetch_split_files()
215211486Simp{
216211730Simp  get_ftpHost
217211486Simp  if [ -z "$VAL" ]
218211486Simp  then
219211486Simp    exit_err "ERROR: Install medium was set to ftp, but no ftpHost was provided!" 
220211486Simp  fi
221211486Simp  FTPHOST="${VAL}"
222211486Simp
223211730Simp  get_ftpDir
224211486Simp  if [ -z "$VAL" ]
225211486Simp  then
226211486Simp    exit_err "ERROR: Install medium was set to ftp, but no ftpDir was provided!" 
227211486Simp  fi
228211486Simp  FTPDIR="${VAL}"
229211486Simp
230211486Simp  # Check if we have a /usr partition to save the download
231211486Simp  if [ -d "${FSMNT}/usr" ]
232211486Simp  then
233211486Simp    OUTFILE="${FSMNT}/usr/.fetch-${INSFILE}"
234211486Simp  else
235211486Simp    OUTFILE="${FSMNT}/.fetch-${INSFILE}"
236211486Simp  fi
237211486Simp
238211730Simp  DIRS="base catpages dict doc games info manpages proflibs kernels src"
239211730Simp  if [ "${FBSD_ARCH}" = "amd64" ]
240211730Simp  then
241211730Simp    DIRS="${DIRS} lib32"
242211730Simp  fi
243211730Simp
244211730Simp  for d in ${DIRS}
245211730Simp  do
246211730Simp    mkdir -p "${OUTFILE}/${d}"
247211730Simp  done
248211730Simp
249211730Simp
250211486Simp  NETRC="${OUTFILE}/.netrc"
251220059Sjpaetzel  cat <<EOF >"${NETRC}"
252211486Simpmachine ${FTPHOST}
253211486Simplogin anonymous
254211486Simppassword anonymous
255211486Simpmacdef INSTALL
256211486Simpbin
257211486Simpprompt
258211486SimpEOF
259211486Simp
260211486Simp  for d in ${DIRS}
261211486Simp  do
262220059Sjpaetzel    cat <<EOF >>"${NETRC}"
263211486Simpcd ${FTPDIR}/${d}
264211486Simplcd ${OUTFILE}/${d}
265211486Simpmreget *
266211486SimpEOF
267211486Simp  done
268211486Simp
269220059Sjpaetzel  cat <<EOF >>"${NETRC}"
270211486Simpbye
271211486Simp
272211486Simp
273211486SimpEOF
274211486Simp
275211487Simp  # Fetch the files via ftp
276211487Simp  echo "$ INSTALL" | ftp -N "${NETRC}" "${FTPHOST}"
277211486Simp
278211486Simp  # Done fetching, now reset the INSFILE to our downloaded archived
279220059Sjpaetzel  export INSFILE="${OUTFILE}"
280211486Simp}
281211486Simp
282214189Simp# Function which does the rsync download from the server specified in cfg
283209513Simpstart_rsync_copy()
284209513Simp{
285209513Simp  # Load our rsync config values
286209513Simp  get_value_from_cfg rsyncPath
287209513Simp  if [ -z "${VAL}" ]; then
288209513Simp    exit_err "ERROR: rsyncPath is unset! Please check your config and try again."
289209513Simp  fi
290220059Sjpaetzel  export RSYNCPATH="${VAL}"
291209513Simp
292209513Simp  get_value_from_cfg rsyncHost
293209513Simp  if [  -z "${VAL}" ]; then
294209513Simp    exit_err "ERROR: rsyncHost is unset! Please check your config and try again."
295209513Simp  fi
296220059Sjpaetzel  export RSYNCHOST="${VAL}"
297209513Simp
298209513Simp  get_value_from_cfg rsyncUser
299209513Simp  if [ -z "${VAL}" ]; then
300209513Simp    exit_err "ERROR: rsyncUser is unset! Please check your config and try again."
301209513Simp  fi
302220059Sjpaetzel  export RSYNCUSER="${VAL}"
303209513Simp
304209513Simp  get_value_from_cfg rsyncPort
305209513Simp  if [ -z "${VAL}" ]; then
306209513Simp    exit_err "ERROR: rsyncPort is unset! Please check your config and try again."
307209513Simp  fi
308220059Sjpaetzel  export RSYNCPORT="${VAL}"
309209513Simp
310220059Sjpaetzel  COUNT=1
311209513Simp  while
312209513Simp  z=1
313209513Simp  do
314209513Simp    if [ ${COUNT} -gt ${RSYNCTRIES} ]
315209513Simp    then
316209513Simp     exit_err "ERROR: Failed rsync command!"
317209513Simp     break
318209513Simp    fi
319209513Simp
320209513Simp    rsync -avvzHsR \
321209513Simp    --rsync-path="rsync --fake-super" \
322209513Simp    -e "ssh -p ${RSYNCPORT}" \
323209513Simp    ${RSYNCUSER}@${RSYNCHOST}:${RSYNCPATH}/./ ${FSMNT}
324220059Sjpaetzel    if [ $? -ne 0 ]
325209513Simp    then
326209513Simp      echo "Rsync failed! Tries: ${COUNT}"
327209513Simp    else
328209513Simp      break
329209513Simp    fi
330209513Simp
331220059Sjpaetzel    COUNT=$((COUNT+1))
332209513Simp  done 
333209513Simp
334209513Simp};
335209513Simp
336213650Simpstart_image_install()
337213650Simp{
338213650Simp  if [ -z "${IMAGE_FILE}" ]
339213650Simp  then
340213650Simp    exit_err "ERROR: installMedium set to image but no image file specified!"
341213650Simp  fi
342209513Simp
343213650Simp  # We are ready to start mounting, lets read the config and do it
344213650Simp  while read line
345213650Simp  do
346220059Sjpaetzel    echo $line | grep -q "^disk0=" 2>/dev/null
347220059Sjpaetzel    if [ $? -eq 0 ]
348213650Simp    then
349213650Simp      # Found a disk= entry, lets get the disk we are working on
350213650Simp      get_value_from_string "${line}"
351213650Simp      strip_white_space "$VAL"
352213650Simp      DISK="$VAL"
353213650Simp    fi
354213650Simp
355220059Sjpaetzel    echo $line | grep -q "^commitDiskPart" 2>/dev/null
356220059Sjpaetzel    if [ $? -eq 0 ]
357213650Simp    then
358213650Simp      # Found our flag to commit this disk setup / lets do sanity check and do it
359220059Sjpaetzel      if [ -n "${DISK}" ]
360213650Simp      then
361213650Simp
362213650Simp        # Write the image
363213650Simp        write_image "${IMAGE_FILE}" "${DISK}"
364213650Simp
365213650Simp        # Increment our disk counter to look for next disk and unset
366213650Simp        unset DISK
367213650Simp        break
368213650Simp
369213650Simp      else
370213650Simp        exit_err "ERROR: commitDiskPart was called without procceding disk<num>= and partition= entries!!!"
371213650Simp      fi
372213650Simp    fi
373213650Simp
374213650Simp  done <${CFGF}
375213650Simp};
376213650Simp
377209513Simp# Entrance function, which starts the installation process
378209513Simpinit_extraction()
379209513Simp{
380209513Simp  # Figure out what file we are using to install from via the config
381209513Simp  get_value_from_cfg installFile
382209513Simp
383220059Sjpaetzel  if [ -n "${VAL}" ]
384209513Simp  then
385220059Sjpaetzel    export INSFILE="${VAL}"
386209513Simp  else
387209513Simp    # If no installFile specified, try our defaults
388209513Simp    if [ "$INSTALLTYPE" = "FreeBSD" ]
389209513Simp    then
390209513Simp      case $PACKAGETYPE in
391211730Simp        uzip) INSFILE="${FBSD_UZIP_FILE}" ;;
392211730Simp        tar) INSFILE="${FBSD_TAR_FILE}" ;;
393211730Simp        split)
394211730Simp          INSDIR="${FBSD_BRANCH_DIR}"
395209513Simp
396211730Simp          # This is to trick opt_mount into not failing
397211730Simp          INSFILE="${INSDIR}"
398211730Simp          ;;
399209513Simp      esac
400209513Simp    else
401209513Simp      case $PACKAGETYPE in
402211730Simp        uzip) INSFILE="${UZIP_FILE}" ;;
403211730Simp        tar) INSFILE="${TAR_FILE}" ;;
404209513Simp      esac
405209513Simp    fi
406209513Simp    export INSFILE
407209513Simp  fi
408209513Simp
409209513Simp  # Lets start by figuring out what medium we are using
410209513Simp  case ${INSTALLMEDIUM} in
411211730Simp    dvd|usb)
412211730Simp      # Lets start by mounting the disk 
413211730Simp      opt_mount 
414220059Sjpaetzel      if [ -n "${INSDIR}" ]
415211730Simp      then
416211730Simp        INSDIR="${CDMNT}/${INSDIR}" ; export INSDIR
417211730Simp	    start_extract_split
418209513Simp
419211730Simp      else
420211730Simp        INSFILE="${CDMNT}/${INSFILE}" ; export INSFILE
421211730Simp        start_extract_uzip_tar
422211730Simp      fi
423211730Simp      ;;
424211486Simp
425212337Simp    ftp)
426211730Simp      if [ "$PACKAGETYPE" = "split" ]
427211730Simp      then
428211730Simp        fetch_split_files
429211730Simp
430211730Simp        INSDIR="${INSFILE}" ; export INSDIR
431211730Simp        start_extract_split
432211730Simp      else
433211730Simp        fetch_install_file
434211730Simp        start_extract_uzip_tar 
435211730Simp      fi
436211730Simp      ;;
437211730Simp
438212337Simp    sftp) ;;
439212337Simp
440212337Simp    rsync) start_rsync_copy ;;
441213650Simp    image) start_image_install ;;
442225657Sjpaetzel    local)
443225657Sjpaetzel      get_value_from_cfg localPath
444225657Sjpaetzel      if [ -z "$VAL" ]
445225657Sjpaetzel      then
446225657Sjpaetzel        exit_err "Install medium was set to local, but no localPath was provided!"
447225657Sjpaetzel      fi
448225657Sjpaetzel      LOCALPATH=$VAL
449225657Sjpaetzel      INSFILE="${LOCALPATH}/${INSFILE}" ; export INSFILE
450225657Sjpaetzel      start_extract_uzip_tar
451225657Sjpaetzel      ;;
452211730Simp    *) exit_err "ERROR: Unknown install medium" ;;
453209513Simp  esac
454209513Simp
455209513Simp};
456