Project

General

Profile

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

    
3
# Copyright (c) 2004-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
pid_file="/var/run/$(basename $0).pid"
50

    
51
# pkg should not ask for confirmations
52
export ASSUME_ALWAYS_YES=true
53

    
54
# Disable automatic update
55
export REPO_AUTOUPDATE=false
56

    
57
# File used to detect second call, after kernel update and reboot
58
upgrade_in_progress="/cf/conf/upgrade_in_progress"
59

    
60
stdout='/dev/null'
61
unset yes
62
while getopts dys opt; do
63
	case ${opt} in
64
		d)
65
			stdout=''
66
			;;
67
		y)
68
			yes=1
69
			;;
70
		*)
71
			usage
72
			exit 1
73
			;;
74
	esac
75
done
76

    
77
usage() {
78
	_echo "Usage: $(basename ${0}) [-d] [-y] [-c]"
79
}
80

    
81
_echo() {
82
	local _n=""
83
	if [ "${1}" = "-n" ]; then
84
		shift
85
		_n="-n"
86
	fi
87

    
88
	if [ -z "${logfile}" ]; then
89
		logfile=/dev/null
90
	fi
91

    
92
	echo ${_n} "${1}" | tee -a ${logfile}
93
}
94

    
95
_exec() {
96
	local _cmd="${1}"
97
	local _msg="${2}"
98
	local _mute="${3}"
99
	local _ignore_result="${4}"
100
	local _stdout="${stdout}"
101

    
102
	if [ -z "${_cmd}" -o -z "${_msg}" ]; then
103
		return 1
104
	fi
105

    
106
	if [ "${_mute}" != "mute" ]; then
107
		_stdout=''
108
	fi
109

    
110
	_echo -n ">>> ${_msg}... "
111
	if [ -z "${_stdout}" ]; then
112
		_echo ""
113
		${_cmd} 2>&1 | tee -a ${logfile}
114
	else
115
		${_cmd} >${_stdout} 2>&1 | tee -a ${logfile}
116
	fi
117
	local _result=$?
118

    
119
	if [ ${_result} -eq 0 -o -n "${_ignore_result}" ]; then
120
		[ -n "${_stdout}" ] \
121
			&& _echo "done."
122
		return 0
123
	else
124
		[ -n "${_stdout}" ] \
125
			&& _echo "failed."
126
		return 1
127
	fi
128
}
129

    
130
_exit() {
131
	if [ -n "${kernel_pkg}" ]; then
132
		_exec "pkg lock ${kernel_pkg}" "Locking kernel package" mute ignore_result
133
	fi
134
	if [ -f "${pid_file}" ]; then
135
		rm -f ${pid_file}
136
	fi
137

    
138
	if [ -n "${1}" ]; then
139
		exit ${1}
140
	fi
141

    
142
	exit 0
143
}
144

    
145
first_step() {
146
	_exec "pkg update" "Updating repositories" mute
147

    
148
	# figure out which kernel variant is running
149
	kernel_pkg=$(pkg query %n $(pkg info pfSense-kernel-\*))
150

    
151
	if [ -z "${kernel_pkg}" ]; then
152
		_echo "ERROR: It was not possible to identify which pfSense kernel is installed"
153
		_exit 1
154
	fi
155

    
156
	kernel_local=$(pkg query %v ${kernel_pkg})
157

    
158
	if [ -z "${kernel_local}" ]; then
159
		_echo "ERROR: It was not possible to determine pfSense kernel local version"
160
		_exit 1
161
	fi
162

    
163
	kernel_remote=$(pkg rquery %v ${kernel_pkg})
164

    
165
	if [ -z "${kernel_remote}" ]; then
166
		_echo "ERROR: It was not possible to determine pfSense kernel remote version"
167
		_exit 1
168
	fi
169

    
170
	kernel_version_compare=$(pkg version -t ${kernel_local} ${kernel_remote})
171

    
172
	if [ "${kernel_version_compare}" = "<" ]; then
173
		kernel_update=1
174
		_exec "pkg unlock ${kernel_pkg}" "Unlocking kernel package" mute ignore_result
175
	elif [ "${kernel_version_compare}" = "=" ]; then
176
		kernel_update=0
177
	elif [ "${kernel_version_compare}" = ">" ]; then
178
		_echo "ERROR: You are using a newer kernel version than remote repository"
179
		_exit 1
180
	else
181
		_echo "ERROR: Error comparing pfSense kernel local and remote versions"
182
		_exit 1
183
	fi
184

    
185
	# XXX find a samrter way to do it
186
	l=$(pkg upgrade -nq | wc -l)
187
	if [ ${l} -eq 1 ]; then
188
		_echo "Your packages are up to date"
189
		_exit 0
190
	fi
191

    
192
	if [ -z "${yes}" ]; then
193
		# Show user which packages are going to be upgraded
194
		pkg upgrade -nq 2>&1 | tee -a ${logfile}
195

    
196
		_echo ""
197
		if [ ${kernel_update} -eq 1 ]; then
198
			_echo "**** WARNING ****"
199
			_echo "Reboot will be required!!"
200
		fi
201
		_echo -n "Proceed with upgrade? (y/N) "
202
		read answer
203
		if [ "${answer}" != "y" ]; then
204
			_echo "Aborting..."
205
			_exit 0
206
		fi
207
	fi
208

    
209
	_echo ">>> Downloading packages..."
210
	if ! pkg upgrade -F 2>&1 | tee -a ${logfile}; then
211
		_echo "ERROR: It was not possible to download packages"
212
		_exit 1
213
	fi
214

    
215
	# Mark firmware subsystem dirty
216
	touch ${firmwarelock}
217

    
218
	# First upgrade kernel and reboot
219
	if [ ${kernel_update} -eq 1 ]; then
220
		_exec "pkg upgrade ${kernel_pkg}" "Upgrading pfSense kernel"
221
		touch ${upgrade_in_progress}
222
		_echo "Rebooting..."
223
		/etc/rc.reboot
224
	fi
225
}
226

    
227
second_step() {
228
	_echo "Upgrading necessary packages..."
229
	if ! pkg upgrade 2>&1 | tee -a ${logfile}; then
230
		_echo "ERROR: An error occurred when upgrade was running..."
231
		_exit 1
232
	fi
233

    
234
	_exec "pkg autoremove" "Removing unnecessary packages" mute ignore_result
235
	_exec "pkg clean" "Cleanup pkg cache" mute ignore_result
236

    
237
	# cleanup caches
238

    
239
	rm -f ${upgrade_in_progress}
240
	rm -f ${firmwarelock}
241
}
242

    
243
if pgrep -qF ${pid_file} >/dev/null 2>&1; then
244
	echo "Another instance is already running... Aborting!"
245
	exit 1
246
fi
247

    
248
echo $$ > ${pid_file}
249

    
250
trap _exit 1 2 15 EXIT
251

    
252
logfile=/cf/conf/upgrade_log.txt
253

    
254
unset need_reboot
255
if [ ! -f "${upgrade_in_progress}" ]; then
256
	if [ -f "${logfile}" ]; then
257
		rm -f ${logfile}
258
	fi
259

    
260
	first_step
261
	need_reboot=1
262
fi
263

    
264
second_step
265

    
266
if [ -n "${need_reboot}" ]; then
267
	_echo "Rebooting..."
268
	/etc/rc.reboot
269
fi
270

    
271
_exit 0
(10-10/20)