1182578Srik#!/bin/sh
2182578Srik#
3182578Srik# Copyright (C) 2008 Roman Kurakin rik@freebsd.org. All rights reserved.
4182578Srik#
5182578Srik# Redistribution and use in source and binary forms, with or without
6182578Srik# modification, are permitted provided that the following conditions
7182578Srik# are met:
8182578Srik# 1. Redistributions of source code must retain the above copyright
9182578Srik#    notice, this list of conditions and the following disclaimer.
10182578Srik# 2. Redistributions in binary form must reproduce the above copyright
11182578Srik#    notice, this list of conditions and the following disclaimer in the
12182578Srik#    documentation and/or other materials provided with the distribution.
13182578Srik#       
14182578Srik# THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15182578Srik# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16182578Srik# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17182578Srik# ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
18182578Srik# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19182578Srik# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20182578Srik# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21182578Srik# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22182578Srik# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23182578Srik# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24182578Srik# SUCH DAMAGE.
25182578Srik#
26182578Srik# Merges FreeBSD's several CD installation medias to the single DVD disk.
27182578Srik#
28182578Srik# $FreeBSD$
29182578Srik
30182578Srik## Helper functions
31182578Srikusage () {
32182578Srik	echo "Usage: $0 <dvd_img_name> <cd_img_name <cd_img_name ..>>"
33182578Srik}
34182578Srik
35182578Srik# Copy data from the cd
36182578Srik# $1 os name
37182578Srik# $2 disk image name
38182578Srik# $3 mount dir
39182578Srik# $4 destination dir
40182578Srikcopycd () {
41182578Srik	# Set some variables
42182578Srik	md=""
43182578Srik	_os="${1}"
44182578Srik	_img="${2}"
45182578Srik	_mnt="${3}"
46182578Srik	_dst="${4}"
47182578Srik	if [ $# -ne "4" ]
48182578Srik	then
49182578Srik		echo "Error: function ${0} takes exactly four parameters."
50182578Srik		exit 1
51182578Srik	fi
52182578Srik	if [ "${_os}" != "FreeBSD" -a "${_os}" != "Linux" ]
53182578Srik	then
54182578Srik		echo "Error: do not know how to handle ${_os} os."
55182578Srik		exit 1
56182578Srik	fi
57182578Srik	if [ ! -f "${_img}" ]
58182578Srik	then
59182578Srik		echo "Error: file ${_img} does not exists or not a regula file."
60182578Srik		exit 1
61182578Srik	fi
62182578Srik	if [ ! -r "${_img}" ]
63182578Srik	then
64182578Srik		echo "Error: you do not have the read permissions."
65182578Srik		exit 1
66182578Srik	fi
67182578Srik	if [ ! -d "${_mnt}" ]
68182578Srik	then
69182578Srik		echo "Error: ${_mnt} is not a directory or does not exists."
70182578Srik	fi
71182578Srik	if [ ! -d "${_dst}" ]
72182578Srik	then
73182578Srik		echo "Error: ${_dst} is not a directory or does not exists."
74182578Srik	fi
75182578Srik	if [ ! -w "${_dst}" ]
76182578Srik	then
77182578Srik		echo "Error: you do not have write permissions granted for ${_dst} directory."
78182578Srik	fi
79182578Srik	if [ "${_os}" != "Linux" ]
80182578Srik	then
81182578Srik		md=`mdconfig -a -t vnode -f ${_img}` || exit 1
82182578Srik		mount_cd9660 /dev/${md} ${_mnt} || exit 1
83182578Srik	else
84182578Srik		mount -o loop ${_img} ${_mnt} || exit 1
85182578Srik	fi
86182578Srik	if [ ! -f ${_mnt}/cdrom.inf ]
87182578Srik	then
88182578Srik		echo "Error: Failed to find cdrom.inf for ${_img}."
89182578Srik		exit 1
90182578Srik	fi
91182578Srik	cdvol=`grep "^CD_VOLUME.*" ${_mnt}/cdrom.inf | sed "s/CD_VOLUME[[:space:]]*=[[:space:]]*//"`
92182578Srik	if test -z "${cdvol}" -o ! "${cdvol}" -eq "${cdvol}" 2> /dev/null
93182578Srik	then
94182578Srik		echo "Error: failed to get volume id for ${_img}."
95182578Srik		exit 1
96182578Srik	fi
97182578Srik	cdver=`grep "^CD_VERSION.*" ${_mnt}/cdrom.inf | sed "s/CD_VERSION[[:space:]]*=[[:space:]]*//"`
98182578Srik	if test -z "${cdver}"
99182578Srik	then
100182578Srik		echo "Error: failed to get version id for ${_img}."
101182578Srik		exit 1
102182578Srik	fi
103182578Srik	if [ -z "${VERID}" ]
104182578Srik	then
105182578Srik		VERID="${cdver}"
106182578Srik		_exclude=""
107182578Srik	else
108182578Srik		if [ "${VERID}" != "${cdver}" ]
109182578Srik		then
110182578Srik			echo "Error: cd version ids mismatch while processing ${_img}."
111182578Srik			exit 1
112182578Srik		fi
113182578Srik#		_exclude="--exclude ./cdrom.inf --exclude ./packages/INDEX"
114182578Srik		_exclude="! -regex ./cdrom.inf ! -regex ./packages/INDEX"
115182578Srik	fi
116182578Srik	echo "Merging ${_img}:"
117182578Srik# --quite -u -V
118182578Srik	(cd "${_mnt}" && find . ${_exclude} | cpio -p -d -m -V --quiet "${_dst}") || exit 1
119182578Srik#	(cd "${_mnt}" && tar ${_exclude} -cvf - .) | (cd "${_dst}" && tar xvf -) || exit 1
120182578Srik	if [ "${_os}" != "Linux" ]
121182578Srik	then	
122182578Srik		umount /dev/${md} || exit 1
123182578Srik		mdconfig -d -u "${md}" || exit 1
124182578Srik	else
125182578Srik		umount ${_mnt} || exit 1
126182578Srik	fi
127182578Srik#	exit 0
128182578Srik}
129182578Srik
130182578Srik# Clear mounted image
131182578Srik# $1 mounted directory
132182578Srik# $2 error code
133182578Srikclearmount ()
134182578Srik{
135182578Srik	if [ $# -ne "2" ]
136182578Srik	then
137182578Srik		echo "Error: function ${0} takes exactly two parameters."
138182578Srik		exit 1
139182578Srik	fi
140182578Srik	if [ -z "${1}" ]
141182578Srik	then
142182578Srik		test -z "${2}" || exit "${2}"
143182578Srik	else
144182578Srik		# Ignore errors
145182578Srik		umount "${1}" 2>/dev/null
146182578Srik		test -z "${2}" || exit "${2}"
147182578Srik	fi
148182578Srik}
149182578Srik
150182578Srik# Clear CD image allocation
151182578Srik# $1 os name
152182578Srik# $2 md
153182578Srik# $3 error code
154182578Srikclearmd ()
155182578Srik{
156182578Srik	if [ $# -ne "3" ]
157182578Srik	then
158182578Srik		echo "Error: function ${0} takes exactly three parameters."
159182578Srik		exit 1
160182578Srik	fi
161182578Srik	if [ "${1}" != "FreeBSD" -o -z "${2}" ]
162182578Srik	then
163182578Srik		test -z "${3}" || exit "${3}"
164182578Srik	else
165182578Srik		# Ignore errors
166182578Srik		mdconfig -d -u "${2}" 2>/dev/null
167182578Srik		test -z "${3}" || exit "${3}"
168182578Srik	fi
169182578Srik}
170182578Srik
171182578Srik## Check params
172182578Srikif [ $# -lt 3 ]
173182578Srikthen
174182578Srik	usage
175182578Srik	echo "Error, this script should take more than two parameters."
176182578Srik	exit 1
177182578Srikfi
178182578Srik
179182578Srik# Check if zero
180182578Srikif [ -z "${1}" ]; then
181182578Srik	usage
182182578Srik	exit 1
183182578Srikfi
184182578Srik
185182578Srik# Check if already exists
186182578Srikif [ -e "${1}" ]; then
187182578Srik	if [ ! -f "${1}" ]; then
188182578Srik		echo "Destination DVD image file already exists and is not a regular file."
189182578Srik		exit 1
190182578Srik	fi
191182578Srik	while echo "The ${1} file exists. Overwrite? (y/n)"
192182578Srik	do
193182578Srik		read line
194182578Srik		case "${line}" in
195182578Srik		y|Y)
196182578Srik			rm -rf "${1}"
197182578Srik			touch "${1}"
198182578Srik			break
199182578Srik			;;
200182578Srik		n|N)
201182578Srik			echo "Please, run program again with a new value."
202182578Srik			exit 1
203182578Srik			;;
204182578Srik		esac
205182578Srik	done
206182578Srikfi
207182578SrikDVDIMAGE="${1}"
208182578Srik
209182578Srikshift
210182578Srik
211182578Srikcount=0
212182578Srikfor i in "$@"
213182578Srikdo
214182578Srik	# Skip empty params.
215182578Srik	if test -z "${i}"; then
216182578Srik		continue
217182578Srik	fi
218182578Srik	if [ ! -f "${i}" -o ! -r "${i}" ]
219182578Srik	then
220182578Srik		echo "Error: The ${i} is not readable, do not exists or not a regular file."
221182578Srik		exit 1
222182578Srik	fi
223182578Srik	count=`expr ${count} \+ 1`
224182578Srikdone
225182578Srik
226182578Srik# Check if we have at the least two CD images
227182578Srikif [ "${count}" -lt 2 ]
228182578Srikthen
229182578Srik	echo "Error: less than two CD images specified."
230182578Srikfi
231182578Srik
232228975Suqs## Some useful variables
233182578Srikpwd=`pwd`
234182578Sriktmpdirin="${pwd}/tmp-$$-in"
235182578Sriktmpdirout="${pwd}/tmp-$$-out"
236182578Sriksystem=`uname -s`
237182578Srikmd=""
238182578Srik
239182578Srik# set the trap options
240182578Sriktrap 'echo ""; echo "Cleaning up"; clearmount "${tmpdirin}" ""; clearmd "${system}" "${md}" ""; rm -rf "${tmpdirin}" "${tmpdirout}";' 0 1 2 3 15
241182578Srikmkdir "${tmpdirin}" || (echo "Error: failed to create tempory ${tmpdirin}"; exit 1)
242182578Srikmkdir "${tmpdirout}" || (echo "Error: failed to create tempory ${tmpdirout}"; exit 1)
243182578Srik
244182578Srikfor i in "$@"
245182578Srikdo
246182578Srik	# Skip empty params.
247182578Srik	if test -z "${i}"; then
248182578Srik		continue
249182578Srik	fi
250182578Srik	copycd "${system}" "${i}" "${tmpdirin}" "${tmpdirout}"
251182578Srik	mv "${tmpdirout}"/packages/INDEX "${tmpdirout}"/packages/INDEX~ || exit 1
252182578Srik	cat "${tmpdirout}"/packages/INDEX~ | sed "s/^\(.*\)|${cdvol}$/\1|1/" > "${tmpdirout}"/packages/INDEX || exit 1
253182578Srik	rm "${tmpdirout}"/packages/INDEX~ || exit 1
254182578Srikdone
255182578Srik
256182578Srikmv "${tmpdirout}"/cdrom.inf "${tmpdirout}"/cdrom.inf~ || exit 1
257182578Srikcat "${tmpdirout}"/cdrom.inf~ | sed "s/^\(CD_VOLUME[[:space:]]\{0,\}=[[:space:]]\{0,\}\)[[:digit:]]\{1,\}/\11/" > "${tmpdirout}"/cdrom.inf || exit 1
258182578Srikrm "${tmpdirout}"/cdrom.inf~ || exit 1
259182578Srik
260182578Srikmkisofs -b boot/cdboot -no-emul-boot -r -J \
261182578Srik	-V "FreeBSD_Install" \
262182578Srik	-publisher "The FreeBSD Project.  http://www.freebsd.org/" \
263182578Srik	-o ${DVDIMAGE} "${tmpdirout}" \
264182578Srik	|| exit 1 
265182578Srik
266182578Srikexit 0
267182578Srik
268