Project

General

Profile

Download (20.8 KB) Statistics
| Branch: | Tag: | Revision:
1
#!/bin/sh
2

    
3
# Copyright (c) 2015 Electric Sheep Fencing, LLC. 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 are met:
7
#
8
# 1. Redistributions of source code must retain the above copyright notice,
9
#    this list of conditions and the following disclaimer.
10
#
11
# 2. Redistributions in binary form must reproduce the above copyright
12
#    notice, this list of conditions and the following disclaimer in
13
#    the documentation and/or other materials provided with the
14
#    distribution.
15
#
16
# 3. All advertising materials mentioning features or use of this software
17
#    must display the following acknowledgment:
18
#    "This product includes software developed by the pfSense Project
19
#    for use in the pfSense® software distribution. (http://www.pfsense.org/).
20
#
21
# 4. The names "pfSense" and "pfSense Project" must not be used to
22
#    endorse or promote products derived from this software without
23
#    prior written permission. For written permission, please contact
24
#    coreteam@pfsense.org.
25
#
26
# 5. Products derived from this software may not be called "pfSense"
27
#    nor may "pfSense" appear in their names without prior written
28
#    permission of the Electric Sheep Fencing, LLC.
29
#
30
# 6. Redistributions of any form whatsoever must retain the following
31
#    acknowledgment:
32
#
33
# "This product includes software developed by the pfSense Project
34
# for use in the pfSense software distribution (http://www.pfsense.org/).
35
#
36
# THIS SOFTWARE IS PROVIDED BY THE pfSense PROJECT ``AS IS'' AND ANY
37
# EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
38
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
39
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE pfSense PROJECT OR
40
# ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
42
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
43
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
45
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
46
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
47
# OF THE POSSIBILITY OF SUCH DAMAGE.
48

    
49
usage() {
50
	echo "Usage: $(basename ${0}) [-46bdyf] [-u|-i PKG_NAME|-r PKG_NAME]" >&2
51
	echo "	-4          - Force IPv4"
52
	echo "	-6          - Force IPv6"
53
	echo "	-b          - Platform is booting" >&2
54
	echo "	-c          - Check if upgrade is necessary" >&2
55
	echo "	-d          - Turn on debug" >&2
56
	echo "	-f          - Force package installation" >&2
57
	echo "	-h          - Show this usage help" >&2
58
	echo "	-l          - Logfile path (defaults to /cf/conf/upgrade_log.txt)" >&2
59
	echo "	-p socket   - Write pkg progress to socket"
60
	echo "	-R          - Do not reboot (this can be dangerous)"
61
	echo "	-y          - Assume yes as the answer to any possible interaction" >&2
62
	echo "" >&2
63
	echo "The following parameters are mutually exclusive:" >&2
64
	echo "	-i PKG_NAME - Install package PKG_NAME" >&2
65
	echo "	-r PKG_NAME - Remove package PKG_NAME" >&2
66
	echo "	-u          - Update repository information" >&2
67
}
68

    
69
_echo() {
70
	local _n=""
71
	if [ "${1}" = "-n" ]; then
72
		shift
73
		_n="-n"
74
	fi
75

    
76
	if [ -z "${logfile}" ]; then
77
		logfile=/dev/null
78
	fi
79

    
80
	echo ${_n} "${1}" | tee -a ${logfile}
81
}
82

    
83
_exec() {
84
	local _cmd="${1}"
85
	local _msg="${2}"
86
	local _mute="${3}"
87
	local _ignore_result="${4}"
88
	local _stdout="${stdout}"
89

    
90
	if [ -z "${_cmd}" -o -z "${_msg}" ]; then
91
		return 1
92
	fi
93

    
94
	if [ "${_mute}" != "mute" ]; then
95
		_stdout=''
96
	fi
97

    
98
	_echo -n ">>> ${_msg}... "
99
	if [ -z "${_stdout}" ]; then
100
		_echo ""
101
		# Ref. http://stackoverflow.com/questions/1221833/bash-pipe-output-and-capture-exit-status
102
		exec 4>&1
103
		local _result=$({ { ${_cmd} 2>&1 3>&-; printf $? 1>&3; } 4>&- | \
104
			tee -a ${logfile} 1>&4; } 3>&1)
105
		exec 4>&-
106
	else
107
		# Ref. http://stackoverflow.com/questions/1221833/bash-pipe-output-and-capture-exit-status
108
		exec 4>&1
109
		local _result=$({ { ${_cmd} >${_stdout} 2>&1 3>&-; printf $? 1>&3; } 4>&- | \
110
			tee -a ${logfile} 1>&4; } 3>&1)
111
		exec 4>&-
112
	fi
113

    
114
	if [ ${_result} -eq 0 -o -n "${_ignore_result}" ]; then
115
		[ -n "${_stdout}" ] \
116
			&& _echo "done."
117
		return 0
118
	else
119
		[ -n "${_stdout}" ] \
120
			&& _echo "failed."
121
		_exit 1
122
	fi
123
}
124

    
125
_exit() {
126
	trap "-" 1 2 15 EXIT
127

    
128
	pkg_lock ${kernel_pkg}
129

    
130
	if [ -f "${pid_file}" ]; then
131
		rm -f ${pid_file}
132
	fi
133

    
134
	if [ -n "${chroot_dir}" ]; then
135
		umount -f ${chroot_dir} >/dev/null 2>&1
136
	fi
137

    
138
	if [ -z "${booting}" -o "${boot_stage}" != "2" ]; then
139
		/etc/rc.conf_mount_ro
140
	fi
141

    
142
	local _rc=${1:-"0"}
143

    
144
	# If EVENT_PIPE is defined, GUI is calling
145
	[ -n "${progress_socket}" ] \
146
		&& _echo "__RC=${_rc}"
147

    
148
	exit ${_rc}
149
}
150

    
151
pkg_with_pb() {
152
	local _event_pipe=""
153

    
154
	if [ -n "${progress_socket}" ]; then
155
		if [ -e "${progress_socket}" ]; then
156
			rm -f ${progress_socket}
157
		fi
158

    
159
		_event_pipe="-o EVENT_PIPE=${progress_socket}"
160

    
161
		nc -lU ${progress_socket} >> ${progress_file} &
162

    
163
		while [ ! -e "${progress_socket}" ]; do
164
			sleep 0.1
165
		done
166
	fi
167

    
168
	pkg ${_event_pipe} $@
169
	return $?
170
}
171

    
172
fetch_upgrade_packages() {
173
	local _pkgs_to_fetch=""
174
	if [ "${platform}" = "nanobsd" ]; then
175
		local _pkg=""
176

    
177
		# Check if all non-auto packages installed on 2nd partition are
178
		# installed on current one, if not, mark them to be deleted by
179
		# pkg autoremove
180
		for _pkg in $(pkg ${pkg_chroot} query -e '%a == 0' %n); do
181
			if ! pkg info -e ${_pkg}; then
182
				_exec "pkg ${pkg_chroot} set -A 1 ${_pkg}" "Scheduling package ${_pkg} for removal"
183
			fi
184
		done
185

    
186
		# Check if all non-auto packages installed on current partition are
187
		# installed on 2nd one, if not, we need to fetch them
188
		for _pkg in $(pkg query -e '%a == 0' %n); do
189
			if ! pkg ${pkg_chroot} info -e ${_pkg}; then
190
				_pkgs_to_fetch="${_pkgs_to_fetch}${_pkgs_to_fetch:+ }${_pkg}"
191
			fi
192
		done
193

    
194
	fi
195

    
196
	_echo ">>> Downloading upgrade packages..."
197
	if ! pkg_with_pb ${pkg_chroot} upgrade -F 2>&1 | tee -a ${logfile}; then
198
		_echo "ERROR: It was not possible to download packages"
199
		_exit 1
200
	fi
201

    
202
	if [ -n "${_pkgs_to_fetch}" ]; then
203
		_echo ">>> Fetching packages not present on upgrade partition..."
204
		if ! pkg_with_pb ${pkg_chroot} fetch -d ${_pkgs_to_fetch} 2>&1 | tee -a ${logfile}; then
205
			_echo "ERROR: It was not possible to fetch packages"
206
			_exit 1
207
		fi
208
	fi
209
}
210

    
211
pkg_lock() {
212
	local _pkg="${1}"
213

    
214
	if [ -z "${_pkg}" ]; then
215
		return
216
	fi
217

    
218
	if [ "$(pkg ${pkg_chroot} query %k ${_pkg})" = "0" ]; then
219
		_exec "pkg ${pkg_chroot} lock ${_pkg}" "Locking package ${_pkg}" mute
220
	fi
221
}
222

    
223
pkg_unlock() {
224
	local _pkg="${1}"
225

    
226
	if [ -z "${_pkg}" ]; then
227
		return
228
	fi
229

    
230
	if [ "$(pkg ${pkg_chroot} query %k ${_pkg})" = "1" ]; then
231
		_exec "pkg ${pkg_chroot} unlock ${_pkg}" "Unlocking package ${_pkg}" mute
232
	fi
233
}
234

    
235
pkg_update() {
236
	local _run_update=1
237

    
238
	local _force=""
239
	if [ "${1}" = "force" ]; then
240
		local _force=1
241
	fi
242

    
243
	if [ -z "${_force}" -a -f ${last_update_file} ]; then
244
		local _last_update=$(head -n 1 ${last_update_file})
245
		# Verify if content contain only numbers
246
		if echo "${_last_update}" | grep -E -q '^[0-9]+$'; then
247
			local _now=$(date +%s)
248
			# Only run update hourly, and if last update is in the future
249
			[ ${_now} -gt ${_last_update} -a $((${_now} - ${_last_update})) -le $((60 * 60)) ] \
250
				&& unset _run_update
251
		fi
252
	fi
253

    
254
	[ -z "${_run_update}" ] \
255
		&& return 0
256

    
257
	_exec "pkg ${pkg_chroot} update" "Updating repositories" mute
258
	date +%s > ${last_update_file}
259
}
260

    
261
pkg_upgrade() {
262
	# figure out which kernel variant is running
263
	export kernel_pkg=$(pkg query %n $(pkg info ${product}-kernel-\* | grep -v -- -debug-))
264

    
265
	if [ -z "${kernel_pkg}" ]; then
266
		_echo "ERROR: It was not possible to identify which ${product} kernel is installed"
267
		_exit 1
268
	fi
269

    
270
	export next_stage=$(pkg annotate -q -S ${kernel_pkg} next_stage)
271

    
272
	if [ -n "${next_stage}" -a -n "${booting}" -a -n "${boot_stage}" ]; then
273
		if [ ${boot_stage} != ${next_stage} ]; then
274
			_exit 0
275
		fi
276
	fi
277

    
278
	# If it's booting and first stage didn't run, just exit
279
	if [ -n "${booting}" -a -z "${next_stage}" ]; then
280
		_exit 0
281
	fi
282

    
283
	unset need_reboot
284
	# First upgrade stage
285
	if [ -z "${next_stage}" ]; then
286
		if [ -f "${logfile}" ]; then
287
			rm -f ${logfile}
288
		fi
289

    
290
		pkg_update
291

    
292
		if [ "$(compare_pkg_version pkg)" = "<" ]; then
293
			_exec "pkg upgrade pkg" "Upgrading pkg" mute
294
			pkg_update force
295
		fi
296

    
297
		if [ $(pkg upgrade -nq | wc -l) -le 1 ]; then
298
			_echo "Your packages are up to date"
299
			_exit 0
300
		fi
301

    
302
		if [ $(pkg upgrade -r ${product}-core -nq | wc -l) -gt 1 ]; then
303
			if [ "${platform}" = "nanobsd" ]; then
304
				_echo "**** WARNING ****"
305
				_echo "Duplicate slice required!!"
306
				_echo ""
307
				_echo "Before start upgrade process, current mounted nanobsd partition"
308
				_echo "needs to be cloned to secondary partition, where update will happen"
309
				_echo ""
310
				if [ -z "${yes}" ]; then
311
					_echo -n "Proceed with upgrade? (y/N) "
312
					read answer
313
					if [ "${answer}" != "y" ]; then
314
						_echo "Aborting..."
315
						_exit 0
316
					fi
317
				fi
318
			fi
319
			setup_nanobsd_env
320
			need_reboot=1
321
		fi
322

    
323
		pkg_unlock ${kernel_pkg}
324

    
325
		if [ -z "${yes}" ]; then
326
			# Show user which packages are going to be upgraded
327
			pkg ${pkg_chroot} upgrade -nq 2>&1 | tee -a ${logfile}
328

    
329
			_echo ""
330
			if [ -n "${need_reboot}" ]; then
331
				_echo "**** WARNING ****"
332
				_echo "Reboot will be required!!"
333
			fi
334
			_echo -n "Proceed with upgrade? (y/N) "
335
			read answer
336
			if [ "${answer}" != "y" ]; then
337
				_echo "Aborting..."
338
				_exit 0
339
			fi
340
		fi
341

    
342
		# Download all upgrade packages first
343
		fetch_upgrade_packages
344

    
345
		if [ $(pkg ${pkg_chroot} upgrade -nq ${kernel_pkg} | wc -l) -gt 1 ]; then
346
			_exec "pkg ${pkg_chroot} upgrade ${kernel_pkg}" "Upgrading ${product} kernel"
347
		fi
348

    
349
		pkg ${pkg_chroot} annotate -q -M ${kernel_pkg} next_stage 2
350
		next_stage=2
351

    
352
		if [ -n "${need_reboot}" -a "${platform}" != "nanobsd" ]; then
353
			do_reboot
354
			_exit 0
355
		fi
356
	fi
357

    
358
	if [ "${next_stage}" = "2" ]; then
359
		pkg_lock "${pkg_prefix}*"
360

    
361
		# XXX: Workaround to upgrade strongswan
362
		# If those symlinks are present, pkg exit because it expects them
363
		# to be a directory
364
		if [ $(pkg ${pkg_chroot} upgrade -nq strongswan | wc -l) -gt 1 ]; then
365
			if [ -L ${chroot_dir}/usr/local/etc/ipsec.d ]; then
366
				rm -f ${chroot_dir}/usr/local/etc/ipsec.d
367
			fi
368
			if [ -L ${chroot_dir}/usr/local/etc/ipsec.conf ]; then
369
				rm -f ${chroot_dir}/usr/local/etc/ipsec.conf
370
			fi
371
			if [ -L ${chroot_dir}/usr/local/etc/strongswan.d ]; then
372
				rm -f ${chroot_dir}/usr/local/etc/strongswan.d
373
			fi
374
			if [ -L ${chroot_dir}/usr/local/etc/strongswan.conf ]; then
375
				rm -f ${chroot_dir}/usr/local/etc/strongswan.conf
376
			fi
377
		fi
378

    
379
		if [ $(pkg ${pkg_chroot} upgrade -nq | wc -l) -gt 1 ]; then
380
			_echo "Upgrading necessary packages..."
381
			if ! pkg ${pkg_chroot} upgrade 2>&1 | tee -a ${logfile}; then
382
				pkg ${pkg_chroot} annotate -q -D ${kernel_pkg} next_stage
383
				pkg_unlock "${pkg_prefix}*"
384
				_echo "ERROR: An error occurred when upgrade was running..."
385
				_exit 1
386
			fi
387
		fi
388

    
389
		# XXX: workaround for #5300
390
		sort -u ${chroot_dir}/usr/local/etc/php/extensions.ini > /tmp/extensions.ini
391
		mv /tmp/extensions.ini ${chroot_dir}/usr/local/etc/php/extensions.ini
392

    
393
		pkg ${pkg_chroot} annotate -q -M ${kernel_pkg} next_stage 3
394
		next_stage=3
395

    
396
		pkg_unlock "${pkg_prefix}*"
397

    
398
		if [ -n "${need_reboot}" -a "${platform}" = "nanobsd" ]; then
399
			switch_active_nanobsd_partition
400
			do_reboot
401
			_exit 0
402
		fi
403

    
404
		if [ -n "${booting}" ]; then
405
			_exit 0
406
		fi
407
	fi
408

    
409
	if [ "${next_stage}" = "3" ]; then
410
		if [ $(pkg upgrade -nq | wc -l) -gt 1 ]; then
411
			_echo "Upgrading necessary packages..."
412
			if ! pkg ${pkg_chroot} upgrade 2>&1 | tee -a ${logfile}; then
413
				pkg ${pkg_chroot} annotate -q -D ${kernel_pkg} next_stage
414
				_echo "ERROR: An error occurred when upgrade was running..."
415
				_exit 1
416
			fi
417
		fi
418

    
419
		pkg ${pkg_chroot} annotate -q -D ${kernel_pkg} next_stage
420

    
421
		# cleanup caches
422
		_exec "pkg ${pkg_chroot} autoremove" "Removing unnecessary packages" mute ignore_result
423
		_exec "pkg ${pkg_chroot} clean" "Cleanup pkg cache" mute ignore_result
424
	fi
425

    
426
	gitsync=$(/usr/local/sbin/read_xml_tag.sh boolean system/gitsync/synconupgrade)
427
	if [ "${gitsync}" = "true" ]; then
428
		repository_url=$(/usr/local/sbin/read_xml_tag.sh string system/gitsync/repositoryurl)
429
		branch=$(/usr/local/sbin/read_xml_tag.sh string system/gitsync/branch)
430

    
431
		# Repository URL is not mandatory
432
		if [ -n "${branch}" ]; then
433
			/usr/local/sbin/pfSsh.php playback gitsync \
434
				${repositoryurl} ${branch} --upgrading
435
		fi
436
	fi
437
}
438

    
439
check_upgrade() {
440
	# figure out main meta package name
441
	if is_pkg_installed ${product}-vmware; then
442
		local _meta_pkg="${product}-vmware"
443
	elif is_pkg_installed ${product}; then
444
		local _meta_pkg="${product}"
445
	else
446
		_echo "ERROR: It was not possible to identify which ${product} meta package is installed"
447
		_exit 1
448
	fi
449

    
450
	pkg_update
451

    
452
	if [ "$(compare_pkg_version ${_meta_pkg})" = "<" ]; then
453
		local _new_version=$(pkg rquery %v ${_meta_pkg})
454
		_echo "${_new_version} version of ${product} is available"
455
		_exit 2
456
	else
457
		for _pkg in $(pkg query -e "%n ~ ${product}-*" %n); do
458
			# Ignore additional packages
459
			if echo "${_pkg}" | grep -q "^${pkg_prefix}"; then
460
				continue
461
			fi
462
			if [ "$(compare_pkg_version ${_pkg})" = "<" ]; then
463
				local _new_version=$(pkg rquery %v ${_pkg})
464
				_echo "${_new_version} version of ${_pkg} is available"
465
				_exit 2
466
			fi
467
		done
468
	fi
469

    
470
	_echo "Your system is up to date"
471
	_exit 0
472
}
473

    
474
setup_nanobsd_env() {
475
	if [ "${platform}" != "nanobsd" ]; then
476
		return;
477
	fi
478

    
479
	chroot_dir=/tmp/nanobsd_upgrade
480
	mkdir -p ${chroot_dir} 2>/dev/null
481
	local _cur_partition=$(mount -p / | cut -f1)
482
	local _update_partition=$(echo ${_cur_partition} | sed -e 's,0$,2,; s,1$,0,; s,2$,1,')
483

    
484
	if [ ! -e "${_update_partition}" ]; then
485
		_echo "Secondary partition (${_update_partition}), used for upgrade not found"
486
		_exit 1
487
	fi
488

    
489
	# Remove /dev
490
	_update_partition=$(echo ${_update_partition} | sed 's,^/dev/,,')
491
	local _update_slice=$(glabel status -s | awk "\$1 == \"${_update_partition}\" { print \$3 }")
492

    
493
	if [ -z "${_update_slice}" -o ! -e "/dev/${_update_slice}" ]; then
494
		_echo "Secondary slice (${_update_slice}), use_update_sliced for upgrade not found"
495
		_exit 1
496
	fi
497

    
498
	_update_slice="/dev/${_update_slice}"
499

    
500
	# Clone slice using same logic from nanobsd_clone_slice()
501
	sysctl kern.geom.debugflags=16 >/dev/null 2>&1
502
	_exec "dd if=/dev/zero of=${_update_slice} bs=1m count=1" "Cleaning secondary partition" mute
503
	_exec "dd if=${_cur_partition} of=${_update_slice} bs=64k" "Duplicating current slice" mute
504
	_exec "tunefs -L ${_update_partition##*/} ${_update_slice}" "Restoring slice label" mute
505
	sysctl kern.geom.debugflags=0 >/dev/null 2>&1
506

    
507
	_exec "mount /dev/${_update_partition} ${chroot_dir}" "Mounting second partition to run upgrade" mute
508

    
509
	sed -i '' -e "s,^${_cur_partition},/dev/${_update_partition}," \
510
		${chroot_dir}/etc/fstab
511

    
512
	pkg_chroot="-c ${chroot_dir}"
513
}
514

    
515
switch_active_nanobsd_partition() {
516
	if [ "${platform}" != "nanobsd" ]; then
517
		return;
518
	fi
519

    
520
	local _cur_partition=$(mount -p / | cut -f1 | sed 's,^/dev/,,')
521
	local _disk=$(glabel status -s | \
522
		awk "\$1 == \"${_cur_partition}\" { print substr(\$3, 0, length(\$3)-3)}")
523
	local _i=$(echo ${_cur_partition} | cut -c ${#_cur_partition})
524

    
525
	if ! echo "${_i}" | egrep -q '^[0-9]$'; then
526
		_echo "Invalid partition label ${_cur_partition}"
527
		_exit 1
528
	fi
529

    
530
	# pfsense0 == part 1 / pfsense1 == part 2
531
	if [ ${_i} -eq 0 ]; then
532
		_i=2
533
	else
534
		_i=1
535
	fi
536

    
537
	_exec "gpart set -a active -i ${_i} ${_disk}" "Setting secondary partition as active" mute
538
}
539

    
540
is_pkg_installed() {
541
	local _pkg_name="${1}"
542
	shift
543
	local _pkg_chroot="$@"
544

    
545
	pkg ${_pkg_chroot} info -e ${_pkg_name}
546
	return $?
547
}
548

    
549
compare_pkg_version() {
550
	local _pkg_name="${1}"
551

    
552
	if ! is_pkg_installed ${_pkg_name} ${pkg_chroot}; then
553
		echo '!'
554
		return -1
555
	fi
556

    
557
	local _lver=$(pkg ${pkg_chroot} query %v ${_pkg_name})
558

    
559
	if [ -z "${_lver}" ]; then
560
		_echo "ERROR: It was not possible to determine ${_pkg_name} local version"
561
		_exit 1
562
	fi
563

    
564
	local _rver=$(pkg ${pkg_chroot} rquery %v ${_pkg_name})
565

    
566
	if [ -z "${_rver}" ]; then
567
		_echo "ERROR: It was not possible to determine ${_pkg_name} remote version"
568
		_exit 1
569
	fi
570

    
571
	local _version=$(pkg version -t ${_lver} ${_rver})
572

    
573
	if [ $? -ne 0 ]; then
574
		_echo "ERROR: Error comparing ${_pkg_name} local and remote versions"
575
		_exit 1
576
	fi
577

    
578
	echo ${_version}
579
	return 0
580
}
581

    
582
pkg_install() {
583
	local _pkg_name="${1}"
584

    
585
	local _force=""
586
	if [ -n "${2}" ]; then
587
		_force="-f"
588
	fi
589

    
590
	if [ -z "${_pkg_name}" ]; then
591
		_echo "ERROR: Blank package name"
592
		_exit 1
593
	fi
594

    
595
	pkg_update
596

    
597
	if is_pkg_installed ${_pkg_name}; then
598
		local _cversion=$(compare_pkg_version ${_pkg_name})
599

    
600
		if [ -z "${_force}" ]; then
601
			if [ "${_cversion}" = "=" ]; then
602
				_echo "Package ${_pkg_name} is up to date"
603
				_exit 0
604
			elif [ "${_cversion}" = ">" ]; then
605
				_echo "Installed ${_pkg_name} version is newer than remote"
606
				_exit 0
607
			fi
608
		fi
609
		local _cmd="upgrade ${_force}"
610
		local _msg="Upgrading"
611
	else
612
		local _cmd="install"
613
		local _msg="Installing"
614
	fi
615

    
616
	_exec "pkg_with_pb ${_cmd} ${_pkg_name}" "${_msg} ${_pkg_name}"
617
	_exec "pkg clean" "Cleaning up cache" mute ignore_result
618
}
619

    
620
pkg_delete() {
621
	local _pkg_name="${1}"
622

    
623
	if [ -z "${_pkg_name}" ]; then
624
		_echo "ERROR: Blank package name"
625
		_exit 1
626
	fi
627

    
628
	if ! is_pkg_installed ${_pkg_name}; then
629
		_echo "ERROR: Package ${_pkg_name} is not installed"
630
		_exit 1
631
	fi
632

    
633
	_exec "pkg_with_pb delete ${_pkg_name}" "Removing ${_pkg_name}"
634
	_exec "pkg autoremove" "Removing stale packages" mute ignore_result
635
}
636

    
637
# Reinstall every pfSense-pkg-* package
638
pkg_reinstall_all() {
639
	for _pkg in $(pkg query -e '%a == 0' %n); do
640
		case ${_pkg} in "${pkg_prefix}"* )
641
			_echo "Reinstalling ${_pkg}"
642
			pkg_install ${_pkg} 1
643
			;;
644
		esac
645
	done
646
}
647

    
648
do_reboot() {
649
	_echo "Upgrade is complete.  Rebooting in 10 seconds."
650
	echo "Upgrade is complete.  Rebooting in 10 seconds." | wall
651
	/etc/rc.notify_message -e -g -m "Upgrade is complete.  Rebooting in 10 seconds."
652
	if [ -z "${dont_reboot}" ]; then
653
		(sleep 10 && /etc/rc.reboot) &
654
	fi
655
}
656

    
657
pid_file="/var/run/$(basename $0).pid"
658
last_update_file="/var/run/$(basename $0)-last-update"
659
logfile="/cf/conf/upgrade_log.txt"
660
stdout='/dev/null'
661

    
662
# pkg should not ask for confirmations
663
export ASSUME_ALWAYS_YES=true
664

    
665
# Disable automatic update
666
export REPO_AUTOUPDATE=false
667

    
668
export product=$(/usr/local/bin/php -n /usr/local/sbin/read_global_var product_name pfSense)
669
export pkg_prefix=$(/usr/local/bin/php -n /usr/local/sbin/read_global_var pkg_prefix pfSense-pkg-)
670
export platform=$(cat /etc/platform)
671

    
672
USE_MFS_TMPVAR=$(/usr/local/sbin/read_xml_tag.sh boolean system/use_mfs_tmpvar)
673
if [ "${platform}" = "nanobsd" ] || [ "${USE_MFS_TMPVAR}" = "true" ]; then
674
	export PKG_DBDIR=/root/var/db/pkg
675
	export PKG_CACHEDIR=/root/var/cache/pkg
676
fi
677

    
678
product_version=$(cat /etc/version)
679
do_not_send_host_uuid=$(/usr/local/sbin/read_xml_tag.sh boolean system/do_not_send_host_uuid)
680
if [ "${do_not_send_host_uuid}" != "true" ]; then
681
	hostuuid=$(sysctl kern.hostuuid)
682
	export HTTP_USER_AGENT="${product}/${product_version}:${hostuuid}"
683
else
684
	export HTTP_USER_AGENT="${product}/${product_version}"
685
fi
686

    
687
# Upgrade process on nanobsd will happen in chroot
688
export pkg_chroot=""
689
export chroot_dir=""
690

    
691
unset dont_reboot
692
unset booting
693
unset boot_stage
694
unset force
695
unset yes
696
unset progress_file
697
unset progress_socket
698
unset action
699
unset action_pkg
700
unset force_ipv4
701
unset force_ipv6
702
while getopts 46b:cdfi:hp:l:r:Ruy opt; do
703
	case ${opt} in
704
		4)
705
			if [ -n "${force_ipv6}" ]; then
706
				usage
707
				_exit 1
708
			fi
709
			force_ipv4=1
710
			;;
711
		6)
712
			if [ -n "${force_ipv4}" ]; then
713
				usage
714
				_exit 1
715
			fi
716
			force_ipv6=1
717
			;;
718
		b)
719
			booting=1
720
			boot_stage="${OPTARG}"
721
			;;
722
		c)
723
			action="check"
724
			;;
725
		d)
726
			stdout=''
727
			;;
728
		f)
729
			force=1
730
			;;
731
		i)
732
			if [ -n "${action}" ]; then
733
				usage
734
				_exit 1
735
			fi
736
			action="install"
737
			action_pkg="${OPTARG}"
738
			;;
739
		h)
740
			usage
741
			_exit 0
742
			;;
743
		l)
744
			logfile="${OPTARG}"
745
			if [ -z "${logfile}" ]; then
746
				usage
747
				_exit 1
748
			fi
749
			;;
750
		p)
751
			progress_socket="${OPTARG}"
752
			if [ -z "${progress_socket}" ]; then
753
				usage
754
				_exit 1
755
			fi
756
			;;
757
		r)
758
			if [ -n "${action}" ]; then
759
				usage
760
				_exit 1
761
			fi
762
			action="delete"
763
			action_pkg="${OPTARG}"
764
			;;
765
		R)
766
			dont_reboot=1
767
			;;
768
		u)
769
			if [ -n "${action}" ]; then
770
				usage
771
				_exit 1
772
			fi
773
			action="update"
774
			;;
775
		y)
776
			yes=1
777
			;;
778
		*)
779
			usage
780
			_exit 1
781
			;;
782
	esac
783
done
784

    
785
if [ -n "${force_ipv4}" ]; then
786
	export IP_VERSION="4"
787
elif [ -n "${force_ipv6}" ]; then
788
	export IP_VERSION="6"
789
fi
790

    
791
# Set default action when no parameter is set
792
: ${action:="upgrade"}
793

    
794
if pgrep -qF ${pid_file} >/dev/null 2>&1; then
795
	echo "Another instance is already running... Aborting!"
796
	exit 1
797
fi
798

    
799
if [ -z "${booting}" -o "${boot_stage}" != "2" ]; then
800
	/etc/rc.conf_mount_rw
801
fi
802

    
803
echo $$ > ${pid_file}
804

    
805
trap _exit 1 2 15 EXIT
806

    
807
if [ "${action}" != "upgrade" -a -f "${logfile}" ]; then
808
	rm -f ${logfile}
809
fi
810

    
811
progress_file=${logfile%.*}.json
812

    
813
if [ -e "${progress_file}" ]; then
814
	rm -f ${progress_file}
815
fi
816

    
817
case "${action}" in
818
	check)
819
		check_upgrade
820
		;;
821
	upgrade)
822
		pkg_upgrade
823
		;;
824
	update)
825
		pkg_update force
826
		;;
827
	install)
828
		if [ ${action_pkg} == "ALL_PACKAGES" ] && [ -n ${force} ]; then
829
			pkg_reinstall_all
830
		else
831
			pkg_install ${action_pkg} ${force}
832
		fi
833
		;;
834
	delete)
835
		pkg_delete ${action_pkg}
836
		;;
837
	*)
838
		_echo "ERROR: Invalid action!"
839
		_exit 1
840
esac
841

    
842
_exit 0
(10-10/23)