| 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 13 matching lines...) Expand all Loading... |
| 24 # 4 Update driven by user ticket when a system ticket is also present | 24 # 4 Update driven by user ticket when a system ticket is also present |
| 25 # 5 Could not prepare existing installed version to receive update | 25 # 5 Could not prepare existing installed version to receive update |
| 26 # 6 Patch sanity check failure | 26 # 6 Patch sanity check failure |
| 27 # 7 rsync failed (could not copy new versioned directory to Versions) | 27 # 7 rsync failed (could not copy new versioned directory to Versions) |
| 28 # 8 rsync failed (could not update outer .app bundle) | 28 # 8 rsync failed (could not update outer .app bundle) |
| 29 # 9 Could not get the version, update URL, or channel after update | 29 # 9 Could not get the version, update URL, or channel after update |
| 30 # 10 Updated application does not have the version number from the update | 30 # 10 Updated application does not have the version number from the update |
| 31 # 11 ksadmin failure | 31 # 11 ksadmin failure |
| 32 # 12 dirpatcher failed for versioned directory | 32 # 12 dirpatcher failed for versioned directory |
| 33 # 13 dirpatcher failed for outer .app bundle | 33 # 13 dirpatcher failed for outer .app bundle |
| 34 # 14 The update is incompatible with the system | 34 # 14 The update is incompatible with the system (presently unused) |
| 35 # | 35 # |
| 36 # The following exit codes can be used to convey special meaning to Keystone. | 36 # The following exit codes can be used to convey special meaning to Keystone. |
| 37 # KeystoneRegistration will present these codes to Chrome as "success." | 37 # KeystoneRegistration will present these codes to Chrome as "success." |
| 38 # 66 (unused) success, request reboot | 38 # 66 (unused) success, request reboot |
| 39 # 77 (unused) try installation again later | 39 # 77 (unused) try installation again later |
| 40 | 40 |
| 41 set -eu | 41 set -eu |
| 42 | 42 |
| 43 # http://b/2290916: Keystone runs the installation with a restrictive PATH | 43 # http://b/2290916: Keystone runs the installation with a restrictive PATH |
| 44 # that only includes the directory containing ksadmin, /bin, and /usr/bin. It | 44 # that only includes the directory containing ksadmin, /bin, and /usr/bin. It |
| (...skipping 402 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 447 | 447 |
| 448 # Returns 0 (true) if ksadmin supports --version-path and --version-key. | 448 # Returns 0 (true) if ksadmin supports --version-path and --version-key. |
| 449 ksadmin_supports_versionpath_versionkey() { | 449 ksadmin_supports_versionpath_versionkey() { |
| 450 # --version-path and --version-key were introduced in Keystone 1.0.9.2318. | 450 # --version-path and --version-key were introduced in Keystone 1.0.9.2318. |
| 451 is_ksadmin_version_ge 1.0.9.2318 | 451 is_ksadmin_version_ge 1.0.9.2318 |
| 452 | 452 |
| 453 # The return value of is_ksadmin_version_ge is used as this function's | 453 # The return value of is_ksadmin_version_ge is used as this function's |
| 454 # return value. | 454 # return value. |
| 455 } | 455 } |
| 456 | 456 |
| 457 has_32_bit_only_cpu() { | |
| 458 local cpu_64_bit_capable="$(sysctl -n hw.cpu64bit_capable 2>/dev/null)" | |
| 459 [[ -z "${cpu_64_bit_capable}" || "${cpu_64_bit_capable}" -eq 0 ]] | |
| 460 | |
| 461 # The return value of the comparison is used as this function's return | |
| 462 # value. | |
| 463 } | |
| 464 | |
| 465 # Runs "defaults read" to obtain the value of a key in a property list. As | 457 # Runs "defaults read" to obtain the value of a key in a property list. As |
| 466 # with "defaults read", an absolute path to a plist is supplied, without the | 458 # with "defaults read", an absolute path to a plist is supplied, without the |
| 467 # ".plist" extension. | 459 # ".plist" extension. |
| 468 # | 460 # |
| 469 # As of Mac OS X 10.8, defaults (and NSUserDefaults and CFPreferences) | 461 # As of Mac OS X 10.8, defaults (and NSUserDefaults and CFPreferences) |
| 470 # normally communicates with cfprefsd to read and write plists. Changes to a | 462 # normally communicates with cfprefsd to read and write plists. Changes to a |
| 471 # plist file aren't necessarily reflected immediately via this API family when | 463 # plist file aren't necessarily reflected immediately via this API family when |
| 472 # not made through this API family, because cfprefsd may return cached data | 464 # not made through this API family, because cfprefsd may return cached data |
| 473 # from a former on-disk version of a plist file instead of reading the current | 465 # from a former on-disk version of a plist file instead of reading the current |
| 474 # version from disk. The old behavior can be restored by setting the | 466 # version from disk. The old behavior can be restored by setting the |
| (...skipping 13 matching lines...) Expand all Loading... |
| 488 # This function exists because the update process delivers new copies of | 480 # This function exists because the update process delivers new copies of |
| 489 # Info.plist files to the disk behind cfprefsd's back, and if cfprefsd becomes | 481 # Info.plist files to the disk behind cfprefsd's back, and if cfprefsd becomes |
| 490 # aware of the original version of the file for any reason (such as this | 482 # aware of the original version of the file for any reason (such as this |
| 491 # script reading values from it via "defaults read"), the new version of the | 483 # script reading values from it via "defaults read"), the new version of the |
| 492 # file will not be immediately effective or visible via cfprefsd after the | 484 # file will not be immediately effective or visible via cfprefsd after the |
| 493 # update is applied. | 485 # update is applied. |
| 494 infoplist_read() { | 486 infoplist_read() { |
| 495 __CFPREFERENCES_AVOID_DAEMON=1 defaults read "${@}" | 487 __CFPREFERENCES_AVOID_DAEMON=1 defaults read "${@}" |
| 496 } | 488 } |
| 497 | 489 |
| 498 # Adjust the tag to contain the -32bit tag suffix. This is intended to be used | |
| 499 # as a last resort, if sanity checks show that a non-32-bit update is about to | |
| 500 # be applied to a 32-bit-only system. If this happens, it means that the | |
| 501 # server delivered a non-32-bit update to a 32-bit-only system, most likely | |
| 502 # because the tag was never updated to include the -32bit tag suffix. | |
| 503 # | |
| 504 # This mechanism takes a heavy-handed approach, clearing --tag-path and | |
| 505 # --tag-key so that the channel identity will no longer follow the installed | |
| 506 # application. However, it's expected that once -32bit is added to the tag, | |
| 507 # the server will deliver a 32-bit update (possibly the final 32-bit version), | |
| 508 # and once installed, that update will restore the --tag-path and --tag-key. | |
| 509 # In any event, channel identity in this case may be moot, if 32-bit builds | |
| 510 # are no longer being produced. | |
| 511 # | |
| 512 # This provides some resilience in the update system for old 32-bit-only | |
| 513 # systems that aren't used during the window between when the -32bit tag | |
| 514 # suffix begins being used and 32-bit releases end. | |
| 515 mark_32_bit_only_system() { | |
| 516 local product_id="${1}" | |
| 517 | |
| 518 # This step isn't critical. | |
| 519 local set_e= | |
| 520 if [[ "${-}" =~ e ]]; then | |
| 521 set_e="y" | |
| 522 set +e | |
| 523 fi | |
| 524 | |
| 525 note "marking 32-bit-only system" | |
| 526 | |
| 527 if ! ksadmin_supports_tagpath_tagkey; then | |
| 528 note "couldn't mark 32-bit-only system, no ksadmin support" | |
| 529 if [[ -n "${set_e}" ]]; then | |
| 530 set -e | |
| 531 fi | |
| 532 return 0 | |
| 533 fi | |
| 534 | |
| 535 local current_tag="$(ksadmin --productid "${product_id}" --print-tag)" | |
| 536 note "current_tag = ${current_tag}" | |
| 537 | |
| 538 if grep -Eq -- '-32bit(-|$)' <<< "${current_tag}"; then | |
| 539 note "current tag already has -32bit" | |
| 540 if [[ -n "${set_e}" ]]; then | |
| 541 set -e | |
| 542 fi | |
| 543 return 0 | |
| 544 fi | |
| 545 | |
| 546 # This clears any other tag suffix, but that shouldn't be a problem. The | |
| 547 # only other currently-defined tag suffix component is -full, but -full and | |
| 548 # -32bit were introduced at the same time, so if -full appears, whatever set | |
| 549 # it would have already had enough knowledge to set -32bit as well, and this | |
| 550 # codepath wouldn't be entered. | |
| 551 local current_channel="$(sed -e 's/-.*//' <<< "${current_tag}")" | |
| 552 local new_tag="${current_channel}-32bit" | |
| 553 note "new_tag = ${new_tag}" | |
| 554 | |
| 555 # Using ksadmin without --register only updates specified values in the | |
| 556 # ticket, without changing other existing values. Giving empty values for | |
| 557 # --tag-path and --tag-key clears those fields. | |
| 558 if ! ksadmin --productid "${product_id}" \ | |
| 559 --tag "${new_tag}" --tag-path '' --tag-key ''; then | |
| 560 err "ksadmin failed to mark 32-bit-only system" | |
| 561 else | |
| 562 note "marked 32-bit-only system" | |
| 563 fi | |
| 564 | |
| 565 # Go back to how things were. | |
| 566 if [[ -n "${set_e}" ]]; then | |
| 567 set -e | |
| 568 fi | |
| 569 } | |
| 570 | |
| 571 # When a patch update fails because the old installed copy doesn't match the | 490 # When a patch update fails because the old installed copy doesn't match the |
| 572 # expected state, mark_failed_patch_update updates the Keystone ticket by | 491 # expected state, mark_failed_patch_update updates the Keystone ticket by |
| 573 # adding "-full" to the tag. The server will see this on a subsequent update | 492 # adding "-full" to the tag. The server will see this on a subsequent update |
| 574 # attempt and will provide a full update (as opposed to a patch) to the | 493 # attempt and will provide a full update (as opposed to a patch) to the |
| 575 # client. | 494 # client. |
| 576 # | 495 # |
| 577 # Even if mark_failed_patch_update fails to modify the tag, the user will | 496 # Even if mark_failed_patch_update fails to modify the tag, the user will |
| 578 # eventually be updated. Patch updates are only provided for successive | 497 # eventually be updated. Patch updates are only provided for successive |
| 579 # releases on a particular channel, to update version o to version o+1. If a | 498 # releases on a particular channel, to update version o to version o+1. If a |
| 580 # patch update fails in this case, eventually version o+2 will be released, | 499 # patch update fails in this case, eventually version o+2 will be released, |
| (...skipping 13 matching lines...) Expand all Loading... |
| 594 set +e | 513 set +e |
| 595 fi | 514 fi |
| 596 | 515 |
| 597 note "marking failed patch update" | 516 note "marking failed patch update" |
| 598 | 517 |
| 599 local channel | 518 local channel |
| 600 channel="$(infoplist_read "${old_ks_plist}" "${KS_CHANNEL_KEY}" 2> /dev/null)" | 519 channel="$(infoplist_read "${old_ks_plist}" "${KS_CHANNEL_KEY}" 2> /dev/null)" |
| 601 | 520 |
| 602 local tag="${channel}" | 521 local tag="${channel}" |
| 603 local tag_key="${KS_CHANNEL_KEY}" | 522 local tag_key="${KS_CHANNEL_KEY}" |
| 604 if has_32_bit_only_cpu; then | |
| 605 tag="${tag}-32bit" | |
| 606 tag_key="${tag_key}-32bit" | |
| 607 fi | |
| 608 | 523 |
| 609 tag="${tag}-full" | 524 tag="${tag}-full" |
| 610 tag_key="${tag_key}-full" | 525 tag_key="${tag_key}-full" |
| 611 | 526 |
| 612 note "tag = ${tag}" | 527 note "tag = ${tag}" |
| 613 note "tag_key = ${tag_key}" | 528 note "tag_key = ${tag_key}" |
| 614 | 529 |
| 615 # ${old_ks_plist}, used for --tag-path, is the Info.plist for the old | 530 # ${old_ks_plist}, used for --tag-path, is the Info.plist for the old |
| 616 # version of Chrome. It may not contain the keys for the "-full" tag suffix. | 531 # version of Chrome. It may not contain the keys for the "-full" tag suffix. |
| 617 # If it doesn't, just bail out without marking the patch update as failed. | 532 # If it doesn't, just bail out without marking the patch update as failed. |
| (...skipping 415 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1033 "${KS_BRAND_KEY}" 2> /dev/null || | 948 "${KS_BRAND_KEY}" 2> /dev/null || |
| 1034 true)" | 949 true)" |
| 1035 note "old_brand = ${old_brand}" | 950 note "old_brand = ${old_brand}" |
| 1036 | 951 |
| 1037 local update_versioned_dir= | 952 local update_versioned_dir= |
| 1038 if [[ -z "${is_patch}" ]]; then | 953 if [[ -z "${is_patch}" ]]; then |
| 1039 update_versioned_dir="${update_app}/${VERSIONS_DIR}/${update_version_app}" | 954 update_versioned_dir="${update_app}/${VERSIONS_DIR}/${update_version_app}" |
| 1040 note "update_versioned_dir = ${update_versioned_dir}" | 955 note "update_versioned_dir = ${update_versioned_dir}" |
| 1041 fi | 956 fi |
| 1042 | 957 |
| 1043 if has_32_bit_only_cpu; then | |
| 1044 # On a 32-bit-only system, make sure that the update contains 32-bit code. | |
| 1045 note "system is 32-bit-only" | |
| 1046 | |
| 1047 local test_binary | |
| 1048 if [[ -z "${is_patch}" ]]; then | |
| 1049 # For a full installer, the framework is available, so check it for | |
| 1050 # 32-bit code. | |
| 1051 local update_framework_dir="${update_versioned_dir}/${FRAMEWORK_DIR}" | |
| 1052 test_binary="${update_framework_dir}/${FRAMEWORK_NAME}" | |
| 1053 else | |
| 1054 # No application code is guaranteed to be available at this point for a | |
| 1055 # patch updater, but goobspatch is built alongside and will have the | |
| 1056 # same bitness of the product that this updater will install, so it's a | |
| 1057 # reasonable proxy. | |
| 1058 test_binary="${patch_dir}/goobspatch" | |
| 1059 fi | |
| 1060 note "test_binary = ${test_binary}" | |
| 1061 | |
| 1062 if ! file "${test_binary}" | grep -q 'i386$'; then | |
| 1063 err "can't install non-32-bit update on 32-bit-only system" | |
| 1064 mark_32_bit_only_system "${product_id}" | |
| 1065 exit 14 | |
| 1066 else | |
| 1067 note "update will run on a 32-bit-only system" | |
| 1068 fi | |
| 1069 fi | |
| 1070 | |
| 1071 ensure_writable_symlinks_recursive "${installed_app}" | 958 ensure_writable_symlinks_recursive "${installed_app}" |
| 1072 | 959 |
| 1073 # By copying to ${installed_app}, the existing application name will be | 960 # By copying to ${installed_app}, the existing application name will be |
| 1074 # preserved, if the user has renamed the application on disk. Respecting | 961 # preserved, if the user has renamed the application on disk. Respecting |
| 1075 # the user's changes is friendly. | 962 # the user's changes is friendly. |
| 1076 | 963 |
| 1077 # Make sure that ${installed_versions_dir} exists, so that it can receive | 964 # Make sure that ${installed_versions_dir} exists, so that it can receive |
| 1078 # the versioned directory. It may not exist if updating from an older | 965 # the versioned directory. It may not exist if updating from an older |
| 1079 # version that did not use the versioned layout on disk. Later, during the | 966 # version that did not use the versioned layout on disk. Later, during the |
| 1080 # rsync to copy the application directory, the mode bits and timestamp on | 967 # rsync to copy the application directory, the mode bits and timestamp on |
| (...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1302 | 1189 |
| 1303 # The channel ID is optional. Suppress stderr to prevent Keystone from | 1190 # The channel ID is optional. Suppress stderr to prevent Keystone from |
| 1304 # seeing possible error output. | 1191 # seeing possible error output. |
| 1305 local channel | 1192 local channel |
| 1306 channel="$(infoplist_read "${new_ks_plist}" \ | 1193 channel="$(infoplist_read "${new_ks_plist}" \ |
| 1307 "${KS_CHANNEL_KEY}" 2> /dev/null || true)" | 1194 "${KS_CHANNEL_KEY}" 2> /dev/null || true)" |
| 1308 note "channel = ${channel}" | 1195 note "channel = ${channel}" |
| 1309 | 1196 |
| 1310 local tag="${channel}" | 1197 local tag="${channel}" |
| 1311 local tag_key="${KS_CHANNEL_KEY}" | 1198 local tag_key="${KS_CHANNEL_KEY}" |
| 1312 if has_32_bit_only_cpu; then | |
| 1313 tag="${tag}-32bit" | |
| 1314 tag_key="${tag_key}-32bit" | |
| 1315 fi | |
| 1316 note "tag = ${tag}" | 1199 note "tag = ${tag}" |
| 1317 note "tag_key = ${tag_key}" | 1200 note "tag_key = ${tag_key}" |
| 1318 | 1201 |
| 1319 # Make sure that the update was successful by comparing the version found in | 1202 # Make sure that the update was successful by comparing the version found in |
| 1320 # the update with the version now on disk. | 1203 # the update with the version now on disk. |
| 1321 if [[ "${new_version_ks}" != "${update_version_ks}" ]]; then | 1204 if [[ "${new_version_ks}" != "${update_version_ks}" ]]; then |
| 1322 err "new_version_ks and update_version_ks do not match" | 1205 err "new_version_ks and update_version_ks do not match" |
| 1323 exit 10 | 1206 exit 10 |
| 1324 fi | 1207 fi |
| 1325 | 1208 |
| (...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1619 | 1502 |
| 1620 # Check "less than" instead of "not equal to" in case Keystone ever changes to | 1503 # Check "less than" instead of "not equal to" in case Keystone ever changes to |
| 1621 # pass more arguments. | 1504 # pass more arguments. |
| 1622 if [[ ${#} -lt 1 ]]; then | 1505 if [[ ${#} -lt 1 ]]; then |
| 1623 usage | 1506 usage |
| 1624 exit 2 | 1507 exit 2 |
| 1625 fi | 1508 fi |
| 1626 | 1509 |
| 1627 main "${@}" | 1510 main "${@}" |
| 1628 exit ${?} | 1511 exit ${?} |
| OLD | NEW |