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