xref: /freebsd/tools/tools/cd2dvd/cd2dvd.sh (revision 315ee00f)
1#!/bin/sh
2#
3# Copyright (C) 2008 Roman Kurakin rik@freebsd.org. 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 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 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# Merges FreeBSD's several CD installation medias to the single DVD disk.
27#
28
29## Helper functions
30usage () {
31	echo "Usage: $0 <dvd_img_name> <cd_img_name <cd_img_name ..>>"
32}
33
34# Copy data from the cd
35# $1 os name
36# $2 disk image name
37# $3 mount dir
38# $4 destination dir
39copycd () {
40	# Set some variables
41	md=""
42	_os="${1}"
43	_img="${2}"
44	_mnt="${3}"
45	_dst="${4}"
46	if [ $# -ne "4" ]
47	then
48		echo "Error: function ${0} takes exactly four parameters."
49		exit 1
50	fi
51	if [ "${_os}" != "FreeBSD" -a "${_os}" != "Linux" ]
52	then
53		echo "Error: do not know how to handle ${_os} os."
54		exit 1
55	fi
56	if [ ! -f "${_img}" ]
57	then
58		echo "Error: file ${_img} does not exists or not a regula file."
59		exit 1
60	fi
61	if [ ! -r "${_img}" ]
62	then
63		echo "Error: you do not have the read permissions."
64		exit 1
65	fi
66	if [ ! -d "${_mnt}" ]
67	then
68		echo "Error: ${_mnt} is not a directory or does not exists."
69	fi
70	if [ ! -d "${_dst}" ]
71	then
72		echo "Error: ${_dst} is not a directory or does not exists."
73	fi
74	if [ ! -w "${_dst}" ]
75	then
76		echo "Error: you do not have write permissions granted for ${_dst} directory."
77	fi
78	if [ "${_os}" != "Linux" ]
79	then
80		md=`mdconfig -a -t vnode -f ${_img}` || exit 1
81		mount_cd9660 /dev/${md} ${_mnt} || exit 1
82	else
83		mount -o loop ${_img} ${_mnt} || exit 1
84	fi
85	if [ ! -f ${_mnt}/cdrom.inf ]
86	then
87		echo "Error: Failed to find cdrom.inf for ${_img}."
88		exit 1
89	fi
90	cdvol=`grep "^CD_VOLUME.*" ${_mnt}/cdrom.inf | sed "s/CD_VOLUME[[:space:]]*=[[:space:]]*//"`
91	if test -z "${cdvol}" -o ! "${cdvol}" -eq "${cdvol}" 2> /dev/null
92	then
93		echo "Error: failed to get volume id for ${_img}."
94		exit 1
95	fi
96	cdver=`grep "^CD_VERSION.*" ${_mnt}/cdrom.inf | sed "s/CD_VERSION[[:space:]]*=[[:space:]]*//"`
97	if test -z "${cdver}"
98	then
99		echo "Error: failed to get version id for ${_img}."
100		exit 1
101	fi
102	if [ -z "${VERID}" ]
103	then
104		VERID="${cdver}"
105		_exclude=""
106	else
107		if [ "${VERID}" != "${cdver}" ]
108		then
109			echo "Error: cd version ids mismatch while processing ${_img}."
110			exit 1
111		fi
112#		_exclude="--exclude ./cdrom.inf --exclude ./packages/INDEX"
113		_exclude="! -regex ./cdrom.inf ! -regex ./packages/INDEX"
114	fi
115	echo "Merging ${_img}:"
116# --quite -u -V
117	(cd "${_mnt}" && find . ${_exclude} | cpio -p -d -m -V --quiet "${_dst}") || exit 1
118#	(cd "${_mnt}" && tar ${_exclude} -cvf - .) | (cd "${_dst}" && tar xvf -) || exit 1
119	if [ "${_os}" != "Linux" ]
120	then
121		umount /dev/${md} || exit 1
122		mdconfig -d -u "${md}" || exit 1
123	else
124		umount ${_mnt} || exit 1
125	fi
126#	exit 0
127}
128
129# Clear mounted image
130# $1 mounted directory
131# $2 error code
132clearmount ()
133{
134	if [ $# -ne "2" ]
135	then
136		echo "Error: function ${0} takes exactly two parameters."
137		exit 1
138	fi
139	if [ -z "${1}" ]
140	then
141		test -z "${2}" || exit "${2}"
142	else
143		# Ignore errors
144		umount "${1}" 2>/dev/null
145		test -z "${2}" || exit "${2}"
146	fi
147}
148
149# Clear CD image allocation
150# $1 os name
151# $2 md
152# $3 error code
153clearmd ()
154{
155	if [ $# -ne "3" ]
156	then
157		echo "Error: function ${0} takes exactly three parameters."
158		exit 1
159	fi
160	if [ "${1}" != "FreeBSD" -o -z "${2}" ]
161	then
162		test -z "${3}" || exit "${3}"
163	else
164		# Ignore errors
165		mdconfig -d -u "${2}" 2>/dev/null
166		test -z "${3}" || exit "${3}"
167	fi
168}
169
170## Check params
171if [ $# -lt 3 ]
172then
173	usage
174	echo "Error, this script should take more than two parameters."
175	exit 1
176fi
177
178# Check if zero
179if [ -z "${1}" ]; then
180	usage
181	exit 1
182fi
183
184# Check if already exists
185if [ -e "${1}" ]; then
186	if [ ! -f "${1}" ]; then
187		echo "Destination DVD image file already exists and is not a regular file."
188		exit 1
189	fi
190	while echo "The ${1} file exists. Overwrite? (y/n)"
191	do
192		read line
193		case "${line}" in
194		y|Y)
195			rm -rf "${1}"
196			touch "${1}"
197			break
198			;;
199		n|N)
200			echo "Please, run program again with a new value."
201			exit 1
202			;;
203		esac
204	done
205fi
206DVDIMAGE="${1}"
207
208shift
209
210count=0
211for i in "$@"
212do
213	# Skip empty params.
214	if test -z "${i}"; then
215		continue
216	fi
217	if [ ! -f "${i}" -o ! -r "${i}" ]
218	then
219		echo "Error: The ${i} is not readable, do not exists or not a regular file."
220		exit 1
221	fi
222	count=`expr ${count} \+ 1`
223done
224
225# Check if we have at the least two CD images
226if [ "${count}" -lt 2 ]
227then
228	echo "Error: less than two CD images specified."
229fi
230
231## Some useful variables
232pwd=`pwd`
233tmpdirin="${pwd}/tmp-$$-in"
234tmpdirout="${pwd}/tmp-$$-out"
235system=`uname -s`
236md=""
237
238# set the trap options
239trap 'echo ""; echo "Cleaning up"; clearmount "${tmpdirin}" ""; clearmd "${system}" "${md}" ""; rm -rf "${tmpdirin}" "${tmpdirout}";' 0 1 2 3 15
240mkdir "${tmpdirin}" || (echo "Error: failed to create tempory ${tmpdirin}"; exit 1)
241mkdir "${tmpdirout}" || (echo "Error: failed to create tempory ${tmpdirout}"; exit 1)
242
243for i in "$@"
244do
245	# Skip empty params.
246	if test -z "${i}"; then
247		continue
248	fi
249	copycd "${system}" "${i}" "${tmpdirin}" "${tmpdirout}"
250	mv "${tmpdirout}"/packages/INDEX "${tmpdirout}"/packages/INDEX~ || exit 1
251	cat "${tmpdirout}"/packages/INDEX~ | sed "s/^\(.*\)|${cdvol}$/\1|1/" > "${tmpdirout}"/packages/INDEX || exit 1
252	rm "${tmpdirout}"/packages/INDEX~ || exit 1
253done
254
255mv "${tmpdirout}"/cdrom.inf "${tmpdirout}"/cdrom.inf~ || exit 1
256cat "${tmpdirout}"/cdrom.inf~ | sed "s/^\(CD_VOLUME[[:space:]]\{0,\}=[[:space:]]\{0,\}\)[[:digit:]]\{1,\}/\11/" > "${tmpdirout}"/cdrom.inf || exit 1
257rm "${tmpdirout}"/cdrom.inf~ || exit 1
258
259mkisofs -b boot/cdboot -no-emul-boot -r -J \
260	-V "FreeBSD_Install" \
261	-publisher "The FreeBSD Project.  https://www.freebsd.org/" \
262	-o ${DVDIMAGE} "${tmpdirout}" \
263	|| exit 1
264
265exit 0
266
267