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