Project

General

Profile

Download (62.5 KB) Statistics
| Branch: | Tag: | Revision:
1
#!/bin/sh
2
#
3
# builder_common.sh
4
#
5
# part of pfSense (https://www.pfsense.org)
6
# Copyright (c) 2004-2020 Rubicon Communications, LLC (Netgate)
7
# All rights reserved.
8
#
9
# FreeSBIE portions of the code
10
# Copyright (c) 2005 Dario Freni
11
# and copied from FreeSBIE project
12
# All rights reserved.
13
#
14
# Licensed under the Apache License, Version 2.0 (the "License");
15
# you may not use this file except in compliance with the License.
16
# You may obtain a copy of the License at
17
#
18
# http://www.apache.org/licenses/LICENSE-2.0
19
#
20
# Unless required by applicable law or agreed to in writing, software
21
# distributed under the License is distributed on an "AS IS" BASIS,
22
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23
# See the License for the specific language governing permissions and
24
# limitations under the License.
25

    
26
if [ -z "${IMAGES_FINAL_DIR}" -o "${IMAGES_FINAL_DIR}" = "/" ]; then
27
	echo "IMAGES_FINAL_DIR is not defined"
28
	print_error_pfS
29
fi
30

    
31
kldload filemon >/dev/null 2>&1
32

    
33
lc() {
34
	echo "${1}" | tr '[[:upper:]]' '[[:lower:]]'
35
}
36

    
37
git_last_commit() {
38
	export CURRENT_COMMIT=$(git -C ${BUILDER_ROOT} log -1 --format='%H')
39
	export CURRENT_AUTHOR=$(git -C ${BUILDER_ROOT} log -1 --format='%an')
40
	echo ">>> Last known commit $CURRENT_AUTHOR - $CURRENT_COMMIT"
41
	echo "$CURRENT_COMMIT" > $SCRATCHDIR/build_commit_info.txt
42
}
43

    
44
# Create core pkg repository
45
core_pkg_create_repo() {
46
	if [ ! -d "${CORE_PKG_REAL_PATH}/All" ]; then
47
		return
48
	fi
49

    
50
	############ ATTENTION ##############
51
	#
52
	# For some reason pkg-repo fail without / in the end of directory name
53
	# so removing it will break command
54
	#
55
	# https://github.com/freebsd/pkg/issues/1364
56
	#
57
	echo -n ">>> Creating core packages repository... "
58
	if pkg repo -q "${CORE_PKG_REAL_PATH}/"; then
59
		echo "Done!"
60
	else
61
		echo "Failed!"
62
		print_error_pfS
63
	fi
64

    
65
	# Use the same directory structure as poudriere does to avoid
66
	# breaking snapshot repositories during rsync
67
	ln -sf $(basename ${CORE_PKG_REAL_PATH}) ${CORE_PKG_PATH}/.latest
68
	ln -sf .latest/All ${CORE_PKG_ALL_PATH}
69
	ln -sf .latest/digests.txz ${CORE_PKG_PATH}/digests.txz
70
	ln -sf .latest/meta.conf ${CORE_PKG_PATH}/meta.conf
71
	ln -sf .latest/meta.txz ${CORE_PKG_PATH}/meta.txz
72
	ln -sf .latest/packagesite.txz ${CORE_PKG_PATH}/packagesite.txz
73
}
74

    
75
# Create core pkg (base, kernel)
76
core_pkg_create() {
77
	local _template="${1}"
78
	local _flavor="${2}"
79
	local _version="${3}"
80
	local _root="${4}"
81
	local _findroot="${5}"
82
	local _filter="${6}"
83

    
84
	local _template_path=${BUILDER_TOOLS}/templates/core_pkg/${_template}
85

    
86
	# Use default pkg repo to obtain ABI and ALTABI
87
	local _abi=$(sed -e "s/%%ARCH%%/${TARGET_ARCH}/g" \
88
	    ${PKG_REPO_DEFAULT%%.conf}.abi)
89
	local _altabi_arch=$(get_altabi_arch ${TARGET_ARCH})
90
	local _altabi=$(sed -e "s/%%ARCH%%/${_altabi_arch}/g" \
91
	    ${PKG_REPO_DEFAULT%%.conf}.altabi)
92

    
93
	${BUILDER_SCRIPTS}/create_core_pkg.sh \
94
		-t "${_template_path}" \
95
		-f "${_flavor}" \
96
		-v "${_version}" \
97
		-r "${_root}" \
98
		-s "${_findroot}" \
99
		-F "${_filter}" \
100
		-d "${CORE_PKG_REAL_PATH}/All" \
101
		-a "${_abi}" \
102
		-A "${_altabi}" \
103
		|| print_error_pfS
104
}
105

    
106
# This routine will output that something went wrong
107
print_error_pfS() {
108
	echo
109
	echo "####################################"
110
	echo "Something went wrong, check errors!" >&2
111
	echo "####################################"
112
	echo
113
	echo "NOTE: a lot of times you can run './build.sh --clean-builder' to resolve."
114
	echo
115
	[ -n "${LOGFILE}" -a -f "${LOGFILE}" ] && \
116
		echo "Log saved on ${LOGFILE}" && \
117
	echo
118
	kill $$
119
	exit 1
120
}
121

    
122
# This routine will verify that the kernel has been
123
# installed OK to the staging area.
124
ensure_kernel_exists() {
125
	if [ ! -f "$1/boot/kernel/kernel.gz" ]; then
126
		echo ">>> ERROR: Could not locate $1/boot/kernel.gz"
127
		print_error_pfS
128
	fi
129
	KERNEL_SIZE=$(stat -f "%z" $1/boot/kernel/kernel.gz)
130
	if [ "$KERNEL_SIZE" -lt 3500 ]; then
131
		echo ">>> ERROR: Kernel $1/boot/kernel.gz appears to be smaller than it should be: $KERNEL_SIZE"
132
		print_error_pfS
133
	fi
134
}
135

    
136
get_pkg_name() {
137
	echo "${PRODUCT_NAME}-${1}-${CORE_PKG_VERSION}"
138
}
139

    
140
# This routine builds all related kernels
141
build_all_kernels() {
142
	# Set KERNEL_BUILD_PATH if it has not been set
143
	if [ -z "${KERNEL_BUILD_PATH}" ]; then
144
		KERNEL_BUILD_PATH=$SCRATCHDIR/kernels
145
		echo ">>> KERNEL_BUILD_PATH has not been set. Setting to ${KERNEL_BUILD_PATH}!"
146
	fi
147

    
148
	[ -d "${KERNEL_BUILD_PATH}" ] \
149
		&& rm -rf ${KERNEL_BUILD_PATH}
150

    
151
	# Build embedded kernel
152
	for BUILD_KERNEL in $BUILD_KERNELS; do
153
		unset KERNCONF
154
		unset KERNEL_DESTDIR
155
		unset KERNEL_NAME
156
		export KERNCONF=$BUILD_KERNEL
157
		export KERNEL_DESTDIR="$KERNEL_BUILD_PATH/$BUILD_KERNEL"
158
		export KERNEL_NAME=${BUILD_KERNEL}
159

    
160
		LOGFILE="${BUILDER_LOGS}/kernel.${KERNCONF}.${TARGET}.log"
161
		echo ">>> Building $BUILD_KERNEL kernel."  | tee -a ${LOGFILE}
162

    
163
		if [ -n "${NO_BUILDKERNEL}" -a -f "${CORE_PKG_ALL_PATH}/$(get_pkg_name kernel-${KERNEL_NAME}).txz" ]; then
164
			echo ">>> NO_BUILDKERNEL set, skipping build" | tee -a ${LOGFILE}
165
			continue
166
		fi
167

    
168
		buildkernel
169

    
170
		echo ">>> Staging $BUILD_KERNEL kernel..." | tee -a ${LOGFILE}
171
		installkernel
172

    
173
		ensure_kernel_exists $KERNEL_DESTDIR
174

    
175
		echo ">>> Creating pkg of $KERNEL_NAME-debug kernel to staging area..."  | tee -a ${LOGFILE}
176
		core_pkg_create kernel-debug ${KERNEL_NAME} ${CORE_PKG_VERSION} ${KERNEL_DESTDIR} \
177
		    "./usr/lib/debug/boot" \*.debug
178
		rm -rf ${KERNEL_DESTDIR}/usr
179

    
180
		echo ">>> Creating pkg of $KERNEL_NAME kernel to staging area..."  | tee -a ${LOGFILE}
181
		core_pkg_create kernel ${KERNEL_NAME} ${CORE_PKG_VERSION} ${KERNEL_DESTDIR} "./boot/kernel ./boot/modules"
182

    
183
		rm -rf $KERNEL_DESTDIR 2>&1 1>/dev/null
184
	done
185
}
186

    
187
install_default_kernel() {
188
	if [ -z "${1}" ]; then
189
		echo ">>> ERROR: install_default_kernel called without a kernel config name"| tee -a ${LOGFILE}
190
		print_error_pfS
191
	fi
192

    
193
	export KERNEL_NAME="${1}"
194

    
195
	echo -n ">>> Installing kernel to be used by image ${KERNEL_NAME}..." | tee -a ${LOGFILE}
196

    
197
	# Copy kernel package to chroot, otherwise pkg won't find it to install
198
	if ! pkg_chroot_add ${FINAL_CHROOT_DIR} kernel-${KERNEL_NAME}; then
199
		echo ">>> ERROR: Error installing kernel package $(get_pkg_name kernel-${KERNEL_NAME}).txz" | tee -a ${LOGFILE}
200
		print_error_pfS
201
	fi
202

    
203
	# Set kernel pkg as vital to avoid user end up removing it for any reason
204
	pkg_chroot ${FINAL_CHROOT_DIR} set -v 1 -y $(get_pkg_name kernel-${KERNEL_NAME})
205

    
206
	if [ ! -f $FINAL_CHROOT_DIR/boot/kernel/kernel.gz ]; then
207
		echo ">>> ERROR: No kernel installed on $FINAL_CHROOT_DIR and the resulting image will be unusable. STOPPING!" | tee -a ${LOGFILE}
208
		print_error_pfS
209
	fi
210
	mkdir -p $FINAL_CHROOT_DIR/pkgs
211
	if [ -z "${2}" -o -n "${INSTALL_EXTRA_KERNELS}" ]; then
212
		cp ${CORE_PKG_ALL_PATH}/$(get_pkg_name kernel-${KERNEL_NAME}).txz $FINAL_CHROOT_DIR/pkgs
213
		if [ -n "${INSTALL_EXTRA_KERNELS}" ]; then
214
			for _EXTRA_KERNEL in $INSTALL_EXTRA_KERNELS; do
215
				_EXTRA_KERNEL_PATH=${CORE_PKG_ALL_PATH}/$(get_pkg_name kernel-${_EXTRA_KERNEL}).txz
216
				if [ -f "${_EXTRA_KERNEL_PATH}" ]; then
217
					echo -n ". adding ${_EXTRA_KERNEL_PATH} on image /pkgs folder"
218
					cp ${_EXTRA_KERNEL_PATH} $FINAL_CHROOT_DIR/pkgs
219
				else
220
					echo ">>> ERROR: Requested kernel $(get_pkg_name kernel-${_EXTRA_KERNEL}).txz was not found to be put on image /pkgs folder!"
221
					print_error_pfS
222
				fi
223
			done
224
		fi
225
	fi
226
	echo "Done." | tee -a ${LOGFILE}
227

    
228
	unset KERNEL_NAME
229
}
230

    
231
# This builds FreeBSD (make buildworld)
232
# Imported from FreeSBIE
233
make_world() {
234
	LOGFILE=${BUILDER_LOGS}/buildworld.${TARGET}
235
	echo ">>> LOGFILE set to $LOGFILE." | tee -a ${LOGFILE}
236
	if [ -n "${NO_BUILDWORLD}" ]; then
237
		echo ">>> NO_BUILDWORLD set, skipping build" | tee -a ${LOGFILE}
238
		return
239
	fi
240

    
241
	echo ">>> $(LC_ALL=C date) - Starting build world for ${TARGET} architecture..." | tee -a ${LOGFILE}
242
	script -aq $LOGFILE ${BUILDER_SCRIPTS}/build_freebsd.sh -K -s ${FREEBSD_SRC_DIR} \
243
		|| print_error_pfS
244
	echo ">>> $(LC_ALL=C date) - Finished build world for ${TARGET} architecture..." | tee -a ${LOGFILE}
245

    
246
	LOGFILE=${BUILDER_LOGS}/installworld.${TARGET}
247
	echo ">>> LOGFILE set to $LOGFILE." | tee -a ${LOGFILE}
248

    
249
	[ -d "${INSTALLER_CHROOT_DIR}" ] \
250
		|| mkdir -p ${INSTALLER_CHROOT_DIR}
251

    
252
	echo ">>> Installing world with bsdinstall for ${TARGET} architecture..." | tee -a ${LOGFILE}
253
	script -aq $LOGFILE ${BUILDER_SCRIPTS}/install_freebsd.sh -i -K \
254
		-s ${FREEBSD_SRC_DIR} \
255
		-d ${INSTALLER_CHROOT_DIR} \
256
		|| print_error_pfS
257

    
258
	# Copy additional installer scripts
259
	install -o root -g wheel -m 0755 ${BUILDER_TOOLS}/installer/*.sh \
260
		${INSTALLER_CHROOT_DIR}/root
261

    
262
	# XXX set root password since we don't have nullok enabled
263
	pw -R ${INSTALLER_CHROOT_DIR} usermod root -w yes
264

    
265
	echo ">>> Installing world without bsdinstall for ${TARGET} architecture..." | tee -a ${LOGFILE}
266
	script -aq $LOGFILE ${BUILDER_SCRIPTS}/install_freebsd.sh -K \
267
		-s ${FREEBSD_SRC_DIR} \
268
		-d ${STAGE_CHROOT_DIR} \
269
		|| print_error_pfS
270

    
271
	# Use the builder cross compiler from obj to produce the final binary.
272
	if [ "${TARGET_ARCH}" == "$(uname -p)" ]; then
273
		BUILD_CC="${MAKEOBJDIRPREFIX}/${FREEBSD_SRC_DIR}/tmp/usr/bin/cc"
274
	else
275
		BUILD_CC="${MAKEOBJDIRPREFIX}/${TARGET}.${TARGET_ARCH}${FREEBSD_SRC_DIR}/tmp/usr/bin/cc"
276
	fi
277

    
278
	[ -f "${BUILD_CC}" ] || print_error_pfS
279

    
280
	# XXX It must go to the scripts
281
	[ -d "${STAGE_CHROOT_DIR}/usr/local/bin" ] \
282
		|| mkdir -p ${STAGE_CHROOT_DIR}/usr/local/bin
283
	makeargs="CC=${BUILD_CC} DESTDIR=${STAGE_CHROOT_DIR}"
284
	echo ">>> Building and installing crypto tools and athstats for ${TARGET} architecture... (Starting - $(LC_ALL=C date))" | tee -a ${LOGFILE}
285
	(script -aq $LOGFILE make -C ${FREEBSD_SRC_DIR}/tools/tools/crypto ${makeargs} clean all install || print_error_pfS;) | egrep '^>>>' | tee -a ${LOGFILE}
286
	# XXX FIX IT
287
#	(script -aq $LOGFILE make -C ${FREEBSD_SRC_DIR}/tools/tools/ath/athstats ${makeargs} clean all install || print_error_pfS;) | egrep '^>>>' | tee -a ${LOGFILE}
288
	echo ">>> Building and installing crypto tools and athstats for ${TARGET} architecture... (Finished - $(LC_ALL=C date))" | tee -a ${LOGFILE}
289

    
290
	if [ "${PRODUCT_NAME}" = "pfSense" -a -n "${GNID_REPO_BASE}" ]; then
291
		echo ">>> Building gnid... " | tee -a ${LOGFILE}
292
		(\
293
			cd ${GNID_SRC_DIR} && \
294
			make \
295
				CC=${BUILD_CC} \
296
				INCLUDE_DIR=${GNID_INCLUDE_DIR} \
297
				LIBCRYPTO_DIR=${GNID_LIBCRYPTO_DIR} \
298
			clean gnid \
299
		) || print_error_pfS
300
		install -o root -g wheel -m 0700 ${GNID_SRC_DIR}/gnid \
301
			${STAGE_CHROOT_DIR}/usr/sbin \
302
			|| print_error_pfS
303
		install -o root -g wheel -m 0700 ${GNID_SRC_DIR}/gnid \
304
			${INSTALLER_CHROOT_DIR}/usr/sbin \
305
			|| print_error_pfS
306
	fi
307

    
308
	unset makeargs
309
}
310

    
311
# This routine creates a ova image that contains
312
# a ovf and vmdk file. These files can be imported
313
# right into vmware or virtual box.
314
# (and many other emulation platforms)
315
# http://www.vmware.com/pdf/ovf_whitepaper_specification.pdf
316
create_ova_image() {
317
	# XXX create a .ovf php creator that you can pass:
318
	#     1. populatedSize
319
	#     2. license
320
	#     3. product name
321
	#     4. version
322
	#     5. number of network interface cards
323
	#     6. allocationUnits
324
	#     7. capacity
325
	#     8. capacityAllocationUnits
326

    
327
	LOGFILE=${BUILDER_LOGS}/ova.${TARGET}.log
328

    
329
	local _mntdir=${OVA_TMP}/mnt
330

    
331
	if [ -d "${_mntdir}" ]; then
332
		local _dev
333
		# XXX Root cause still didn't found but it doesn't umount
334
		#     properly on looped builds and then require this extra
335
		#     check
336
		while true; do
337
			_dev=$(mount -p ${_mntdir} 2>/dev/null | awk '{print $1}')
338
			[ $? -ne 0 -o -z "${_dev}" ] \
339
				&& break
340
			umount -f ${_mntdir}
341
			mdconfig -d -u ${_dev#/dev/}
342
		done
343
		chflags -R noschg ${OVA_TMP}
344
		rm -rf ${OVA_TMP}
345
	fi
346

    
347
	mkdir -p $(dirname ${OVAPATH})
348

    
349
	mkdir -p ${_mntdir}
350

    
351
	if [ -z "${OVA_SWAP_PART_SIZE_IN_GB}" -o "${OVA_SWAP_PART_SIZE_IN_GB}" = "0" ]; then
352
		# first partition size (freebsd-ufs)
353
		local OVA_FIRST_PART_SIZE_IN_GB=${VMDK_DISK_CAPACITY_IN_GB}
354
		# Calculate real first partition size, removing 256 blocks (131072 bytes) beginning/loader
355
		local OVA_FIRST_PART_SIZE=$((${OVA_FIRST_PART_SIZE_IN_GB}*1024*1024*1024-131072))
356
		# Unset swap partition size variable
357
		unset OVA_SWAP_PART_SIZE
358
		# Parameter used by mkimg
359
		unset OVA_SWAP_PART_PARAM
360
	else
361
		# first partition size (freebsd-ufs)
362
		local OVA_FIRST_PART_SIZE_IN_GB=$((VMDK_DISK_CAPACITY_IN_GB-OVA_SWAP_PART_SIZE_IN_GB))
363
		# Use first partition size in g
364
		local OVA_FIRST_PART_SIZE="${OVA_FIRST_PART_SIZE_IN_GB}g"
365
		# Calculate real swap size, removing 256 blocks (131072 bytes) beginning/loader
366
		local OVA_SWAP_PART_SIZE=$((${OVA_SWAP_PART_SIZE_IN_GB}*1024*1024*1024-131072))
367
		# Parameter used by mkimg
368
		local OVA_SWAP_PART_PARAM="-p freebsd-swap/swap0::${OVA_SWAP_PART_SIZE}"
369
	fi
370

    
371
	# Prepare folder to be put in image
372
	customize_stagearea_for_image "ova"
373
	install_default_kernel ${DEFAULT_KERNEL} "no"
374

    
375
	# Fill fstab
376
	echo ">>> Installing platform specific items..." | tee -a ${LOGFILE}
377
	echo "/dev/gpt/${PRODUCT_NAME}	/	ufs		rw	1	1" > ${FINAL_CHROOT_DIR}/etc/fstab
378
	if [ -n "${OVA_SWAP_PART_SIZE}" ]; then
379
		echo "/dev/gpt/swap0	none	swap	sw	0	0" >> ${FINAL_CHROOT_DIR}/etc/fstab
380
	fi
381

    
382
	# Create / partition
383
	echo -n ">>> Creating / partition... " | tee -a ${LOGFILE}
384
	truncate -s ${OVA_FIRST_PART_SIZE} ${OVA_TMP}/${OVFUFS}
385
	local _md=$(mdconfig -a -f ${OVA_TMP}/${OVFUFS})
386
	trap "mdconfig -d -u ${_md}; return" 1 2 15 EXIT
387

    
388
	newfs -L ${PRODUCT_NAME} -j /dev/${_md} 2>&1 >>${LOGFILE}
389

    
390
	if ! mount /dev/${_md} ${_mntdir} 2>&1 >>${LOGFILE}; then
391
		echo "Failed!" | tee -a ${LOGFILE}
392
		echo ">>> ERROR: Error mounting temporary vmdk image. STOPPING!" | tee -a ${LOGFILE}
393
		print_error_pfS
394
	fi
395
	trap "sync; sleep 3; umount ${_mntdir} || umount -f ${_mntdir}; mdconfig -d -u ${_md}; return" 1 2 15 EXIT
396

    
397
	echo "Done!" | tee -a ${LOGFILE}
398

    
399
	clone_directory_contents ${FINAL_CHROOT_DIR} ${_mntdir}
400

    
401
	sync
402
	sleep 3
403
	umount ${_mntdir} || umount -f ${_mntdir} >>${LOGFILE} 2>&1
404
	mdconfig -d -u ${_md}
405
	trap "-" 1 2 15 EXIT
406

    
407
	# Create raw disk
408
	echo -n ">>> Creating raw disk... " | tee -a ${LOGFILE}
409
	mkimg \
410
		-s gpt \
411
		-f raw \
412
		-b ${FINAL_CHROOT_DIR}/boot/pmbr \
413
		-p freebsd-boot:=${FINAL_CHROOT_DIR}/boot/gptboot \
414
		-p freebsd-ufs/${PRODUCT_NAME}:=${OVA_TMP}/${OVFUFS} \
415
		${OVA_SWAP_PART_PARAM} \
416
		-o ${OVA_TMP}/${OVFRAW} 2>&1 >> ${LOGFILE}
417

    
418
	if [ $? -ne 0 -o ! -f ${OVA_TMP}/${OVFRAW} ]; then
419
		if [ -f ${OVA_TMP}/${OVFUFS} ]; then
420
			rm -f ${OVA_TMP}/${OVFUFS}
421
		fi
422
		if [ -f ${OVA_TMP}/${OVFRAW} ]; then
423
			rm -f ${OVA_TMP}/${OVFRAW}
424
		fi
425
		echo "Failed!" | tee -a ${LOGFILE}
426
		echo ">>> ERROR: Error creating temporary vmdk image. STOPPING!" | tee -a ${LOGFILE}
427
		print_error_pfS
428
	fi
429
	echo "Done!" | tee -a ${LOGFILE}
430

    
431
	# We don't need it anymore
432
	rm -f ${OVA_TMP}/${OVFUFS} >/dev/null 2>&1
433

    
434
	# Convert raw to vmdk
435
	echo -n ">>> Creating vmdk disk... " | tee -a ${LOGFILE}
436
	vmdktool -z9 -v ${OVA_TMP}/${OVFVMDK} ${OVA_TMP}/${OVFRAW}
437

    
438
	if [ $? -ne 0 -o ! -f ${OVA_TMP}/${OVFVMDK} ]; then
439
		if [ -f ${OVA_TMP}/${OVFRAW} ]; then
440
			rm -f ${OVA_TMP}/${OVFRAW}
441
		fi
442
		if [ -f ${OVA_TMP}/${OVFVMDK} ]; then
443
			rm -f ${OVA_TMP}/${OVFVMDK}
444
		fi
445
		echo "Failed!" | tee -a ${LOGFILE}
446
		echo ">>> ERROR: Error creating vmdk image. STOPPING!" | tee -a ${LOGFILE}
447
		print_error_pfS
448
	fi
449
	echo "Done!" | tee -a ${LOGFILE}
450

    
451
	rm -f ${OVA_TMP}/${OVFRAW}
452

    
453
	ova_setup_ovf_template
454

    
455
	echo -n ">>> Writing final ova image... " | tee -a ${LOGFILE}
456
	# Create OVA file for vmware
457
	gtar -C ${OVA_TMP} -cpf ${OVAPATH} ${PRODUCT_NAME}.ovf ${OVFVMDK}
458
	echo "Done!" | tee -a ${LOGFILE}
459
	rm -f ${OVA_TMP}/${OVFVMDK} >/dev/null 2>&1
460

    
461
	echo ">>> OVA created: $(LC_ALL=C date)" | tee -a ${LOGFILE}
462
}
463

    
464
# called from create_ova_image
465
ova_setup_ovf_template() {
466
	if [ ! -f ${OVFTEMPLATE} ]; then
467
		echo ">>> ERROR: OVF template file (${OVFTEMPLATE}) not found."
468
		print_error_pfS
469
	fi
470

    
471
	#  OperatingSystemSection (${PRODUCT_NAME}.ovf)
472
	#  42   FreeBSD 32-Bit
473
	#  78   FreeBSD 64-Bit
474
	if [ "${TARGET}" = "amd64" ]; then
475
		local _os_id="78"
476
		local _os_type="freebsd64Guest"
477
		local _os_descr="FreeBSD 64-Bit"
478
	else
479
		echo ">>> ERROR: Platform not supported for OVA (${TARGET})"
480
		print_error_pfS
481
	fi
482

    
483
	local POPULATED_SIZE=$(du -d0 -k $FINAL_CHROOT_DIR | cut -f1)
484
	local POPULATED_SIZE_IN_BYTES=$((${POPULATED_SIZE}*1024))
485
	local VMDK_FILE_SIZE=$(stat -f "%z" ${OVA_TMP}/${OVFVMDK})
486

    
487
	sed \
488
		-e "s,%%VMDK_FILE_SIZE%%,${VMDK_FILE_SIZE},g" \
489
		-e "s,%%VMDK_DISK_CAPACITY_IN_GB%%,${VMDK_DISK_CAPACITY_IN_GB},g" \
490
		-e "s,%%POPULATED_SIZE_IN_BYTES%%,${POPULATED_SIZE_IN_BYTES},g" \
491
		-e "s,%%OS_ID%%,${_os_id},g" \
492
		-e "s,%%OS_TYPE%%,${_os_type},g" \
493
		-e "s,%%OS_DESCR%%,${_os_descr},g" \
494
		-e "s,%%PRODUCT_NAME%%,${PRODUCT_NAME},g" \
495
		-e "s,%%PRODUCT_NAME_SUFFIX%%,${PRODUCT_NAME_SUFFIX},g" \
496
		-e "s,%%PRODUCT_VERSION%%,${PRODUCT_VERSION},g" \
497
		-e "s,%%PRODUCT_URL%%,${PRODUCT_URL},g" \
498
		-e "s#%%VENDOR_NAME%%#${VENDOR_NAME}#g" \
499
		-e "s#%%OVF_INFO%%#${OVF_INFO}#g" \
500
		-e "/^%%PRODUCT_LICENSE%%/r ${BUILDER_ROOT}/LICENSE" \
501
		-e "/^%%PRODUCT_LICENSE%%/d" \
502
		${OVFTEMPLATE} > ${OVA_TMP}/${PRODUCT_NAME}.ovf
503
}
504

    
505
# Cleans up previous builds
506
clean_builder() {
507
	# Clean out directories
508
	echo ">>> Cleaning up previous build environment...Please wait!"
509

    
510
	staginareas_clean_each_run
511

    
512
	if [ -d "${STAGE_CHROOT_DIR}" ]; then
513
		echo -n ">>> Cleaning ${STAGE_CHROOT_DIR}... "
514
		chflags -R noschg ${STAGE_CHROOT_DIR} 2>&1 >/dev/null
515
		rm -rf ${STAGE_CHROOT_DIR}/* 2>/dev/null
516
		echo "Done."
517
	fi
518

    
519
	if [ -d "${INSTALLER_CHROOT_DIR}" ]; then
520
		echo -n ">>> Cleaning ${INSTALLER_CHROOT_DIR}... "
521
		chflags -R noschg ${INSTALLER_CHROOT_DIR} 2>&1 >/dev/null
522
		rm -rf ${INSTALLER_CHROOT_DIR}/* 2>/dev/null
523
		echo "Done."
524
	fi
525

    
526
	if [ -z "${NO_CLEAN_FREEBSD_OBJ}" -a -d "${FREEBSD_SRC_DIR}" ]; then
527
		OBJTREE=$(make -C ${FREEBSD_SRC_DIR} -V OBJTREE)
528
		if [ -d "${OBJTREE}" ]; then
529
			echo -n ">>> Cleaning FreeBSD objects dir staging..."
530
			echo -n "."
531
			chflags -R noschg ${OBJTREE} 2>&1 >/dev/null
532
			echo -n "."
533
			rm -rf ${OBJTREE}/*
534
			echo "Done!"
535
		fi
536
		if [ -d "${KERNEL_BUILD_PATH}" ]; then
537
			echo -n ">>> Cleaning previously built kernel stage area..."
538
			rm -rf $KERNEL_BUILD_PATH/*
539
			echo "Done!"
540
		fi
541
	fi
542
	mkdir -p $KERNEL_BUILD_PATH
543

    
544
	echo -n ">>> Cleaning previously built images..."
545
	rm -rf $IMAGES_FINAL_DIR/*
546
	echo "Done!"
547

    
548
	echo -n ">>> Cleaning previous builder logs..."
549
	if [ -d "$BUILDER_LOGS" ]; then
550
		rm -rf ${BUILDER_LOGS}
551
	fi
552
	mkdir -p ${BUILDER_LOGS}
553

    
554
	echo "Done!"
555

    
556
	echo ">>> Cleaning of builder environment has finished."
557
}
558

    
559
clone_directory_contents() {
560
	if [ ! -e "$2" ]; then
561
		mkdir -p "$2"
562
	fi
563
	if [ ! -d "$1" -o ! -d "$2" ]; then
564
		if [ -z "${LOGFILE}" ]; then
565
			echo ">>> ERROR: Argument $1 supplied is not a directory!"
566
		else
567
			echo ">>> ERROR: Argument $1 supplied is not a directory!" | tee -a ${LOGFILE}
568
		fi
569
		print_error_pfS
570
	fi
571
	echo -n ">>> Using TAR to clone $1 to $2 ..."
572
	tar -C ${1} -c -f - . | tar -C ${2} -x -p -f -
573
	echo "Done!"
574
}
575

    
576
clone_to_staging_area() {
577
	# Clone everything to the final staging area
578
	echo -n ">>> Cloning everything to ${STAGE_CHROOT_DIR} staging area..."
579
	LOGFILE=${BUILDER_LOGS}/cloning.${TARGET}.log
580

    
581
	tar -C ${PRODUCT_SRC} -c -f - . | \
582
		tar -C ${STAGE_CHROOT_DIR} -x -p -f -
583

    
584
	if [ "${PRODUCT_NAME}" != "pfSense" ]; then
585
		mv ${STAGE_CHROOT_DIR}/usr/local/sbin/pfSense-upgrade \
586
			${STAGE_CHROOT_DIR}/usr/local/sbin/${PRODUCT_NAME}-upgrade
587
	fi
588

    
589
	mkdir -p ${STAGE_CHROOT_DIR}/etc/mtree
590
	mtree -Pcp ${STAGE_CHROOT_DIR}/var > ${STAGE_CHROOT_DIR}/etc/mtree/var.dist
591
	mtree -Pcp ${STAGE_CHROOT_DIR}/etc > ${STAGE_CHROOT_DIR}/etc/mtree/etc.dist
592
	if [ -d ${STAGE_CHROOT_DIR}/usr/local/etc ]; then
593
		mtree -Pcp ${STAGE_CHROOT_DIR}/usr/local/etc > ${STAGE_CHROOT_DIR}/etc/mtree/localetc.dist
594
	fi
595

    
596
	## Add buildtime and lastcommit information
597
	# This is used for detecting updates.
598
	echo "$BUILTDATESTRING" > $STAGE_CHROOT_DIR/etc/version.buildtime
599
	# Record last commit info if it is available.
600
	if [ -f $SCRATCHDIR/build_commit_info.txt ]; then
601
		cp $SCRATCHDIR/build_commit_info.txt $STAGE_CHROOT_DIR/etc/version.lastcommit
602
	fi
603

    
604
	local _exclude_files="${SCRATCHDIR}/base_exclude_files"
605
	sed \
606
		-e "s,%%PRODUCT_NAME%%,${PRODUCT_NAME},g" \
607
		-e "s,%%VERSION%%,${_version},g" \
608
		${BUILDER_TOOLS}/templates/core_pkg/base/exclude_files \
609
		> ${_exclude_files}
610

    
611
	mkdir -p ${STAGE_CHROOT_DIR}${PRODUCT_SHARE_DIR} >/dev/null 2>&1
612

    
613
	# Include a sample pkg stable conf to base
614
	setup_pkg_repo \
615
		${PKG_REPO_DEFAULT} \
616
		${STAGE_CHROOT_DIR}${PRODUCT_SHARE_DIR}/${PRODUCT_NAME}-repo.conf \
617
		${TARGET} \
618
		${TARGET_ARCH}
619

    
620
	mtree \
621
		-c \
622
		-k uid,gid,mode,size,flags,sha256digest \
623
		-p ${STAGE_CHROOT_DIR} \
624
		-X ${_exclude_files} \
625
		> ${STAGE_CHROOT_DIR}${PRODUCT_SHARE_DIR}/base.mtree
626
	tar \
627
		-C ${STAGE_CHROOT_DIR} \
628
		-cJf ${STAGE_CHROOT_DIR}${PRODUCT_SHARE_DIR}/base.txz \
629
		-X ${_exclude_files} \
630
		.
631

    
632
	core_pkg_create rc "" ${CORE_PKG_VERSION} ${STAGE_CHROOT_DIR}
633
	core_pkg_create base "" ${CORE_PKG_VERSION} ${STAGE_CHROOT_DIR}
634
	core_pkg_create default-config "" ${CORE_PKG_VERSION} ${STAGE_CHROOT_DIR}
635

    
636
	local DEFAULTCONF=${STAGE_CHROOT_DIR}/conf.default/config.xml
637

    
638
	# Save current WAN and LAN if value
639
	local _old_wan_if=$(xml sel -t -v "${XML_ROOTOBJ}/interfaces/wan/if" ${DEFAULTCONF})
640
	local _old_lan_if=$(xml sel -t -v "${XML_ROOTOBJ}/interfaces/lan/if" ${DEFAULTCONF})
641

    
642
	# Change default interface names to match vmware driver
643
	xml ed -P -L -u "${XML_ROOTOBJ}/interfaces/wan/if" -v "vmx0" ${DEFAULTCONF}
644
	xml ed -P -L -u "${XML_ROOTOBJ}/interfaces/lan/if" -v "vmx1" ${DEFAULTCONF}
645
	core_pkg_create default-config "vmware" ${CORE_PKG_VERSION} ${STAGE_CHROOT_DIR}
646

    
647
	# Restore default values to be used by serial package
648
	xml ed -P -L -u "${XML_ROOTOBJ}/interfaces/wan/if" -v "${_old_wan_if}" ${DEFAULTCONF}
649
	xml ed -P -L -u "${XML_ROOTOBJ}/interfaces/lan/if" -v "${_old_lan_if}" ${DEFAULTCONF}
650

    
651
	# Activate serial console in config.xml
652
	xml ed -L -P -d "${XML_ROOTOBJ}/system/enableserial" ${DEFAULTCONF}
653
	xml ed -P -s "${XML_ROOTOBJ}/system" -t elem -n "enableserial" \
654
		${DEFAULTCONF} > ${DEFAULTCONF}.tmp
655
	xml fo -t ${DEFAULTCONF}.tmp > ${DEFAULTCONF}
656
	rm -f ${DEFAULTCONF}.tmp
657

    
658
	echo force > ${STAGE_CHROOT_DIR}/cf/conf/enableserial_force
659

    
660
	core_pkg_create default-config-serial "" ${CORE_PKG_VERSION} ${STAGE_CHROOT_DIR}
661

    
662
	rm -f ${STAGE_CHROOT_DIR}/cf/conf/enableserial_force
663
	rm -f ${STAGE_CHROOT_DIR}/cf/conf/config.xml
664

    
665
	# Make sure pkg is present
666
	pkg_bootstrap ${STAGE_CHROOT_DIR}
667

    
668
	# Make sure correct repo is available on tmp dir
669
	mkdir -p ${STAGE_CHROOT_DIR}/tmp/pkg/pkg-repos
670
	setup_pkg_repo \
671
		${PKG_REPO_BUILD} \
672
		${STAGE_CHROOT_DIR}/tmp/pkg/pkg-repos/repo.conf \
673
		${TARGET} \
674
		${TARGET_ARCH} \
675
		staging \
676
		${STAGE_CHROOT_DIR}/tmp/pkg/pkg.conf
677

    
678
	echo "Done!"
679
}
680

    
681
create_final_staging_area() {
682
	if [ -z "${FINAL_CHROOT_DIR}" ]; then
683
		echo ">>> ERROR: FINAL_CHROOT_DIR is not set, cannot continue!" | tee -a ${LOGFILE}
684
		print_error_pfS
685
	fi
686

    
687
	if [ -d "${FINAL_CHROOT_DIR}" ]; then
688
		echo -n ">>> Previous ${FINAL_CHROOT_DIR} detected cleaning up..." | tee -a ${LOGFILE}
689
		chflags -R noschg ${FINAL_CHROOT_DIR} 2>&1 1>/dev/null
690
		rm -rf ${FINAL_CHROOT_DIR}/* 2>&1 1>/dev/null
691
		echo "Done." | tee -a ${LOGFILE}
692
	fi
693

    
694
	echo ">>> Preparing Final image staging area: $(LC_ALL=C date)" 2>&1 | tee -a ${LOGFILE}
695
	echo ">>> Cloning ${STAGE_CHROOT_DIR} to ${FINAL_CHROOT_DIR}" 2>&1 | tee -a ${LOGFILE}
696
	clone_directory_contents ${STAGE_CHROOT_DIR} ${FINAL_CHROOT_DIR}
697

    
698
	if [ ! -f $FINAL_CHROOT_DIR/sbin/init ]; then
699
		echo ">>> ERROR: Something went wrong during cloning -- Please verify!" 2>&1 | tee -a ${LOGFILE}
700
		print_error_pfS
701
	fi
702
}
703

    
704
customize_stagearea_for_image() {
705
	local _image_type="$1"
706
	local _default_config="" # filled with $2 below
707
	local _image_variant="$3"
708

    
709
	if [ -n "$2" ]; then
710
		_default_config="$2"
711
	elif [ "${_image_type}" = "memstickserial" -o \
712
	     "${_image_type}" = "memstickadi" ]; then
713
		_default_config="default-config-serial"
714
	elif [ "${_image_type}" = "ova" ]; then
715
		_default_config="default-config-vmware"
716
	else
717
		_default_config="default-config"
718
	fi
719

    
720
	# Prepare final stage area
721
	create_final_staging_area
722

    
723
	pkg_chroot_add ${FINAL_CHROOT_DIR} rc
724
	pkg_chroot_add ${FINAL_CHROOT_DIR} base
725

    
726
	# Set base/rc pkgs as vital to avoid user end up removing it for any reason
727
	pkg_chroot ${FINAL_CHROOT_DIR} set -v 1 -y $(get_pkg_name rc)
728
	pkg_chroot ${FINAL_CHROOT_DIR} set -v 1 -y $(get_pkg_name base)
729

    
730
	if [ "${_image_type}" = "iso" -o \
731
	     "${_image_type}" = "memstick" -o \
732
	     "${_image_type}" = "memstickserial" -o \
733
	     "${_image_type}" = "memstickadi" ]; then
734
		mkdir -p ${FINAL_CHROOT_DIR}/pkgs
735
		cp ${CORE_PKG_ALL_PATH}/*default-config*.txz ${FINAL_CHROOT_DIR}/pkgs
736
	fi
737

    
738
	pkg_chroot_add ${FINAL_CHROOT_DIR} ${_default_config}
739

    
740
	# XXX: Workaround to avoid pkg to complain regarding release
741
	#      repo on first boot since packages are installed from
742
	#      staging server during build phase
743
	if [ -n "${USE_PKG_REPO_STAGING}" ]; then
744
		_read_cmd="select value from repodata where key='packagesite'"
745
		if [ -n "${_IS_RELEASE}" -o -n "${_IS_RC}" ]; then
746
			local _tgt_server="${PKG_REPO_SERVER_RELEASE}"
747
		else
748
			local _tgt_server="${PKG_REPO_SERVER_DEVEL}"
749
		fi
750
		for _db in ${FINAL_CHROOT_DIR}/var/db/pkg/repo-*sqlite; do
751
			_cur=$(/usr/local/bin/sqlite3 ${_db} "${_read_cmd}")
752
			_new=$(echo "${_cur}" | sed -e "s,^${PKG_REPO_SERVER_STAGING},${_tgt_server},")
753
			/usr/local/bin/sqlite3 ${_db} "update repodata set value='${_new}' where key='packagesite'"
754
		done
755
	fi
756

    
757
	if [ -n "$_image_variant" -a \
758
	    -d ${BUILDER_TOOLS}/templates/custom_logos/${_image_variant} ]; then
759
		mkdir -p ${FINAL_CHROOT_DIR}/usr/local/share/${PRODUCT_NAME}/custom_logos
760
		cp -f \
761
			${BUILDER_TOOLS}/templates/custom_logos/${_image_variant}/*.svg \
762
			${FINAL_CHROOT_DIR}/usr/local/share/${PRODUCT_NAME}/custom_logos
763
		cp -f \
764
			${BUILDER_TOOLS}/templates/custom_logos/${_image_variant}/*.css \
765
			${FINAL_CHROOT_DIR}/usr/local/share/${PRODUCT_NAME}/custom_logos
766
	fi
767

    
768
	# Remove temporary repo conf
769
	rm -rf ${FINAL_CHROOT_DIR}/tmp/pkg
770
}
771

    
772
create_distribution_tarball() {
773
	mkdir -p ${INSTALLER_CHROOT_DIR}/usr/freebsd-dist
774

    
775
	echo -n ">>> Creating distribution tarball... " | tee -a ${LOGFILE}
776
	tar -C ${FINAL_CHROOT_DIR} --exclude ./pkgs \
777
		-cJf ${INSTALLER_CHROOT_DIR}/usr/freebsd-dist/base.txz .
778
	echo "Done!" | tee -a ${LOGFILE}
779

    
780
	echo -n ">>> Creating manifest... " | tee -a ${LOGFILE}
781
	(cd ${INSTALLER_CHROOT_DIR}/usr/freebsd-dist && \
782
		sh ${FREEBSD_SRC_DIR}/release/scripts/make-manifest.sh base.txz) \
783
		> ${INSTALLER_CHROOT_DIR}/usr/freebsd-dist/MANIFEST
784
	echo "Done!" | tee -a ${LOGFILE}
785
}
786

    
787
create_iso_image() {
788
	local _variant="$1"
789

    
790
	LOGFILE=${BUILDER_LOGS}/isoimage.${TARGET}
791

    
792
	if [ -z "${ISOPATH}" ]; then
793
		echo ">>> ISOPATH is empty skipping generation of ISO image!" | tee -a ${LOGFILE}
794
		return
795
	fi
796

    
797
	echo ">>> Building bootable ISO image for ${TARGET}" | tee -a ${LOGFILE}
798

    
799
	mkdir -p $(dirname ${ISOPATH})
800

    
801
	local _image_path=${ISOPATH}
802
	if [ -n "${_variant}" ]; then
803
		_image_path=$(echo "$_image_path" | \
804
			sed "s/${PRODUCT_NAME_SUFFIX}-/&${_variant}-/")
805
		VARIANTIMAGES="${VARIANTIMAGES}${VARIANTIMAGES:+ }${_image_path}"
806
	fi
807

    
808
	customize_stagearea_for_image "iso" "" $_variant
809
	install_default_kernel ${DEFAULT_KERNEL}
810

    
811
	BOOTCONF=${INSTALLER_CHROOT_DIR}/boot.config
812
	LOADERCONF=${INSTALLER_CHROOT_DIR}/boot/loader.conf
813

    
814
	rm -f ${LOADERCONF} ${BOOTCONF} >/dev/null 2>&1
815
	echo 'autoboot_delay="3"' > ${LOADERCONF}
816
	echo 'kern.cam.boot_delay=10000' >> ${LOADERCONF}
817
	cat ${LOADERCONF} > ${FINAL_CHROOT_DIR}/boot/loader.conf
818

    
819
	create_distribution_tarball
820

    
821
	FSLABEL=$(echo ${PRODUCT_NAME} | tr '[:lower:]' '[:upper:]')
822

    
823
	sh ${FREEBSD_SRC_DIR}/release/${TARGET}/mkisoimages.sh -b \
824
		${FSLABEL} \
825
		${_image_path} \
826
		${INSTALLER_CHROOT_DIR}
827

    
828
	if [ ! -f "${_image_path}" ]; then
829
		echo "ERROR! ISO image was not built"
830
		print_error_pfS
831
	fi
832

    
833
	gzip -qf $_image_path &
834
	_bg_pids="${_bg_pids}${_bg_pids:+ }$!"
835

    
836
	echo ">>> ISO created: $(LC_ALL=C date)" | tee -a ${LOGFILE}
837
}
838

    
839
create_memstick_image() {
840
	local _variant="$1"
841

    
842
	LOGFILE=${BUILDER_LOGS}/memstick.${TARGET}
843
	if [ "${MEMSTICKPATH}" = "" ]; then
844
		echo ">>> MEMSTICKPATH is empty skipping generation of memstick image!" | tee -a ${LOGFILE}
845
		return
846
	fi
847

    
848
	mkdir -p $(dirname ${MEMSTICKPATH})
849

    
850
	local _image_path=${MEMSTICKPATH}
851
	if [ -n "${_variant}" ]; then
852
		_image_path=$(echo "$_image_path" | \
853
			sed "s/-memstick-/-memstick-${_variant}-/")
854
		VARIANTIMAGES="${VARIANTIMAGES}${VARIANTIMAGES:+ }${_image_path}"
855
	fi
856

    
857
	customize_stagearea_for_image "memstick" "" $_variant
858
	install_default_kernel ${DEFAULT_KERNEL}
859

    
860
	echo ">>> Creating memstick to ${_image_path}." 2>&1 | tee -a ${LOGFILE}
861

    
862
	BOOTCONF=${INSTALLER_CHROOT_DIR}/boot.config
863
	LOADERCONF=${INSTALLER_CHROOT_DIR}/boot/loader.conf
864

    
865
	rm -f ${LOADERCONF} ${BOOTCONF} >/dev/null 2>&1
866

    
867
	echo 'autoboot_delay="3"' > ${LOADERCONF}
868
	echo 'kern.cam.boot_delay=10000' >> ${LOADERCONF}
869
	echo 'boot_serial="NO"' >> ${LOADERCONF}
870
	cat ${LOADERCONF} > ${FINAL_CHROOT_DIR}/boot/loader.conf
871

    
872
	create_distribution_tarball
873

    
874
	FSLABEL=$(echo ${PRODUCT_NAME} | tr '[:lower:]' '[:upper:]')
875

    
876
	sh ${FREEBSD_SRC_DIR}/release/${TARGET}/mkisoimages.sh -b \
877
		${FSLABEL} \
878
		${_image_path} \
879
		${INSTALLER_CHROOT_DIR}
880

    
881
	if [ ! -f "${_image_path}" ]; then
882
		echo "ERROR! memstick image was not built"
883
		print_error_pfS
884
	fi
885

    
886
	gzip -qf $_image_path &
887
	_bg_pids="${_bg_pids}${_bg_pids:+ }$!"
888

    
889
	echo ">>> MEMSTICK created: $(LC_ALL=C date)" | tee -a ${LOGFILE}
890
}
891

    
892
create_memstick_serial_image() {
893
	LOGFILE=${BUILDER_LOGS}/memstickserial.${TARGET}
894
	if [ "${MEMSTICKSERIALPATH}" = "" ]; then
895
		echo ">>> MEMSTICKSERIALPATH is empty skipping generation of memstick image!" | tee -a ${LOGFILE}
896
		return
897
	fi
898

    
899
	mkdir -p $(dirname ${MEMSTICKSERIALPATH})
900

    
901
	customize_stagearea_for_image "memstickserial"
902
	install_default_kernel ${DEFAULT_KERNEL}
903

    
904
	echo ">>> Creating serial memstick to ${MEMSTICKSERIALPATH}." 2>&1 | tee -a ${LOGFILE}
905

    
906
	BOOTCONF=${INSTALLER_CHROOT_DIR}/boot.config
907
	LOADERCONF=${INSTALLER_CHROOT_DIR}/boot/loader.conf
908

    
909
	echo ">>> Activating serial console..." 2>&1 | tee -a ${LOGFILE}
910
	echo "-S115200 -D" > ${BOOTCONF}
911

    
912
	# Activate serial console+video console in loader.conf
913
	echo 'autoboot_delay="3"' > ${LOADERCONF}
914
	echo 'kern.cam.boot_delay=10000' >> ${LOADERCONF}
915
	echo 'boot_multicons="YES"' >> ${LOADERCONF}
916
	echo 'boot_serial="YES"' >> ${LOADERCONF}
917
	echo 'console="comconsole,vidconsole"' >> ${LOADERCONF}
918
	echo 'comconsole_speed="115200"' >> ${LOADERCONF}
919

    
920
	cat ${BOOTCONF} >> ${FINAL_CHROOT_DIR}/boot.config
921
	cat ${LOADERCONF} >> ${FINAL_CHROOT_DIR}/boot/loader.conf
922

    
923
	create_distribution_tarball
924

    
925
	sh ${FREEBSD_SRC_DIR}/release/${TARGET}/make-memstick.sh \
926
		${INSTALLER_CHROOT_DIR} \
927
		${MEMSTICKSERIALPATH}
928

    
929
	if [ ! -f "${MEMSTICKSERIALPATH}" ]; then
930
		echo "ERROR! memstick serial image was not built"
931
		print_error_pfS
932
	fi
933

    
934
	gzip -qf $MEMSTICKSERIALPATH &
935
	_bg_pids="${_bg_pids}${_bg_pids:+ }$!"
936

    
937
	echo ">>> MEMSTICKSERIAL created: $(LC_ALL=C date)" | tee -a ${LOGFILE}
938
}
939

    
940
create_memstick_adi_image() {
941
	LOGFILE=${BUILDER_LOGS}/memstickadi.${TARGET}
942
	if [ "${MEMSTICKADIPATH}" = "" ]; then
943
		echo ">>> MEMSTICKADIPATH is empty skipping generation of memstick image!" | tee -a ${LOGFILE}
944
		return
945
	fi
946

    
947
	mkdir -p $(dirname ${MEMSTICKADIPATH})
948

    
949
	customize_stagearea_for_image "memstickadi"
950
	install_default_kernel ${DEFAULT_KERNEL}
951

    
952
	echo ">>> Creating serial memstick to ${MEMSTICKADIPATH}." 2>&1 | tee -a ${LOGFILE}
953

    
954
	BOOTCONF=${INSTALLER_CHROOT_DIR}/boot.config
955
	LOADERCONF=${INSTALLER_CHROOT_DIR}/boot/loader.conf
956

    
957
	echo ">>> Activating serial console..." 2>&1 | tee -a ${LOGFILE}
958
	echo "-S115200 -h" > ${BOOTCONF}
959

    
960
	# Activate serial console+video console in loader.conf
961
	echo 'autoboot_delay="3"' > ${LOADERCONF}
962
	echo 'kern.cam.boot_delay=10000' >> ${LOADERCONF}
963
	echo 'boot_serial="YES"' >> ${LOADERCONF}
964
	echo 'console="comconsole"' >> ${LOADERCONF}
965
	echo 'comconsole_speed="115200"' >> ${LOADERCONF}
966
	echo 'comconsole_port="0x2F8"' >> ${LOADERCONF}
967
	echo 'hint.uart.0.flags="0x00"' >> ${LOADERCONF}
968
	echo 'hint.uart.1.flags="0x10"' >> ${LOADERCONF}
969

    
970
	cat ${BOOTCONF} >> ${FINAL_CHROOT_DIR}/boot.config
971
	cat ${LOADERCONF} >> ${FINAL_CHROOT_DIR}/boot/loader.conf
972

    
973
	create_distribution_tarball
974

    
975
	sh ${FREEBSD_SRC_DIR}/release/${TARGET}/make-memstick.sh \
976
		${INSTALLER_CHROOT_DIR} \
977
		${MEMSTICKADIPATH}
978

    
979
	if [ ! -f "${MEMSTICKADIPATH}" ]; then
980
		echo "ERROR! memstick ADI image was not built"
981
		print_error_pfS
982
	fi
983

    
984
	gzip -qf $MEMSTICKADIPATH &
985
	_bg_pids="${_bg_pids}${_bg_pids:+ }$!"
986

    
987
	echo ">>> MEMSTICKADI created: $(LC_ALL=C date)" | tee -a ${LOGFILE}
988
}
989

    
990
get_altabi_arch() {
991
	local _target_arch="$1"
992

    
993
	if [ "${_target_arch}" = "amd64" ]; then
994
		echo "x86:64"
995
	elif [ "${_target_arch}" = "i386" ]; then
996
		echo "x86:32"
997
	elif [ "${_target_arch}" = "armv6" ]; then
998
		echo "32:el:eabi:hardfp"
999
	else
1000
		echo ">>> ERROR: Invalid arch"
1001
		print_error_pfS
1002
	fi
1003
}
1004

    
1005
# Create pkg conf on desired place with desired arch/branch
1006
setup_pkg_repo() {
1007
	if [ -z "${4}" ]; then
1008
		return
1009
	fi
1010

    
1011
	local _template="${1}"
1012
	local _target="${2}"
1013
	local _arch="${3}"
1014
	local _target_arch="${4}"
1015
	local _staging="${5}"
1016
	local _pkg_conf="${6}"
1017

    
1018
	if [ -z "${_template}" -o ! -f "${_template}" ]; then
1019
		echo ">>> ERROR: It was not possible to find pkg conf template ${_template}"
1020
		print_error_pfS
1021
	fi
1022

    
1023
	if [ -n "${_staging}" -a -n "${USE_PKG_REPO_STAGING}" ]; then
1024
		local _pkg_repo_server_devel=${PKG_REPO_SERVER_STAGING}
1025
		local _pkg_repo_branch_devel=${PKG_REPO_BRANCH_STAGING}
1026
		local _pkg_repo_server_release=${PKG_REPO_SERVER_STAGING}
1027
		local _pkg_repo_branch_release=${PKG_REPO_BRANCH_STAGING}
1028
	else
1029
		local _pkg_repo_server_devel=${PKG_REPO_SERVER_DEVEL}
1030
		local _pkg_repo_branch_devel=${PKG_REPO_BRANCH_DEVEL}
1031
		local _pkg_repo_server_release=${PKG_REPO_SERVER_RELEASE}
1032
		local _pkg_repo_branch_release=${PKG_REPO_BRANCH_RELEASE}
1033
	fi
1034

    
1035
	mkdir -p $(dirname ${_target}) >/dev/null 2>&1
1036

    
1037
	sed \
1038
		-e "s/%%ARCH%%/${_target_arch}/" \
1039
		-e "s/%%PKG_REPO_BRANCH_DEVEL%%/${_pkg_repo_branch_devel}/g" \
1040
		-e "s/%%PKG_REPO_BRANCH_RELEASE%%/${_pkg_repo_branch_release}/g" \
1041
		-e "s,%%PKG_REPO_SERVER_DEVEL%%,${_pkg_repo_server_devel},g" \
1042
		-e "s,%%PKG_REPO_SERVER_RELEASE%%,${_pkg_repo_server_release},g" \
1043
		-e "s,%%POUDRIERE_PORTS_NAME%%,${POUDRIERE_PORTS_NAME},g" \
1044
		-e "s/%%PRODUCT_NAME%%/${PRODUCT_NAME}/g" \
1045
		-e "s/%%REPO_BRANCH_PREFIX%%/${REPO_BRANCH_PREFIX}/g" \
1046
		${_template} \
1047
		> ${_target}
1048

    
1049
	local ALTABI_ARCH=$(get_altabi_arch ${_target_arch})
1050

    
1051
	ABI=$(cat ${_template%%.conf}.abi 2>/dev/null \
1052
	    | sed -e "s/%%ARCH%%/${_target_arch}/g")
1053
	ALTABI=$(cat ${_template%%.conf}.altabi 2>/dev/null \
1054
	    | sed -e "s/%%ARCH%%/${ALTABI_ARCH}/g")
1055

    
1056
	if [ -n "${_pkg_conf}" -a -n "${ABI}" -a -n "${ALTABI}" ]; then
1057
		mkdir -p $(dirname ${_pkg_conf})
1058
		echo "ABI=${ABI}" > ${_pkg_conf}
1059
		echo "ALTABI=${ALTABI}" >> ${_pkg_conf}
1060
	fi
1061
}
1062

    
1063
depend_check() {
1064
	for _pkg in ${BUILDER_PKG_DEPENDENCIES}; do
1065
		if ! pkg info -e ${_pkg}; then
1066
			echo "Missing dependency (${_pkg})."
1067
			print_error_pfS
1068
		fi
1069
	done
1070
}
1071

    
1072
# This routine ensures any ports / binaries that the builder
1073
# system needs are on disk and ready for execution.
1074
builder_setup() {
1075
	# If Product-builder is already installed, just leave
1076
	if pkg info -e -q ${PRODUCT_NAME}-builder; then
1077
		return
1078
	fi
1079

    
1080
	if [ ! -f ${PKG_REPO_PATH} ]; then
1081
		[ -d $(dirname ${PKG_REPO_PATH}) ] \
1082
			|| mkdir -p $(dirname ${PKG_REPO_PATH})
1083

    
1084
		update_freebsd_sources
1085

    
1086
		local _arch=$(uname -m)
1087
		setup_pkg_repo \
1088
			${PKG_REPO_BUILD} \
1089
			${PKG_REPO_PATH} \
1090
			${_arch} \
1091
			${_arch} \
1092
			"staging"
1093

    
1094
		# Use fingerprint keys from repo
1095
		sed -i '' -e "/fingerprints:/ s,\"/,\"${BUILDER_ROOT}/src/," \
1096
			${PKG_REPO_PATH}
1097
	fi
1098

    
1099
	pkg install ${PRODUCT_NAME}-builder
1100
}
1101

    
1102
# Updates FreeBSD sources
1103
update_freebsd_sources() {
1104
	if [ "${1}" = "full" ]; then
1105
		local _full=1
1106
		local _clone_params=""
1107
	else
1108
		local _full=0
1109
		local _clone_params="--depth 1 --single-branch"
1110
	fi
1111

    
1112
	if [ -n "${NO_BUILDWORLD}" -a -n "${NO_BUILDKERNEL}" ]; then
1113
		echo ">>> NO_BUILDWORLD and NO_BUILDKERNEL set, skipping update of freebsd sources" | tee -a ${LOGFILE}
1114
		return
1115
	fi
1116

    
1117
	echo ">>> Obtaining FreeBSD sources (${FREEBSD_BRANCH})..."
1118
	${BUILDER_SCRIPTS}/git_checkout.sh \
1119
		-r ${FREEBSD_REPO_BASE} \
1120
		-d ${FREEBSD_SRC_DIR} \
1121
		-b ${FREEBSD_BRANCH}
1122

    
1123
	if [ $? -ne 0 -o ! -d "${FREEBSD_SRC_DIR}/.git" ]; then
1124
		echo ">>> ERROR: It was not possible to clone FreeBSD src repo"
1125
		print_error_pfS
1126
	fi
1127

    
1128
	if [ -n "${GIT_FREEBSD_COSHA1}" ]; then
1129
		echo -n ">>> Checking out desired commit (${GIT_FREEBSD_COSHA1})... "
1130
		( git -C  ${FREEBSD_SRC_DIR} checkout ${GIT_FREEBSD_COSHA1} ) 2>&1 | \
1131
			grep -C3 -i -E 'error|fatal'
1132
		echo "Done!"
1133
	fi
1134

    
1135
	if [ "${PRODUCT_NAME}" = "pfSense" -a -n "${GNID_REPO_BASE}" ]; then
1136
		echo ">>> Obtaining gnid sources..."
1137
		${BUILDER_SCRIPTS}/git_checkout.sh \
1138
			-r ${GNID_REPO_BASE} \
1139
			-d ${GNID_SRC_DIR} \
1140
			-b ${GNID_BRANCH}
1141
	fi
1142
}
1143

    
1144
pkg_chroot() {
1145
	local _root="${1}"
1146
	shift
1147

    
1148
	if [ $# -eq 0 ]; then
1149
		return -1
1150
	fi
1151

    
1152
	if [ -z "${_root}" -o "${_root}" = "/" -o ! -d "${_root}" ]; then
1153
		return -1
1154
	fi
1155

    
1156
	mkdir -p \
1157
		${SCRATCHDIR}/pkg_cache \
1158
		${_root}/var/cache/pkg \
1159
		${_root}/dev
1160

    
1161
	/sbin/mount -t nullfs ${SCRATCHDIR}/pkg_cache ${_root}/var/cache/pkg
1162
	/sbin/mount -t devfs devfs ${_root}/dev
1163
	cp -f /etc/resolv.conf ${_root}/etc/resolv.conf
1164
	touch ${BUILDER_LOGS}/install_pkg_install_ports.txt
1165
	local _params=""
1166
	if [ -f "${_root}/tmp/pkg/pkg-repos/repo.conf" ]; then
1167
		_params="--repo-conf-dir /tmp/pkg/pkg-repos "
1168
	fi
1169
	if [ -f "${_root}/tmp/pkg/pkg.conf" ]; then
1170
		_params="${_params} --config /tmp/pkg/pkg.conf "
1171
	fi
1172
	script -aq ${BUILDER_LOGS}/install_pkg_install_ports.txt \
1173
		chroot ${_root} pkg ${_params}$@ >/dev/null 2>&1
1174
	local result=$?
1175
	rm -f ${_root}/etc/resolv.conf
1176
	/sbin/umount -f ${_root}/dev
1177
	/sbin/umount -f ${_root}/var/cache/pkg
1178

    
1179
	return $result
1180
}
1181

    
1182

    
1183
pkg_chroot_add() {
1184
	if [ -z "${1}" -o -z "${2}" ]; then
1185
		return 1
1186
	fi
1187

    
1188
	local _target="${1}"
1189
	local _pkg="$(get_pkg_name ${2}).txz"
1190

    
1191
	if [ ! -d "${_target}" ]; then
1192
		echo ">>> ERROR: Target dir ${_target} not found"
1193
		print_error_pfS
1194
	fi
1195

    
1196
	if [ ! -f ${CORE_PKG_ALL_PATH}/${_pkg} ]; then
1197
		echo ">>> ERROR: Package ${_pkg} not found"
1198
		print_error_pfS
1199
	fi
1200

    
1201
	cp ${CORE_PKG_ALL_PATH}/${_pkg} ${_target}
1202
	pkg_chroot ${_target} add /${_pkg}
1203
	rm -f ${_target}/${_pkg}
1204
}
1205

    
1206
pkg_bootstrap() {
1207
	local _root=${1:-"${STAGE_CHROOT_DIR}"}
1208

    
1209
	setup_pkg_repo \
1210
		${PKG_REPO_BUILD} \
1211
		${_root}${PKG_REPO_PATH} \
1212
		${TARGET} \
1213
		${TARGET_ARCH} \
1214
		"staging"
1215

    
1216
	pkg_chroot ${_root} bootstrap -f
1217
}
1218

    
1219
# This routine assists with installing various
1220
# freebsd ports files into the pfsense-fs staging
1221
# area.
1222
install_pkg_install_ports() {
1223
	local MAIN_PKG="${1}"
1224

    
1225
	if [ -z "${MAIN_PKG}" ]; then
1226
		MAIN_PKG=${PRODUCT_NAME}
1227
	fi
1228

    
1229
	echo ">>> Installing pkg repository in chroot (${STAGE_CHROOT_DIR})..."
1230

    
1231
	[ -d ${STAGE_CHROOT_DIR}/var/cache/pkg ] || \
1232
		mkdir -p ${STAGE_CHROOT_DIR}/var/cache/pkg
1233

    
1234
	[ -d ${SCRATCHDIR}/pkg_cache ] || \
1235
		mkdir -p ${SCRATCHDIR}/pkg_cache
1236

    
1237
	echo -n ">>> Installing built ports (packages) in chroot (${STAGE_CHROOT_DIR})... "
1238
	# First mark all packages as automatically installed
1239
	pkg_chroot ${STAGE_CHROOT_DIR} set -A 1 -a
1240
	# Install all necessary packages
1241
	if ! pkg_chroot ${STAGE_CHROOT_DIR} install ${MAIN_PKG} ${custom_package_list}; then
1242
		echo "Failed!"
1243
		print_error_pfS
1244
	fi
1245
	# Make sure required packages are set as non-automatic
1246
	pkg_chroot ${STAGE_CHROOT_DIR} set -A 0 pkg ${MAIN_PKG} ${custom_package_list}
1247
	# pkg and MAIN_PKG are vital
1248
	pkg_chroot ${STAGE_CHROOT_DIR} set -y -v 1 pkg ${MAIN_PKG}
1249
	# Remove unnecessary packages
1250
	pkg_chroot ${STAGE_CHROOT_DIR} autoremove
1251
	echo "Done!"
1252
}
1253

    
1254
staginareas_clean_each_run() {
1255
	echo -n ">>> Cleaning build directories: "
1256
	if [ -d "${FINAL_CHROOT_DIR}" ]; then
1257
		BASENAME=$(basename ${FINAL_CHROOT_DIR})
1258
		echo -n "$BASENAME "
1259
		chflags -R noschg ${FINAL_CHROOT_DIR} 2>&1 >/dev/null
1260
		rm -rf ${FINAL_CHROOT_DIR}/* 2>/dev/null
1261
	fi
1262
	echo "Done!"
1263
}
1264

    
1265
# Imported from FreeSBIE
1266
buildkernel() {
1267
	local _kernconf=${1:-${KERNCONF}}
1268

    
1269
	if [ -n "${NO_BUILDKERNEL}" ]; then
1270
		echo ">>> NO_BUILDKERNEL set, skipping build" | tee -a ${LOGFILE}
1271
		return
1272
	fi
1273

    
1274
	if [ -z "${_kernconf}" ]; then
1275
		echo ">>> ERROR: No kernel configuration defined probably this is not what you want! STOPPING!" | tee -a ${LOGFILE}
1276
		print_error_pfS
1277
	fi
1278

    
1279
	local _old_kernconf=${KERNCONF}
1280
	export KERNCONF=${_kernconf}
1281

    
1282
	echo ">>> $(LC_ALL=C date) - Starting build kernel for ${TARGET} architecture..." | tee -a ${LOGFILE}
1283
	script -aq $LOGFILE ${BUILDER_SCRIPTS}/build_freebsd.sh -W -s ${FREEBSD_SRC_DIR} \
1284
		|| print_error_pfS
1285
	echo ">>> $(LC_ALL=C date) - Finished build kernel for ${TARGET} architecture..." | tee -a ${LOGFILE}
1286

    
1287
	export KERNCONF=${_old_kernconf}
1288
}
1289

    
1290
# Imported from FreeSBIE
1291
installkernel() {
1292
	local _destdir=${1:-${KERNEL_DESTDIR}}
1293
	local _kernconf=${2:-${KERNCONF}}
1294

    
1295
	if [ -z "${_kernconf}" ]; then
1296
		echo ">>> ERROR: No kernel configuration defined probably this is not what you want! STOPPING!" | tee -a ${LOGFILE}
1297
		print_error_pfS
1298
	fi
1299

    
1300
	local _old_kernconf=${KERNCONF}
1301
	export KERNCONF=${_kernconf}
1302

    
1303
	mkdir -p ${STAGE_CHROOT_DIR}/boot
1304
	echo ">>> Installing kernel (${_kernconf}) for ${TARGET} architecture..." | tee -a ${LOGFILE}
1305
	script -aq $LOGFILE ${BUILDER_SCRIPTS}/install_freebsd.sh -W -D -z \
1306
		-s ${FREEBSD_SRC_DIR} \
1307
		-d ${_destdir} \
1308
		|| print_error_pfS
1309

    
1310
	export KERNCONF=${_old_kernconf}
1311
}
1312

    
1313
# Launch is ran first to setup a few variables that we need
1314
# Imported from FreeSBIE
1315
launch() {
1316
	if [ "$(id -u)" != "0" ]; then
1317
		echo "Sorry, this must be done as root."
1318
	fi
1319

    
1320
	echo ">>> Operation $0 has started at $(date)"
1321
}
1322

    
1323
finish() {
1324
	echo ">>> Operation $0 has ended at $(date)"
1325
}
1326

    
1327
pkg_repo_rsync() {
1328
	local _repo_path_param="${1}"
1329
	local _ignore_final_rsync="${2}"
1330
	local _aws_sync_cmd="aws s3 sync --quiet --exclude '.real*/*' --exclude '.latest/*'"
1331

    
1332
	if [ -z "${_repo_path_param}" -o ! -d "${_repo_path_param}" ]; then
1333
		return
1334
	fi
1335

    
1336
	if [ -n "${SKIP_FINAL_RSYNC}" ]; then
1337
		_ignore_final_rsync="1"
1338
	fi
1339

    
1340
	# Sanitize path
1341
	_repo_path=$(realpath ${_repo_path_param})
1342

    
1343
	local _repo_dir=$(dirname ${_repo_path})
1344
	local _repo_base=$(basename ${_repo_path})
1345

    
1346
	# Add ./ it's an rsync trick to make it chdir to directory before sending it
1347
	_repo_path="${_repo_dir}/./${_repo_base}"
1348

    
1349
	if [ -z "${LOGFILE}" ]; then
1350
		local _logfile="/dev/null"
1351
	else
1352
		local _logfile="${LOGFILE}"
1353
	fi
1354

    
1355
	if [ -n "${PKG_REPO_SIGNING_COMMAND}" -a -z "${DO_NOT_SIGN_PKG_REPO}" ]; then
1356
		# Detect poudriere directory structure
1357
		if [ -L "${_repo_path}/.latest" ]; then
1358
			local _real_repo_path=$(readlink -f ${_repo_path}/.latest)
1359
		else
1360
			local _real_repo_path=${_repo_path}
1361
		fi
1362

    
1363
		echo -n ">>> Signing repository... " | tee -a ${_logfile}
1364
		############ ATTENTION ##############
1365
		#
1366
		# For some reason pkg-repo fail without / in the end of directory name
1367
		# so removing it will break command
1368
		#
1369
		# https://github.com/freebsd/pkg/issues/1364
1370
		#
1371
		if script -aq ${_logfile} pkg repo ${_real_repo_path}/ \
1372
		    signing_command: ${PKG_REPO_SIGNING_COMMAND} >/dev/null 2>&1; then
1373
			echo "Done!" | tee -a ${_logfile}
1374
		else
1375
			echo "Failed!" | tee -a ${_logfile}
1376
			echo ">>> ERROR: An error occurred trying to sign repo"
1377
			print_error_pfS
1378
		fi
1379

    
1380
		local _pkgfile="${_repo_path}/Latest/pkg.txz"
1381
		if [ -e ${_pkgfile} ]; then
1382
			echo -n ">>> Signing Latest/pkg.txz for bootstraping... " | tee -a ${_logfile}
1383

    
1384
			if sha256 -q ${_pkgfile} | ${PKG_REPO_SIGNING_COMMAND} \
1385
			    > ${_pkgfile}.sig 2>/dev/null; then
1386
				echo "Done!" | tee -a ${_logfile}
1387
			else
1388
				echo "Failed!" | tee -a ${_logfile}
1389
				echo ">>> ERROR: An error occurred trying to sign Latest/pkg.txz"
1390
				print_error_pfS
1391
			fi
1392
		fi
1393
	fi
1394

    
1395
	if [ -z "${UPLOAD}" ]; then
1396
		return
1397
	fi
1398

    
1399
	for _pkg_rsync_hostname in ${PKG_RSYNC_HOSTNAME}; do
1400
		# Make sure destination directory exist
1401
		ssh -o StrictHostKeyChecking=no -p ${PKG_RSYNC_SSH_PORT} \
1402
			${PKG_RSYNC_USERNAME}@${_pkg_rsync_hostname} \
1403
			"mkdir -p ${PKG_RSYNC_DESTDIR}"
1404

    
1405
		echo -n ">>> Sending updated repository to ${_pkg_rsync_hostname}... " | tee -a ${_logfile}
1406
		if script -aq ${_logfile} rsync -Have "ssh -o StrictHostKeyChecking=no -p ${PKG_RSYNC_SSH_PORT}" \
1407
			--timeout=60 --delete-delay ${_repo_path} \
1408
			${PKG_RSYNC_USERNAME}@${_pkg_rsync_hostname}:${PKG_RSYNC_DESTDIR} >/dev/null 2>&1
1409
		then
1410
			echo "Done!" | tee -a ${_logfile}
1411
		else
1412
			echo "Failed!" | tee -a ${_logfile}
1413
			echo ">>> ERROR: An error occurred sending repo to remote hostname"
1414
			print_error_pfS
1415
		fi
1416

    
1417
		if [ -z "${USE_PKG_REPO_STAGING}" -o -n "${_ignore_final_rsync}" ]; then
1418
			return
1419
		fi
1420

    
1421
		if [ -n "${_IS_RELEASE}" -o "${_repo_path_param}" = "${CORE_PKG_PATH}" ]; then
1422
			for _pkg_final_rsync_hostname in ${PKG_FINAL_RSYNC_HOSTNAME}; do
1423
				# Send .real* directories first to prevent having a broken repo while transfer happens
1424
				local _cmd="rsync -Have \"ssh -o StrictHostKeyChecking=no -p ${PKG_FINAL_RSYNC_SSH_PORT}\" \
1425
					--timeout=60 ${PKG_RSYNC_DESTDIR}/./${_repo_base%%-core}* \
1426
					--include=\"/*\" --include=\"*/.real*\" --include=\"*/.real*/***\" \
1427
					--exclude=\"*\" \
1428
					${PKG_FINAL_RSYNC_USERNAME}@${_pkg_final_rsync_hostname}:${PKG_FINAL_RSYNC_DESTDIR}"
1429

    
1430
				echo -n ">>> Sending updated packages to ${_pkg_final_rsync_hostname}... " | tee -a ${_logfile}
1431
				if script -aq ${_logfile} ssh -o StrictHostKeyChecking=no -p ${PKG_RSYNC_SSH_PORT} \
1432
					${PKG_RSYNC_USERNAME}@${_pkg_rsync_hostname} ${_cmd} >/dev/null 2>&1; then
1433
					echo "Done!" | tee -a ${_logfile}
1434
				else
1435
					echo "Failed!" | tee -a ${_logfile}
1436
					echo ">>> ERROR: An error occurred sending repo to final hostname"
1437
					print_error_pfS
1438
				fi
1439

    
1440
				_cmd="rsync -Have \"ssh -o StrictHostKeyChecking=no -p ${PKG_FINAL_RSYNC_SSH_PORT}\" \
1441
					--timeout=60 --delete-delay ${PKG_RSYNC_DESTDIR}/./${_repo_base%%-core}* \
1442
					${PKG_FINAL_RSYNC_USERNAME}@${_pkg_final_rsync_hostname}:${PKG_FINAL_RSYNC_DESTDIR}"
1443

    
1444
				echo -n ">>> Sending updated repositories metadata to ${_pkg_final_rsync_hostname}... " | tee -a ${_logfile}
1445
				if script -aq ${_logfile} ssh -o StrictHostKeyChecking=no -p ${PKG_RSYNC_SSH_PORT} \
1446
					${PKG_RSYNC_USERNAME}@${_pkg_rsync_hostname} ${_cmd} >/dev/null 2>&1; then
1447
					echo "Done!" | tee -a ${_logfile}
1448
				else
1449
					echo "Failed!" | tee -a ${_logfile}
1450
					echo ">>> ERROR: An error occurred sending repo to final hostname"
1451
					print_error_pfS
1452
				fi
1453

    
1454
				if [ -z "${PKG_FINAL_S3_PATH}" ]; then
1455
					continue
1456
				fi
1457

    
1458
				local _repos=$(ssh -o StrictHostKeyChecking=no -p ${PKG_FINAL_RSYNC_SSH_PORT} \
1459
				    ${PKG_FINAL_RSYNC_USERNAME}@${_pkg_final_rsync_hostname} \
1460
				    "ls -1d ${PKG_FINAL_RSYNC_DESTDIR}/${_repo_base%%-core}*")
1461
				for _repo in ${_repos}; do
1462
					echo -n ">>> Sending updated packages to AWS ${PKG_FINAL_S3_PATH}... " | tee -a ${_logfile}
1463
					if script -aq ${_logfile} ssh -o StrictHostKeyChecking=no -p ${PKG_FINAL_RSYNC_SSH_PORT} \
1464
					    ${PKG_FINAL_RSYNC_USERNAME}@${_pkg_final_rsync_hostname} \
1465
					    "${_aws_sync_cmd} ${_repo} ${PKG_FINAL_S3_PATH}/$(basename ${_repo})"; then
1466
						echo "Done!" | tee -a ${_logfile}
1467
					else
1468
						echo "Failed!" | tee -a ${_logfile}
1469
						echo ">>> ERROR: An error occurred sending files to AWS S3"
1470
						print_error_pfS
1471
					fi
1472
					echo -n ">>> Cleaning up packages at AWS ${PKG_FINAL_S3_PATH}... " | tee -a ${_logfile}
1473
					if script -aq ${_logfile} ssh -o StrictHostKeyChecking=no -p ${PKG_FINAL_RSYNC_SSH_PORT} \
1474
					    ${PKG_FINAL_RSYNC_USERNAME}@${_pkg_final_rsync_hostname} \
1475
					    "${_aws_sync_cmd} --delete ${_repo} ${PKG_FINAL_S3_PATH}/$(basename ${_repo})"; then
1476
						echo "Done!" | tee -a ${_logfile}
1477
					else
1478
						echo "Failed!" | tee -a ${_logfile}
1479
						echo ">>> ERROR: An error occurred sending files to AWS S3"
1480
						print_error_pfS
1481
					fi
1482
				done
1483
			done
1484
		fi
1485
	done
1486
}
1487

    
1488
poudriere_possible_archs() {
1489
	local _arch=$(uname -m)
1490
	local _archs=""
1491

    
1492
	# If host is amd64, we'll create both repos, and if possible armv6
1493
	if [ "${_arch}" = "amd64" ]; then
1494
		_archs="amd64.amd64"
1495

    
1496
		if [ -f /usr/local/bin/qemu-arm-static ]; then
1497
			# Make sure binmiscctl is ok
1498
			/usr/local/etc/rc.d/qemu_user_static forcestart >/dev/null 2>&1
1499

    
1500
			if binmiscctl lookup armv6 >/dev/null 2>&1; then
1501
				_archs="${_archs} arm.armv6"
1502
			fi
1503
		fi
1504
	fi
1505

    
1506
	if [ -n "${ARCH_LIST}" ]; then
1507
		local _found=0
1508
		for _desired_arch in ${ARCH_LIST}; do
1509
			_found=0
1510
			for _possible_arch in ${_archs}; do
1511
				if [ "${_desired_arch}" = "${_possible_arch}" ]; then
1512
					_found=1
1513
					break
1514
				fi
1515
			done
1516
			if [ ${_found} -eq 0 ]; then
1517
				echo ">>> ERROR: Impossible to build for arch: ${_desired_arch}"
1518
				print_error_pfS
1519
			fi
1520
		done
1521
		_archs="${ARCH_LIST}"
1522
	fi
1523

    
1524
	echo ${_archs}
1525
}
1526

    
1527
poudriere_jail_name() {
1528
	local _jail_arch="${1}"
1529

    
1530
	if [ -z "${_jail_arch}" ]; then
1531
		return 1
1532
	fi
1533

    
1534
	# Remove arch
1535
	echo "${PRODUCT_NAME}_${POUDRIERE_BRANCH}_${_jail_arch##*.}"
1536
}
1537

    
1538
poudriere_rename_ports() {
1539
	if [ "${PRODUCT_NAME}" = "pfSense" ]; then
1540
		return;
1541
	fi
1542

    
1543
	LOGFILE=${BUILDER_LOGS}/poudriere.log
1544

    
1545
	local _ports_dir="/usr/local/poudriere/ports/${POUDRIERE_PORTS_NAME}"
1546

    
1547
	echo -n ">>> Renaming product ports on ${POUDRIERE_PORTS_NAME}... " | tee -a ${LOGFILE}
1548
	for d in $(find ${_ports_dir} -depth 2 -type d -name '*pfSense*'); do
1549
		local _pdir=$(dirname ${d})
1550
		local _pname=$(echo $(basename ${d}) | sed "s,pfSense,${PRODUCT_NAME},")
1551
		local _plist=""
1552
		local _pdescr=""
1553

    
1554
		if [ -e ${_pdir}/${_pname} ]; then
1555
			rm -rf ${_pdir}/${_pname}
1556
		fi
1557

    
1558
		cp -r ${d} ${_pdir}/${_pname}
1559

    
1560
		if [ -f ${_pdir}/${_pname}/pkg-plist ]; then
1561
			_plist=${_pdir}/${_pname}/pkg-plist
1562
		fi
1563

    
1564
		if [ -f ${_pdir}/${_pname}/pkg-descr ]; then
1565
			_pdescr=${_pdir}/${_pname}/pkg-descr
1566
		fi
1567

    
1568
		sed -i '' -e "s,pfSense,${PRODUCT_NAME},g" \
1569
			  -e "s,https://www.pfsense.org,${PRODUCT_URL},g" \
1570
			  -e "/^MAINTAINER=/ s,^.*$,MAINTAINER=	${PRODUCT_EMAIL}," \
1571
			${_pdir}/${_pname}/Makefile ${_pdescr} ${_plist}
1572

    
1573
		# PHP module is special
1574
		if echo "${_pname}" | grep -q "^php[0-9]*-${PRODUCT_NAME}-module"; then
1575
			local _product_capital=$(echo ${PRODUCT_NAME} | tr '[a-z]' '[A-Z]')
1576
			sed -i '' -e "s,PHP_PFSENSE,PHP_${_product_capital},g" \
1577
				  -e "s,PFSENSE_SHARED_LIBADD,${_product_capital}_SHARED_LIBADD,g" \
1578
				  -e "s,pfSense,${PRODUCT_NAME},g" \
1579
				  -e "s,pfSense.c,${PRODUCT_NAME}\.c,g" \
1580
				${_pdir}/${_pname}/files/config.m4
1581

    
1582
			sed -i '' -e "s,COMPILE_DL_PFSENSE,COMPILE_DL_${_product_capital}," \
1583
				  -e "s,pfSense_module_entry,${PRODUCT_NAME}_module_entry,g" \
1584
				  -e "s,php_pfSense.h,php_${PRODUCT_NAME}\.h,g" \
1585
				  -e "/ZEND_GET_MODULE/ s,pfSense,${PRODUCT_NAME}," \
1586
				  -e "/PHP_PFSENSE_WORLD_EXTNAME/ s,pfSense,${PRODUCT_NAME}," \
1587
				${_pdir}/${_pname}/files/pfSense.c \
1588
				${_pdir}/${_pname}/files/dummynet.c \
1589
				${_pdir}/${_pname}/files/php_pfSense.h
1590
		fi
1591

    
1592
		if [ -d ${_pdir}/${_pname}/files ]; then
1593
			for fd in $(find ${_pdir}/${_pname}/files -name '*pfSense*'); do
1594
				local _fddir=$(dirname ${fd})
1595
				local _fdname=$(echo $(basename ${fd}) | sed "s,pfSense,${PRODUCT_NAME},")
1596

    
1597
				mv ${fd} ${_fddir}/${_fdname}
1598
			done
1599
		fi
1600
	done
1601
	echo "Done!" | tee -a ${LOGFILE}
1602
}
1603

    
1604
poudriere_create_ports_tree() {
1605
	LOGFILE=${BUILDER_LOGS}/poudriere.log
1606

    
1607
	if ! poudriere ports -l | grep -q -E "^${POUDRIERE_PORTS_NAME}[[:blank:]]"; then
1608
		local _branch=""
1609
		if [ -z "${POUDRIERE_PORTS_GIT_URL}" ]; then
1610
			echo ">>> ERROR: POUDRIERE_PORTS_GIT_URL is not defined"
1611
			print_error_pfS
1612
		fi
1613
		if [ -n "${POUDRIERE_PORTS_GIT_BRANCH}" ]; then
1614
			_branch="-B ${POUDRIERE_PORTS_GIT_BRANCH}"
1615
		fi
1616
		echo -n ">>> Creating poudriere ports tree, it may take some time... " | tee -a ${LOGFILE}
1617
		if ! script -aq ${LOGFILE} poudriere ports -c -p "${POUDRIERE_PORTS_NAME}" -m git -U ${POUDRIERE_PORTS_GIT_URL} ${_branch} >/dev/null 2>&1; then
1618
			echo "" | tee -a ${LOGFILE}
1619
			echo ">>> ERROR: Error creating poudriere ports tree, aborting..." | tee -a ${LOGFILE}
1620
			print_error_pfS
1621
		fi
1622
		echo "Done!" | tee -a ${LOGFILE}
1623
		poudriere_rename_ports
1624
	fi
1625
}
1626

    
1627
poudriere_init() {
1628
	local _error=0
1629
	local _archs=$(poudriere_possible_archs)
1630

    
1631
	LOGFILE=${BUILDER_LOGS}/poudriere.log
1632

    
1633
	# Sanity checks
1634
	if [ -z "${ZFS_TANK}" ]; then
1635
		echo ">>> ERROR: \$ZFS_TANK is empty" | tee -a ${LOGFILE}
1636
		error=1
1637
	fi
1638

    
1639
	if [ -z "${ZFS_ROOT}" ]; then
1640
		echo ">>> ERROR: \$ZFS_ROOT is empty" | tee -a ${LOGFILE}
1641
		error=1
1642
	fi
1643

    
1644
	if [ -z "${POUDRIERE_PORTS_NAME}" ]; then
1645
		echo ">>> ERROR: \$POUDRIERE_PORTS_NAME is empty" | tee -a ${LOGFILE}
1646
		error=1
1647
	fi
1648

    
1649
	if [ ${_error} -eq 1 ]; then
1650
		print_error_pfS
1651
	fi
1652

    
1653
	# Check if zpool exists
1654
	if ! zpool list ${ZFS_TANK} >/dev/null 2>&1; then
1655
		echo ">>> ERROR: ZFS tank ${ZFS_TANK} not found, please create it and try again..." | tee -a ${LOGFILE}
1656
		print_error_pfS
1657
	fi
1658

    
1659
	# Check if zfs rootfs exists
1660
	if ! zfs list ${ZFS_TANK}${ZFS_ROOT} >/dev/null 2>&1; then
1661
		echo -n ">>> Creating ZFS filesystem ${ZFS_TANK}${ZFS_ROOT}... "
1662
		if zfs create -o atime=off -o mountpoint=/usr/local${ZFS_ROOT} \
1663
		    ${ZFS_TANK}${ZFS_ROOT} >/dev/null 2>&1; then
1664
			echo "Done!"
1665
		else
1666
			echo "Failed!"
1667
			print_error_pfS
1668
		fi
1669
	fi
1670

    
1671
	# Make sure poudriere is installed
1672
	if [ ! -f /usr/local/bin/poudriere ]; then
1673
		echo ">>> Installing poudriere..." | tee -a ${LOGFILE}
1674
		if ! pkg install poudriere >/dev/null 2>&1; then
1675
			echo ">>> ERROR: poudriere was not installed, aborting..." | tee -a ${LOGFILE}
1676
			print_error_pfS
1677
		fi
1678
	fi
1679

    
1680
	# Create poudriere.conf
1681
	if [ -z "${POUDRIERE_PORTS_GIT_URL}" ]; then
1682
		echo ">>> ERROR: POUDRIERE_PORTS_GIT_URL is not defined"
1683
		print_error_pfS
1684
	fi
1685

    
1686
	# PARALLEL_JOBS us ncpu / 4 for best performance
1687
	local _parallel_jobs=$(sysctl -qn hw.ncpu)
1688
	_parallel_jobs=$((_parallel_jobs / 4))
1689

    
1690
	echo ">>> Creating poudriere.conf" | tee -a ${LOGFILE}
1691
	cat <<EOF >/usr/local/etc/poudriere.conf
1692
ZPOOL=${ZFS_TANK}
1693
ZROOTFS=${ZFS_ROOT}
1694
RESOLV_CONF=/etc/resolv.conf
1695
BASEFS=/usr/local/poudriere
1696
USE_PORTLINT=no
1697
USE_TMPFS=yes
1698
NOLINUX=yes
1699
DISTFILES_CACHE=/usr/ports/distfiles
1700
CHECK_CHANGED_OPTIONS=yes
1701
CHECK_CHANGED_DEPS=yes
1702
ATOMIC_PACKAGE_REPOSITORY=yes
1703
COMMIT_PACKAGES_ON_FAILURE=no
1704
KEEP_OLD_PACKAGES=yes
1705
KEEP_OLD_PACKAGES_COUNT=5
1706
ALLOW_MAKE_JOBS=yes
1707
PARALLEL_JOBS=${_parallel_jobs}
1708
EOF
1709

    
1710
	if pkg info -e ccache; then
1711
	cat <<EOF >>/usr/local/etc/poudriere.conf
1712
CCACHE_DIR=/var/cache/ccache
1713
EOF
1714
	fi
1715

    
1716
	# Create specific items conf
1717
	[ ! -d /usr/local/etc/poudriere.d ] \
1718
		&& mkdir -p /usr/local/etc/poudriere.d
1719

    
1720
	# Create DISTFILES_CACHE if it doesn't exist
1721
	if [ ! -d /usr/ports/distfiles ]; then
1722
		mkdir -p /usr/ports/distfiles
1723
	fi
1724

    
1725
	# Remove old jails
1726
	for jail_arch in ${_archs}; do
1727
		jail_name=$(poudriere_jail_name ${jail_arch})
1728

    
1729
		if poudriere jail -i -j "${jail_name}" >/dev/null 2>&1; then
1730
			echo ">>> Poudriere jail ${jail_name} already exists, deleting it..." | tee -a ${LOGFILE}
1731
			poudriere jail -d -j "${jail_name}"
1732
		fi
1733
	done
1734

    
1735
	# Remove old ports tree
1736
	if poudriere ports -l | grep -q -E "^${POUDRIERE_PORTS_NAME}[[:blank:]]"; then
1737
		echo ">>> Poudriere ports tree ${POUDRIERE_PORTS_NAME} already exists, deleting it..." | tee -a ${LOGFILE}
1738
		poudriere ports -d -p "${POUDRIERE_PORTS_NAME}"
1739
	fi
1740

    
1741
	local native_xtools=""
1742
	# Now we are ready to create jails
1743
	for jail_arch in ${_archs}; do
1744
		jail_name=$(poudriere_jail_name ${jail_arch})
1745

    
1746
		if [ "${jail_arch}" = "arm.armv6" ]; then
1747
			native_xtools="-x"
1748
		else
1749
			native_xtools=""
1750
		fi
1751

    
1752
		echo -n ">>> Creating jail ${jail_name}, it may take some time... " | tee -a ${LOGFILE}
1753
		if ! script -aq ${LOGFILE} poudriere jail -c -j "${jail_name}" -v ${FREEBSD_BRANCH} \
1754
				-a ${jail_arch} -m git -U ${FREEBSD_REPO_BASE_POUDRIERE} ${native_xtools} >/dev/null 2>&1; then
1755
			echo "" | tee -a ${LOGFILE}
1756
			echo ">>> ERROR: Error creating jail ${jail_name}, aborting..." | tee -a ${LOGFILE}
1757
			print_error_pfS
1758
		fi
1759
		echo "Done!" | tee -a ${LOGFILE}
1760
	done
1761

    
1762
	poudriere_create_ports_tree
1763

    
1764
	echo ">>> Poudriere is now configured!" | tee -a ${LOGFILE}
1765
}
1766

    
1767
poudriere_update_jails() {
1768
	local _archs=$(poudriere_possible_archs)
1769

    
1770
	LOGFILE=${BUILDER_LOGS}/poudriere.log
1771

    
1772
	local native_xtools=""
1773
	for jail_arch in ${_archs}; do
1774
		jail_name=$(poudriere_jail_name ${jail_arch})
1775

    
1776
		local _create_or_update="-u"
1777
		local _create_or_update_text="Updating"
1778
		if ! poudriere jail -i -j "${jail_name}" >/dev/null 2>&1; then
1779
			echo ">>> Poudriere jail ${jail_name} not found, creating..." | tee -a ${LOGFILE}
1780
			_create_or_update="-c -v ${FREEBSD_BRANCH} -a ${jail_arch} -m git -U ${FREEBSD_REPO_BASE_POUDRIERE}"
1781
			_create_or_update_text="Creating"
1782
		fi
1783

    
1784
		if [ "${jail_arch}" = "arm.armv6" ]; then
1785
			native_xtools="-x"
1786
		else
1787
			native_xtools=""
1788
		fi
1789

    
1790
		echo -n ">>> ${_create_or_update_text} jail ${jail_name}, it may take some time... " | tee -a ${LOGFILE}
1791
		if ! script -aq ${LOGFILE} poudriere jail ${_create_or_update} -j "${jail_name}" ${native_xtools} >/dev/null 2>&1; then
1792
			echo "" | tee -a ${LOGFILE}
1793
			echo ">>> ERROR: Error ${_create_or_update_text} jail ${jail_name}, aborting..." | tee -a ${LOGFILE}
1794
			print_error_pfS
1795
		fi
1796
		echo "Done!" | tee -a ${LOGFILE}
1797
	done
1798
}
1799

    
1800
poudriere_update_ports() {
1801
	LOGFILE=${BUILDER_LOGS}/poudriere.log
1802

    
1803
	# Create ports tree if necessary
1804
	if ! poudriere ports -l | grep -q -E "^${POUDRIERE_PORTS_NAME}[[:blank:]]"; then
1805
		poudriere_create_ports_tree
1806
	else
1807
		echo -n ">>> Resetting local changes on ports tree ${POUDRIERE_PORTS_NAME}... " | tee -a ${LOGFILE}
1808
		script -aq ${LOGFILE} git -C "/usr/local/poudriere/ports/${POUDRIERE_PORTS_NAME}" reset --hard >/dev/null 2>&1
1809
		script -aq ${LOGFILE} git -C "/usr/local/poudriere/ports/${POUDRIERE_PORTS_NAME}" clean -fd >/dev/null 2>&1
1810
		echo "Done!" | tee -a ${LOGFILE}
1811
		echo -n ">>> Updating ports tree ${POUDRIERE_PORTS_NAME}... " | tee -a ${LOGFILE}
1812
		script -aq ${LOGFILE} poudriere ports -u -p "${POUDRIERE_PORTS_NAME}" >/dev/null 2>&1
1813
		echo "Done!" | tee -a ${LOGFILE}
1814
		poudriere_rename_ports
1815
	fi
1816
}
1817

    
1818
poudriere_bulk() {
1819
	local _archs=$(poudriere_possible_archs)
1820
	local _makeconf
1821

    
1822
	# Create DISTFILES_CACHE if it doesn't exist
1823
	if [ ! -d /usr/ports/distfiles ]; then
1824
		mkdir -p /usr/ports/distfiles
1825
	fi
1826

    
1827
	LOGFILE=${BUILDER_LOGS}/poudriere.log
1828

    
1829
	if [ -n "${UPLOAD}" -a -z "${PKG_RSYNC_HOSTNAME}" ]; then
1830
		echo ">>> ERROR: PKG_RSYNC_HOSTNAME is not set"
1831
		print_error_pfS
1832
	fi
1833

    
1834
	rm -f ${LOGFILE}
1835

    
1836
	poudriere_create_ports_tree
1837

    
1838
	[ -d /usr/local/etc/poudriere.d ] || \
1839
		mkdir -p /usr/local/etc/poudriere.d
1840

    
1841
	_makeconf=/usr/local/etc/poudriere.d/${POUDRIERE_PORTS_NAME}-make.conf
1842
	if [ -f "${BUILDER_TOOLS}/conf/pfPorts/make.conf" ]; then
1843
		cp -f "${BUILDER_TOOLS}/conf/pfPorts/make.conf" ${_makeconf}
1844
	fi
1845

    
1846
	cat <<EOF >>/usr/local/etc/poudriere.d/${POUDRIERE_PORTS_NAME}-make.conf
1847
PKG_REPO_BRANCH_DEVEL=${PKG_REPO_BRANCH_DEVEL}
1848
PKG_REPO_BRANCH_RELEASE=${PKG_REPO_BRANCH_RELEASE}
1849
PKG_REPO_SERVER_DEVEL=${PKG_REPO_SERVER_DEVEL}
1850
PKG_REPO_SERVER_RELEASE=${PKG_REPO_SERVER_RELEASE}
1851
POUDRIERE_PORTS_NAME=${POUDRIERE_PORTS_NAME}
1852
PFSENSE_DEFAULT_REPO=${PFSENSE_DEFAULT_REPO}
1853
PRODUCT_NAME=${PRODUCT_NAME}
1854
REPO_BRANCH_PREFIX=${REPO_BRANCH_PREFIX}
1855
EOF
1856

    
1857
	local _value=""
1858
	for jail_arch in ${_archs}; do
1859
		eval "_value=\${PKG_REPO_BRANCH_DEVEL_${jail_arch##*.}}"
1860
		if [ -n "${_value}" ]; then
1861
			echo "PKG_REPO_BRANCH_DEVEL_${jail_arch##*.}=${_value}" \
1862
				>> ${_makeconf}
1863
		fi
1864
		eval "_value=\${PKG_REPO_BRANCH_RELEASE_${jail_arch##*.}}"
1865
		if [ -n "${_value}" ]; then
1866
			echo "PKG_REPO_BRANCH_RELEASE_${jail_arch##*.}=${_value}" \
1867
				>> ${_makeconf}
1868
		fi
1869
		eval "_value=\${PKG_REPO_SERVER_DEVEL_${jail_arch##*.}}"
1870
		if [ -n "${_value}" ]; then
1871
			echo "PKG_REPO_SERVER_DEVEL_${jail_arch##*.}=${_value}" \
1872
				>> ${_makeconf}
1873
		fi
1874
		eval "_value=\${PKG_REPO_SERVER_RELEASE_${jail_arch##*.}}"
1875
		if [ -n "${_value}" ]; then
1876
			echo "PKG_REPO_SERVER_RELEASE_${jail_arch##*.}=${_value}" \
1877
				>> ${_makeconf}
1878
		fi
1879
	done
1880

    
1881
	# Change version of pfSense meta ports for snapshots
1882
	if [ -z "${_IS_RELEASE}" ]; then
1883
		local _meta_pkg_version="$(echo "${PRODUCT_VERSION}" | sed 's,DEVELOPMENT,ALPHA,')-${DATESTRING}"
1884
		sed -i '' \
1885
			-e "/^DISTVERSION/ s,^.*,DISTVERSION=	${_meta_pkg_version}," \
1886
			-e "/^PORTREVISION=/d" \
1887
			/usr/local/poudriere/ports/${POUDRIERE_PORTS_NAME}/security/${PRODUCT_NAME}/Makefile \
1888
			/usr/local/poudriere/ports/${POUDRIERE_PORTS_NAME}/sysutils/${PRODUCT_NAME}-repo/Makefile
1889
	fi
1890

    
1891
	# Copy over pkg repo templates to pfSense-repo
1892
	mkdir -p /usr/local/poudriere/ports/${POUDRIERE_PORTS_NAME}/sysutils/${PRODUCT_NAME}-repo/files
1893
	cp -f ${PKG_REPO_BASE}/* \
1894
		/usr/local/poudriere/ports/${POUDRIERE_PORTS_NAME}/sysutils/${PRODUCT_NAME}-repo/files
1895

    
1896
	for jail_arch in ${_archs}; do
1897
		jail_name=$(poudriere_jail_name ${jail_arch})
1898

    
1899
		if ! poudriere jail -i -j "${jail_name}" >/dev/null 2>&1; then
1900
			echo ">>> Poudriere jail ${jail_name} not found, skipping..." | tee -a ${LOGFILE}
1901
			continue
1902
		fi
1903

    
1904
		_ref_bulk=${SCRATCHDIR}/poudriere_bulk.${POUDRIERE_BRANCH}.ref.${jail_arch}
1905
		rm -rf ${_ref_bulk} ${_ref_bulk}.tmp
1906
		touch ${_ref_bulk}.tmp
1907
		if [ -f "${POUDRIERE_BULK}.${jail_arch#*.}" ]; then
1908
			cat "${POUDRIERE_BULK}.${jail_arch#*.}" >> ${_ref_bulk}.tmp
1909
		fi
1910
		if [ -f "${POUDRIERE_BULK}" ]; then
1911
			cat "${POUDRIERE_BULK}" >> ${_ref_bulk}.tmp
1912
		fi
1913
		cat ${_ref_bulk}.tmp | sort -u > ${_ref_bulk}
1914

    
1915
		_bulk=${SCRATCHDIR}/poudriere_bulk.${POUDRIERE_BRANCH}.${jail_arch}
1916
		sed -e "s,%%PRODUCT_NAME%%,${PRODUCT_NAME},g" ${_ref_bulk} > ${_bulk}
1917

    
1918
		local _exclude_bulk="${POUDRIERE_BULK}.exclude.${jail_arch}"
1919
		if [ -f "${_exclude_bulk}" ]; then
1920
			mv ${_bulk} ${_bulk}.tmp
1921
			sed -e "s,%%PRODUCT_NAME%%,${PRODUCT_NAME},g" ${_exclude_bulk} > ${_bulk}.exclude
1922
			cat ${_bulk}.tmp ${_bulk}.exclude | sort | uniq -u > ${_bulk}
1923
			rm -f ${_bulk}.tmp ${_bulk}.exclude
1924
		fi
1925

    
1926
		if ! poudriere bulk -f ${_bulk} -j ${jail_name} -p ${POUDRIERE_PORTS_NAME}; then
1927
			echo ">>> ERROR: Something went wrong..."
1928
			print_error_pfS
1929
		fi
1930

    
1931
		echo ">>> Cleaning up old packages from repo..."
1932
		if ! poudriere pkgclean -f ${_bulk} -j ${jail_name} -p ${POUDRIERE_PORTS_NAME} -y; then
1933
			echo ">>> ERROR: Something went wrong..."
1934
			print_error_pfS
1935
		fi
1936

    
1937
		pkg_repo_rsync "/usr/local/poudriere/data/packages/${jail_name}-${POUDRIERE_PORTS_NAME}"
1938
	done
1939
}
1940

    
1941
# This routine is called to write out to stdout
1942
# a string. The string is appended to $SNAPSHOTSLOGFILE
1943
snapshots_update_status() {
1944
	if [ -z "$1" ]; then
1945
		return
1946
	fi
1947
	if [ -z "${SNAPSHOTS}" -a -z "${POUDRIERE_SNAPSHOTS}" ]; then
1948
		return
1949
	fi
1950
	echo "$*"
1951
	echo "`date` -|- $*" >> $SNAPSHOTSLOGFILE
1952
}
1953

    
1954
create_sha256() {
1955
	local _file="${1}"
1956

    
1957
	if [ ! -f "${_file}" ]; then
1958
		return 1
1959
	fi
1960

    
1961
	( \
1962
		cd $(dirname ${_file}) && \
1963
		sha256 $(basename ${_file}) > $(basename ${_file}).sha256 \
1964
	)
1965
}
1966

    
1967
snapshots_create_latest_symlink() {
1968
	local _image="${1}"
1969

    
1970
	if [ -z "${_image}" ]; then
1971
		return
1972
	fi
1973

    
1974
	if [ -z "${TIMESTAMP_SUFFIX}" ]; then
1975
		return
1976
	fi
1977

    
1978
	if [ ! -f "${_image}" ]; then
1979
		return
1980
	fi
1981

    
1982
	local _symlink=$(echo ${_image} | sed "s,${TIMESTAMP_SUFFIX},-latest,")
1983
	ln -sf $(basename ${_image}) ${_symlink}
1984
	ln -sf $(basename ${_image}).sha256 ${_symlink}.sha256
1985
}
1986

    
1987
snapshots_create_sha256() {
1988
	local _img=""
1989

    
1990
	for _img in ${ISOPATH} ${MEMSTICKPATH} ${MEMSTICKSERIALPATH} ${MEMSTICKADIPATH} ${OVAPATH} ${VARIANTIMAGES}; do
1991
		if [ -f "${_img}.gz" ]; then
1992
			_img="${_img}.gz"
1993
		fi
1994
		if [ ! -f "${_img}" ]; then
1995
			continue
1996
		fi
1997
		create_sha256 ${_img}
1998
		snapshots_create_latest_symlink ${_img}
1999
	done
2000
}
2001

    
2002
snapshots_scp_files() {
2003
	if [ -z "${RSYNC_COPY_ARGUMENTS}" ]; then
2004
		RSYNC_COPY_ARGUMENTS="-Have \"ssh -o StrictHostKeyChecking=no\" --timeout=60"
2005
	fi
2006

    
2007
	snapshots_update_status ">>> Copying core pkg repo to ${PKG_RSYNC_HOSTNAME}"
2008
	pkg_repo_rsync "${CORE_PKG_PATH}"
2009
	snapshots_update_status ">>> Finished copying core pkg repo"
2010

    
2011
	for _rsyncip in ${RSYNCIP}; do
2012
		snapshots_update_status ">>> Copying files to ${_rsyncip}"
2013

    
2014
		# Ensure directory(s) are available
2015
		ssh -o StrictHostKeyChecking=no ${RSYNCUSER}@${_rsyncip} "mkdir -p ${RSYNCPATH}/installer"
2016
		if [ -d $IMAGES_FINAL_DIR/virtualization ]; then
2017
			ssh -o StrictHostKeyChecking=no ${RSYNCUSER}@${_rsyncip} "mkdir -p ${RSYNCPATH}/virtualization"
2018
		fi
2019
		# ensure permissions are correct for r+w
2020
		ssh -o StrictHostKeyChecking=no ${RSYNCUSER}@${_rsyncip} "chmod -R ug+rw ${RSYNCPATH}/."
2021
		rsync $RSYNC_COPY_ARGUMENTS $IMAGES_FINAL_DIR/installer/* \
2022
			${RSYNCUSER}@${_rsyncip}:${RSYNCPATH}/installer/
2023
		if [ -d $IMAGES_FINAL_DIR/virtualization ]; then
2024
			rsync $RSYNC_COPY_ARGUMENTS $IMAGES_FINAL_DIR/virtualization/* \
2025
				${RSYNCUSER}@${_rsyncip}:${RSYNCPATH}/virtualization/
2026
		fi
2027

    
2028
		snapshots_update_status ">>> Finished copying files."
2029
	done
2030
}
(2-2/3)