OLD | NEW |
1 #!/bin/bash -p | 1 #!/bin/bash -p |
2 | 2 |
3 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 3 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
4 # Use of this source code is governed by a BSD-style license that can be | 4 # Use of this source code is governed by a BSD-style license that can be |
5 # found in the LICENSE file. | 5 # found in the LICENSE file. |
6 | 6 |
7 # usage: keystone_install.sh update_dmg_mount_point | 7 # usage: keystone_install.sh update_dmg_mount_point |
8 # | 8 # |
9 # Called by the Keystone system to update the installed application with a new | 9 # Called by the Keystone system to update the installed application with a new |
10 # version from a disk image. | 10 # version from a disk image. |
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
272 while IFS= read -r -d $'\0' symlink; do | 272 while IFS= read -r -d $'\0' symlink; do |
273 ensure_writable_symlink "${symlink}" | 273 ensure_writable_symlink "${symlink}" |
274 done < <(find "${directory}" -type l -print0) | 274 done < <(find "${directory}" -type l -print0) |
275 | 275 |
276 # Go back to how things were. | 276 # Go back to how things were. |
277 if [[ -n "${set_e}" ]]; then | 277 if [[ -n "${set_e}" ]]; then |
278 set -e | 278 set -e |
279 fi | 279 fi |
280 } | 280 } |
281 | 281 |
| 282 # is_version_ge accepts two version numbers, left and right, and performs a |
| 283 # piecewise comparison determining the result of left >= right, returning true |
| 284 # (0) if left >= right, and false (1) if left < right. If left or right are |
| 285 # missing components relative to the other, the missing components are assumed |
| 286 # to be 0, such that 10.6 == 10.6.0. |
| 287 is_version_ge() { |
| 288 local left="${1}" |
| 289 local right="${2}" |
| 290 |
| 291 local -a left_array right_array |
| 292 IFS=. left_array=(${left}) |
| 293 IFS=. right_array=(${right}) |
| 294 |
| 295 local left_count=${#left_array[@]} |
| 296 local right_count=${#right_array[@]} |
| 297 local count=${left_count} |
| 298 if [[ ${right_count} -lt ${count} ]]; then |
| 299 count=${right_count} |
| 300 fi |
| 301 |
| 302 # Compare the components piecewise, as long as there are corresponding |
| 303 # components on each side. If left_element and right_element are unequal, |
| 304 # a comparison can be made. |
| 305 local index=0 |
| 306 while [[ ${index} -lt ${count} ]]; do |
| 307 local left_element="${left_array[${index}]}" |
| 308 local right_element="${right_array[${index}]}" |
| 309 if [[ ${left_element} -gt ${right_element} ]]; then |
| 310 return 0 |
| 311 elif [[ ${left_element} -lt ${right_element} ]]; then |
| 312 return 1 |
| 313 fi |
| 314 ((++index)) |
| 315 done |
| 316 |
| 317 # If there are more components on the left than on the right, continue |
| 318 # comparing, assuming 0 for each of the missing components on the right. |
| 319 while [[ ${index} -lt ${left_count} ]]; do |
| 320 local left_element="${left_array[${index}]}" |
| 321 if [[ ${left_element} -gt 0 ]]; then |
| 322 return 0 |
| 323 fi |
| 324 ((++index)) |
| 325 done |
| 326 |
| 327 # If there are more components on the right than on the left, continue |
| 328 # comparing, assuming 0 for each of the missing components on the left. |
| 329 while [[ ${index} -lt ${right_count} ]]; do |
| 330 local right_element="${right_array[${index}]}" |
| 331 if [[ ${right_element} -gt 0 ]]; then |
| 332 return 1 |
| 333 fi |
| 334 ((++index)) |
| 335 done |
| 336 |
| 337 # Upon reaching this point, the two version numbers are semantically equal. |
| 338 return 0 |
| 339 } |
| 340 |
| 341 # Prints the OS version, as reported by sw_vers -productVersion, to stdout. |
| 342 # This function operates with "static" variables: it will only check the OS |
| 343 # version once per script run. |
| 344 g_checked_os_version= |
| 345 g_os_version= |
| 346 os_version() { |
| 347 if [[ -z "${g_checked_os_version}" ]]; then |
| 348 g_checked_os_version="y" |
| 349 g_os_version="$(sw_vers -productVersion)" |
| 350 note "g_os_version = ${g_os_version}" |
| 351 fi |
| 352 echo "${g_os_version}" |
| 353 return 0 |
| 354 } |
| 355 |
| 356 # Compares the running OS version against a supplied version number, |
| 357 # |check_version|, and returns 0 (true) if the running OS version is greater |
| 358 # than or equal to |check_version| according to a piece-wise comparison. |
| 359 # Returns 1 (false) if the running OS version number cannot be determined or |
| 360 # if |check_version| is greater than the running OS version. |check_version| |
| 361 # should be a string of the form "major.minor" or "major.minor.micro". |
| 362 is_os_version_ge() { |
| 363 local check_version="${1}" |
| 364 |
| 365 local os_version="$(os_version)" |
| 366 is_version_ge "${os_version}" "${check_version}" |
| 367 |
| 368 # The return value of is_version_ge is used as this function's return value. |
| 369 } |
| 370 |
| 371 # Returns 0 (true) if xattr supports -r for recursive operation. |
| 372 os_xattr_supports_r() { |
| 373 # xattr -r is supported in Mac OS X 10.6. |
| 374 is_os_version_ge 10.6 |
| 375 |
| 376 # The return value of is_os_version_ge is used as this function's return |
| 377 # value. |
| 378 } |
| 379 |
282 # Prints the version of ksadmin, as reported by ksadmin --ksadmin-version, to | 380 # Prints the version of ksadmin, as reported by ksadmin --ksadmin-version, to |
283 # stdout. This function operates with "static" variables: it will only check | 381 # stdout. This function operates with "static" variables: it will only check |
284 # the ksadmin version once per script run. If ksadmin is old enough to not | 382 # the ksadmin version once per script run. If ksadmin is old enough to not |
285 # support --ksadmin-version, or another error occurs, this function prints an | 383 # support --ksadmin-version, or another error occurs, this function prints an |
286 # empty string. | 384 # empty string. |
287 g_checked_ksadmin_version= | 385 g_checked_ksadmin_version= |
288 g_ksadmin_version= | 386 g_ksadmin_version= |
289 ksadmin_version() { | 387 ksadmin_version() { |
290 if [[ -z "${g_checked_ksadmin_version}" ]]; then | 388 if [[ -z "${g_checked_ksadmin_version}" ]]; then |
291 g_checked_ksadmin_version="y" | 389 g_checked_ksadmin_version="y" |
292 g_ksadmin_version="$(ksadmin --ksadmin-version || true)" | 390 g_ksadmin_version="$(ksadmin --ksadmin-version || true)" |
| 391 note "g_ksadmin_version = ${g_ksadmin_version}" |
293 fi | 392 fi |
294 echo "${g_ksadmin_version}" | 393 echo "${g_ksadmin_version}" |
295 return 0 | 394 return 0 |
296 } | 395 } |
297 | 396 |
298 # Compares the installed ksadmin version against a supplied version number, | 397 # Compares the installed ksadmin version against a supplied version number, |
299 # |check_version|, and returns 0 (true) if the installed Keystone version is | 398 # |check_version|, and returns 0 (true) if the installed Keystone version is |
300 # greater than or equal to |check_version| according to a piece-wise | 399 # greater than or equal to |check_version| according to a piece-wise |
301 # comparison. Returns 1 (false) if the installed Keystone version number | 400 # comparison. Returns 1 (false) if the installed Keystone version number |
302 # cannot be determined or if |check_version| is greater than the installed | 401 # cannot be determined or if |check_version| is greater than the installed |
303 # Keystone version. |check_version| should be a string of the form | 402 # Keystone version. |check_version| should be a string of the form |
304 # "major.minor.micro.build". Returns 1 (false) if either |check_version| or | 403 # "major.minor.micro.build". |
305 # the Keystone version do not match this format. | |
306 readonly KSADMIN_VERSION_RE="^([0-9]+)\\.([0-9]+)\\.([0-9]+)\\.([0-9]+)\$" | |
307 is_ksadmin_version_ge() { | 404 is_ksadmin_version_ge() { |
308 local check_version="${1}" | 405 local check_version="${1}" |
309 | 406 |
310 if ! [[ "${check_version}" =~ ${KSADMIN_VERSION_RE} ]]; then | 407 local ksadmin_version="$(ksadmin_version)" |
311 return 1 | 408 is_version_ge "${ksadmin_version}" "${check_version}" |
312 fi | |
313 | 409 |
314 local check_components=("${BASH_REMATCH[1]}" | 410 # The return value of is_version_ge is used as this function's return value. |
315 "${BASH_REMATCH[2]}" | |
316 "${BASH_REMATCH[3]}" | |
317 "${BASH_REMATCH[4]}") | |
318 | |
319 local ksadmin_version | |
320 ksadmin_version="$(ksadmin_version)" | |
321 | |
322 if ! [[ "${ksadmin_version}" =~ ${KSADMIN_VERSION_RE} ]]; then | |
323 return 1 | |
324 fi | |
325 | |
326 local ksadmin_components=("${BASH_REMATCH[1]}" | |
327 "${BASH_REMATCH[2]}" | |
328 "${BASH_REMATCH[3]}" | |
329 "${BASH_REMATCH[4]}") | |
330 | |
331 local i | |
332 for i in "${!check_components[@]}"; do | |
333 local check_component="${check_components[${i}]}" | |
334 local ksadmin_component="${ksadmin_components[${i}]}" | |
335 | |
336 if [[ ${ksadmin_component} -lt ${check_component} ]]; then | |
337 # ksadmin_version is less than check_version. | |
338 return 1 | |
339 fi | |
340 if [[ ${ksadmin_component} -gt ${check_component} ]]; then | |
341 # ksadmin_version is greater than check_version. | |
342 return 0 | |
343 fi | |
344 done | |
345 | |
346 # The version numbers are equal. | |
347 return 0 | |
348 } | 411 } |
349 | 412 |
350 # Returns 0 (true) if ksadmin supports --tag. | 413 # Returns 0 (true) if ksadmin supports --tag. |
351 ksadmin_supports_tag() { | 414 ksadmin_supports_tag() { |
352 local ksadmin_version | 415 local ksadmin_version |
353 | 416 |
354 ksadmin_version="$(ksadmin_version)" | 417 ksadmin_version="$(ksadmin_version)" |
355 if [[ -n "${ksadmin_version}" ]]; then | 418 if [[ -n "${ksadmin_version}" ]]; then |
356 # A ksadmin that recognizes --ksadmin-version and provides a version | 419 # A ksadmin that recognizes --ksadmin-version and provides a version |
357 # number is new enough to recognize --tag. | 420 # number is new enough to recognize --tag. |
(...skipping 898 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1256 | 1319 |
1257 note "chmod_mode = ${chmod_mode}" | 1320 note "chmod_mode = ${chmod_mode}" |
1258 chmod -R "${chmod_mode}" "${installed_app}" 2> /dev/null | 1321 chmod -R "${chmod_mode}" "${installed_app}" 2> /dev/null |
1259 | 1322 |
1260 # On the Mac, or at least on HFS+, symbolic link permissions are significant, | 1323 # On the Mac, or at least on HFS+, symbolic link permissions are significant, |
1261 # but chmod -R and -h can't be used together. Do another pass to fix the | 1324 # but chmod -R and -h can't be used together. Do another pass to fix the |
1262 # permissions on any symbolic links. | 1325 # permissions on any symbolic links. |
1263 find "${installed_app}" -type l -exec chmod -h "${chmod_mode}" {} + \ | 1326 find "${installed_app}" -type l -exec chmod -h "${chmod_mode}" {} + \ |
1264 2> /dev/null | 1327 2> /dev/null |
1265 | 1328 |
1266 # Host OS version check, to be able to take advantage of features on newer | |
1267 # systems and fall back to slow ways of doing things on older systems. | |
1268 local os_version | |
1269 os_version="$(sw_vers -productVersion)" | |
1270 note "os_version = ${os_version}" | |
1271 | |
1272 local os_major=0 | |
1273 local os_minor=0 | |
1274 if [[ "${os_version}" =~ ^([0-9]+)\.([0-9]+) ]]; then | |
1275 os_major="${BASH_REMATCH[1]}" | |
1276 os_minor="${BASH_REMATCH[2]}" | |
1277 fi | |
1278 note "os_major = ${os_major}" | |
1279 note "os_minor = ${os_minor}" | |
1280 | |
1281 # If an update is triggered from within the application itself, the update | 1329 # If an update is triggered from within the application itself, the update |
1282 # process inherits the quarantine bit (LSFileQuarantineEnabled). Any files | 1330 # process inherits the quarantine bit (LSFileQuarantineEnabled). Any files |
1283 # or directories created during the update will be quarantined in that case, | 1331 # or directories created during the update will be quarantined in that case, |
1284 # which may cause Launch Services to display quarantine UI. That's bad, | 1332 # which may cause Launch Services to display quarantine UI. That's bad, |
1285 # especially if it happens when the outer .app launches a quarantined inner | 1333 # especially if it happens when the outer .app launches a quarantined inner |
1286 # helper. If the application is already on the system and is being updated, | 1334 # helper. If the application is already on the system and is being updated, |
1287 # then it can be assumed that it should not be quarantined. Use xattr to | 1335 # then it can be assumed that it should not be quarantined. Use xattr to |
1288 # drop the quarantine attribute. | 1336 # drop the quarantine attribute. |
1289 # | 1337 # |
1290 # TODO(mark): Instead of letting the quarantine attribute be set and then | 1338 # TODO(mark): Instead of letting the quarantine attribute be set and then |
1291 # dropping it here, figure out a way to get the update process to run | 1339 # dropping it here, figure out a way to get the update process to run |
1292 # without LSFileQuarantineEnabled even when triggering an update from within | 1340 # without LSFileQuarantineEnabled even when triggering an update from within |
1293 # the application. | 1341 # the application. |
1294 note "lifting quarantine" | 1342 note "lifting quarantine" |
1295 | 1343 |
1296 if [[ ${os_major} -gt 10 ]] || | 1344 if os_xattr_supports_r; then |
1297 ([[ ${os_major} -eq 10 ]] && [[ ${os_minor} -ge 6 ]]); then | |
1298 # On 10.6, xattr supports -r for recursive operation. | 1345 # On 10.6, xattr supports -r for recursive operation. |
1299 xattr -d -r "${QUARANTINE_ATTR}" "${installed_app}" 2> /dev/null | 1346 xattr -d -r "${QUARANTINE_ATTR}" "${installed_app}" 2> /dev/null |
1300 else | 1347 else |
1301 # On earlier systems, xattr doesn't support -r, so run xattr via find. | 1348 # On earlier systems, xattr doesn't support -r, so run xattr via find. |
1302 find "${installed_app}" -exec xattr -d "${QUARANTINE_ATTR}" {} + \ | 1349 find "${installed_app}" -exec xattr -d "${QUARANTINE_ATTR}" {} + \ |
1303 2> /dev/null | 1350 2> /dev/null |
1304 fi | 1351 fi |
1305 | 1352 |
1306 # Do Keychain reauthorization. This involves running a stub executable on | 1353 # Do Keychain reauthorization. This involves running a stub executable on |
1307 # the dmg that loads the newly-updated framework and jumps to it to perform | 1354 # the dmg that loads the newly-updated framework and jumps to it to perform |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1358 | 1405 |
1359 # Check "less than" instead of "not equal to" in case Keystone ever changes to | 1406 # Check "less than" instead of "not equal to" in case Keystone ever changes to |
1360 # pass more arguments. | 1407 # pass more arguments. |
1361 if [[ ${#} -lt 1 ]]; then | 1408 if [[ ${#} -lt 1 ]]; then |
1362 usage | 1409 usage |
1363 exit 2 | 1410 exit 2 |
1364 fi | 1411 fi |
1365 | 1412 |
1366 main "${@}" | 1413 main "${@}" |
1367 exit ${?} | 1414 exit ${?} |
OLD | NEW |