]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - usr.sbin/pc-sysinstall/backend/functions-extractimage.sh
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / usr.sbin / pc-sysinstall / backend / functions-extractimage.sh
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$
27
28 # Functions which perform the extraction / installation of system to disk
29
30 . ${BACKEND}/functions-mountoptical.sh
31
32 # Performs the extraction of data to disk from FreeBSD dist files
33 start_extract_dist()
34 {
35   if [ -z "$1" ] ; then exit_err "Called dist extraction with no directory set!"; fi
36   if [ -z "$INSFILE" ]; then exit_err "Called extraction with no install file set!"; fi
37   local DDIR="$1"
38
39   # Check if we are doing an upgrade, and if so use our exclude list
40   if [ "${INSTALLMODE}" = "upgrade" ]; then
41    TAROPTS="-X ${PROGDIR}/conf/exclude-from-upgrade"
42   else
43    TAROPTS=""
44   fi
45
46   # Loop though and extract dist files
47   for di in $INSFILE
48   do
49       # Check the MANIFEST see if we have an archive size / count
50       if [ -e "${DDIR}/MANIFEST" ]; then 
51          count=`grep "^${di}.txz" ${DDIR}/MANIFEST | awk '{print $3}'`
52          if [ ! -z "$count" ] ; then
53             echo "INSTALLCOUNT: $count"
54          fi
55       fi
56       echo_log "pc-sysinstall: Starting Extraction (${di})"
57       tar -xpv -C ${FSMNT} -f ${DDIR}/${di}.txz ${TAROPTS} >&1 2>&1
58       if [ $? -ne 0 ]; then
59         exit_err "ERROR: Failed extracting the dist file: $di"
60       fi
61   done
62
63   # Check if this was a FTP download and clean it up now
64   if [ "${INSTALLMEDIUM}" = "ftp" ]; then
65     echo_log "Cleaning up downloaded archives"
66     rm -rf ${DDIR}
67   fi
68
69   echo_log "pc-sysinstall: Extraction Finished"
70 }
71
72 # Performs the extraction of data to disk from a uzip or tar archive
73 start_extract_uzip_tar()
74 {
75   if [ -z "$INSFILE" ]; then
76     exit_err "ERROR: Called extraction with no install file set!"
77   fi
78
79   # Check if we have a .count file, and echo it out for a front-end to use in progress bars
80   if [ -e "${INSFILE}.count" ]; then
81     echo "INSTALLCOUNT: `cat ${INSFILE}.count`"
82   fi
83
84   # Check if we are doing an upgrade, and if so use our exclude list
85   if [ "${INSTALLMODE}" = "upgrade" ]; then
86    TAROPTS="-X ${PROGDIR}/conf/exclude-from-upgrade"
87   else
88    TAROPTS=""
89   fi
90
91   echo_log "pc-sysinstall: Starting Extraction"
92
93   case ${PACKAGETYPE} in
94     uzip)
95       if ! kldstat -v | grep -q "geom_uzip" ; then
96         exit_err "Kernel module geom_uzip not loaded"
97       fi
98
99           # Start by mounting the uzip image
100       MDDEVICE=`mdconfig -a -t vnode -o readonly -f ${INSFILE}`
101       mkdir -p ${FSMNT}.uzip
102       mount -r /dev/${MDDEVICE}.uzip ${FSMNT}.uzip
103       if [ $? -ne 0 ]
104       then
105         exit_err "ERROR: Failed mounting the ${INSFILE}"
106       fi
107       cd ${FSMNT}.uzip
108
109       # Copy over all the files now!
110       tar cvf - . 2>/dev/null | tar -xpv -C ${FSMNT} ${TAROPTS} -f - 2>&1 | tee -a ${FSMNT}/.tar-extract.log
111       if [ $? -ne 0 ]
112       then
113         cd /
114         echo "TAR failure occurred:" >>${LOGOUT}
115         cat ${FSMNT}/.tar-extract.log | grep "tar:" >>${LOGOUT}
116         umount ${FSMNT}.uzip
117         mdconfig -d -u ${MDDEVICE}
118         exit_err "ERROR: Failed extracting the tar image"
119       fi
120
121       # All finished, now lets umount and cleanup
122       cd /
123       umount ${FSMNT}.uzip
124       mdconfig -d -u ${MDDEVICE}
125        ;;
126     tar)
127       tar -xpv -C ${FSMNT} -f ${INSFILE} ${TAROPTS} >&1 2>&1
128       if [ $? -ne 0 ]; then
129         exit_err "ERROR: Failed extracting the tar image"
130       fi
131       ;;
132   esac
133
134   # Check if this was a FTP download and clean it up now
135   if [ "${INSTALLMEDIUM}" = "ftp" ]
136   then
137     echo_log "Cleaning up downloaded archive"
138     rm ${INSFILE} 
139     rm ${INSFILE}.count >/dev/null 2>/dev/null 
140     rm ${INSFILE}.md5 >/dev/null 2>/dev/null
141   fi
142
143   echo_log "pc-sysinstall: Extraction Finished"
144
145 };
146
147 # Performs the extraction of data to disk from a directory with split files
148 start_extract_split()
149 {
150   if [ -z "${INSDIR}" ]
151   then
152     exit_err "ERROR: Called extraction with no install directory set!"
153   fi
154
155   echo_log "pc-sysinstall: Starting Extraction"
156
157   # Used by install.sh
158   DESTDIR="${FSMNT}"
159   export DESTDIR
160
161   HERE=`pwd`
162   DIRS=`ls -d ${INSDIR}/*|grep -Ev '(uzip|kernels|src)'`
163   for dir in ${DIRS}
164   do
165     cd "${dir}"
166     if [ -f "install.sh" ]
167     then
168       echo_log "Extracting" `basename ${dir}`
169       echo "y" | sh install.sh >/dev/null
170       if [ $? -ne 0 ]
171       then
172         exit_err "ERROR: Failed extracting ${dir}"
173       fi
174     else
175       exit_err "ERROR: ${dir}/install.sh does not exist"
176     fi
177   done
178   cd "${HERE}"
179   
180   KERNELS=`ls -d ${INSDIR}/*|grep kernels`
181   cd "${KERNELS}"
182   if [ -f "install.sh" ]
183   then
184     echo_log "Extracting" `basename ${KERNELS}`
185     echo "y" | sh install.sh generic >/dev/null
186     if [ $? -ne 0 ]
187     then
188       exit_err "ERROR: Failed extracting ${KERNELS}"
189     fi
190     rm -rf "${FSMNT}/boot/kernel"
191     mv "${FSMNT}/boot/GENERIC" "${FSMNT}/boot/kernel"
192   else
193     exit_err "ERROR: ${KERNELS}/install.sh does not exist"
194   fi
195   cd "${HERE}"
196
197   SOURCE=`ls -d ${INSDIR}/*|grep src`
198   cd "${SOURCE}"
199   if [ -f "install.sh" ]
200   then
201     echo_log "Extracting" `basename ${SOURCE}`
202     echo "y" | sh install.sh all >/dev/null
203     if [ $? -ne 0 ]
204     then
205       exit_err "ERROR: Failed extracting ${SOURCE}"
206     fi
207   else
208     exit_err "ERROR: ${SOURCE}/install.sh does not exist"
209   fi
210   cd "${HERE}"
211
212   echo_log "pc-sysinstall: Extraction Finished"
213 };
214
215 # Function which will attempt to fetch the dist file(s) before we start
216 fetch_dist_file()
217 {
218   get_value_from_cfg ftpPath
219   if [ -z "$VAL" ]
220   then
221     exit_err "ERROR: Install medium was set to ftp, but no ftpPath was provided!" 
222   fi
223
224   FTPPATH="${VAL}"
225   
226   # Check if we have a /usr partition to save the download
227   if [ -d "${FSMNT}/usr" ]
228   then
229     DLDIR="${FSMNT}/usr/.fetch.$$"
230   else
231     DLDIR="${FSMNT}/.fetch.$$"
232   fi
233   mkdir -p ${DLDIR}
234
235   # Do the fetch of the dist archive(s) now
236   for di in $INSFILE
237   do
238     fetch_file "${FTPPATH}/${di}.txz" "${DLDIR}/${di}.txz" "1"
239   done
240
241   # Check to see if there is a MANIFEST file for this install
242   fetch_file "${FTPPATH}/MANIFEST" "${DLDIR}/MANIFEST" "0"
243
244   export DLDIR
245 };
246
247 # Function which will attempt to fetch the install file before we start
248 # the install
249 fetch_install_file()
250 {
251   get_value_from_cfg ftpPath
252   if [ -z "$VAL" ]
253   then
254     exit_err "ERROR: Install medium was set to ftp, but no ftpPath was provided!" 
255   fi
256
257   FTPPATH="${VAL}"
258   
259   # Check if we have a /usr partition to save the download
260   if [ -d "${FSMNT}/usr" ]
261   then
262     OUTFILE="${FSMNT}/usr/.fetch-${INSFILE}"
263   else
264     OUTFILE="${FSMNT}/.fetch-${INSFILE}"
265   fi
266
267   # Do the fetch of the archive now
268   fetch_file "${FTPPATH}/${INSFILE}" "${OUTFILE}" "1"
269
270   # Check to see if there is a .count file for this install
271   fetch_file "${FTPPATH}/${INSFILE}.count" "${OUTFILE}.count" "0"
272
273   # Check to see if there is a .md5 file for this install
274   fetch_file "${FTPPATH}/${INSFILE}.md5" "${OUTFILE}.md5" "0"
275
276   # Done fetching, now reset the INSFILE to our downloaded archived
277   export INSFILE="${OUTFILE}"
278
279 };
280
281 # Function which will download freebsd install files
282 fetch_split_files()
283 {
284   get_ftpHost
285   if [ -z "$VAL" ]
286   then
287     exit_err "ERROR: Install medium was set to ftp, but no ftpHost was provided!" 
288   fi
289   FTPHOST="${VAL}"
290
291   get_ftpDir
292   if [ -z "$VAL" ]
293   then
294     exit_err "ERROR: Install medium was set to ftp, but no ftpDir was provided!" 
295   fi
296   FTPDIR="${VAL}"
297
298   # Check if we have a /usr partition to save the download
299   if [ -d "${FSMNT}/usr" ]
300   then
301     OUTFILE="${FSMNT}/usr/.fetch-${INSFILE}"
302   else
303     OUTFILE="${FSMNT}/.fetch-${INSFILE}"
304   fi
305
306   DIRS="base catpages dict doc games info manpages proflibs kernels src"
307   if [ "${FBSD_ARCH}" = "amd64" ]
308   then
309     DIRS="${DIRS} lib32"
310   fi
311
312   for d in ${DIRS}
313   do
314     mkdir -p "${OUTFILE}/${d}"
315   done
316
317
318   NETRC="${OUTFILE}/.netrc"
319   cat <<EOF >"${NETRC}"
320 machine ${FTPHOST}
321 login anonymous
322 password anonymous
323 macdef INSTALL
324 bin
325 prompt
326 EOF
327
328   for d in ${DIRS}
329   do
330     cat <<EOF >>"${NETRC}"
331 cd ${FTPDIR}/${d}
332 lcd ${OUTFILE}/${d}
333 mreget *
334 EOF
335   done
336
337   cat <<EOF >>"${NETRC}"
338 bye
339
340
341 EOF
342
343   # Fetch the files via ftp
344   echo "$ INSTALL" | ftp -N "${NETRC}" "${FTPHOST}"
345
346   # Done fetching, now reset the INSFILE to our downloaded archived
347   export INSFILE="${OUTFILE}"
348 }
349
350 # Function which does the rsync download from the server specified in cfg
351 start_rsync_copy()
352 {
353   # Load our rsync config values
354   get_value_from_cfg rsyncPath
355   if [ -z "${VAL}" ]; then
356     exit_err "ERROR: rsyncPath is unset! Please check your config and try again."
357   fi
358   export RSYNCPATH="${VAL}"
359
360   get_value_from_cfg rsyncHost
361   if [  -z "${VAL}" ]; then
362     exit_err "ERROR: rsyncHost is unset! Please check your config and try again."
363   fi
364   export RSYNCHOST="${VAL}"
365
366   get_value_from_cfg rsyncUser
367   if [ -z "${VAL}" ]; then
368     exit_err "ERROR: rsyncUser is unset! Please check your config and try again."
369   fi
370   export RSYNCUSER="${VAL}"
371
372   get_value_from_cfg rsyncPort
373   if [ -z "${VAL}" ]; then
374     exit_err "ERROR: rsyncPort is unset! Please check your config and try again."
375   fi
376   export RSYNCPORT="${VAL}"
377
378   COUNT=1
379   while
380   z=1
381   do
382     if [ ${COUNT} -gt ${RSYNCTRIES} ]
383     then
384      exit_err "ERROR: Failed rsync command!"
385      break
386     fi
387
388     rsync -avvzHsR \
389     --rsync-path="rsync --fake-super" \
390     -e "ssh -p ${RSYNCPORT}" \
391     ${RSYNCUSER}@${RSYNCHOST}:${RSYNCPATH}/./ ${FSMNT}
392     if [ $? -ne 0 ]
393     then
394       echo "Rsync failed! Tries: ${COUNT}"
395     else
396       break
397     fi
398
399     COUNT=$((COUNT+1))
400   done 
401
402 };
403
404 start_image_install()
405 {
406   if [ -z "${IMAGE_FILE}" ]
407   then
408     exit_err "ERROR: installMedium set to image but no image file specified!"
409   fi
410
411   # We are ready to start mounting, lets read the config and do it
412   while read line
413   do
414     echo $line | grep -q "^disk0=" 2>/dev/null
415     if [ $? -eq 0 ]
416     then
417       # Found a disk= entry, lets get the disk we are working on
418       get_value_from_string "${line}"
419       strip_white_space "$VAL"
420       DISK="$VAL"
421     fi
422
423     echo $line | grep -q "^commitDiskPart" 2>/dev/null
424     if [ $? -eq 0 ]
425     then
426       # Found our flag to commit this disk setup / lets do sanity check and do it
427       if [ -n "${DISK}" ]
428       then
429
430         # Write the image
431         write_image "${IMAGE_FILE}" "${DISK}"
432
433         # Increment our disk counter to look for next disk and unset
434         unset DISK
435         break
436
437       else
438         exit_err "ERROR: commitDiskPart was called without procceding disk<num>= and partition= entries!!!"
439       fi
440     fi
441
442   done <${CFGF}
443 };
444
445 # Entrance function, which starts the installation process
446 init_extraction()
447 {
448   # Figure out what file we are using to install from via the config
449   get_value_from_cfg installFile
450
451   if [ -n "${VAL}" ]
452   then
453     export INSFILE="${VAL}"
454   else
455     # If no installFile specified, try our defaults
456     if [ "$INSTALLTYPE" = "FreeBSD" ]
457     then
458       case $PACKAGETYPE in
459         uzip) INSFILE="${FBSD_UZIP_FILE}" ;;
460         tar) INSFILE="${FBSD_TAR_FILE}" ;;
461         dist) 
462           get_value_from_cfg_with_spaces distFiles
463           if [ -z "$VAL" ] ; then
464              exit_err "No dist files specified!"
465           fi
466           INSFILE="${VAL}" 
467           ;;
468         split)
469           INSDIR="${FBSD_BRANCH_DIR}"
470
471           # This is to trick opt_mount into not failing
472           INSFILE="${INSDIR}"
473           ;;
474       esac
475     else
476       case $PACKAGETYPE in
477         uzip) INSFILE="${UZIP_FILE}" ;;
478         tar) INSFILE="${TAR_FILE}" ;;
479         dist) 
480           get_value_from_cfg_with_spaces distFiles
481           if [ -z "$VAL" ] ; then
482              exit_err "No dist files specified!"
483           fi
484           INSFILE="${VAL}" 
485           ;;
486       esac
487     fi
488     export INSFILE
489   fi
490
491   # Lets start by figuring out what medium we are using
492   case ${INSTALLMEDIUM} in
493     dvd|usb)
494       # Lets start by mounting the disk 
495       opt_mount 
496       if [ -n "${INSDIR}" ]
497       then
498         INSDIR="${CDMNT}/${INSDIR}" ; export INSDIR
499             start_extract_split
500
501       else
502         if [ "$PACKAGETYPE" = "dist" ] ; then
503           start_extract_dist "${CDMNT}/usr/freebsd-dist"
504         else
505           INSFILE="${CDMNT}/${INSFILE}" ; export INSFILE
506           start_extract_uzip_tar
507         fi
508       fi
509       ;;
510
511     ftp)
512       case $PACKAGETYPE in
513          split)
514            fetch_split_files
515
516            INSDIR="${INSFILE}" ; export INSDIR
517            start_extract_split
518            ;;
519           dist)
520            fetch_dist_file
521            start_extract_dist "$DLDIR"
522            ;;
523              *)
524            fetch_install_file
525            start_extract_uzip_tar 
526            ;;
527        esac
528       ;;
529
530     sftp) ;;
531
532     rsync) start_rsync_copy ;;
533     image) start_image_install ;;
534     local)
535       get_value_from_cfg localPath
536       if [ -z "$VAL" ]
537       then
538         exit_err "Install medium was set to local, but no localPath was provided!"
539       fi
540       LOCALPATH=$VAL
541       if [ "$PACKAGETYPE" = "dist" ] ; then
542         INSFILE="${INSFILE}" ; export INSFILE
543         start_extract_dist "$LOCALPATH"
544       else
545         INSFILE="${LOCALPATH}/${INSFILE}" ; export INSFILE
546         start_extract_uzip_tar
547       fi
548       ;;
549     *) exit_err "ERROR: Unknown install medium" ;;
550   esac
551
552 };