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 |