15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#!/bin/bash -p 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Copyright (c) 2011 The Chromium Authors. All rights reserved. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# found in the LICENSE file. 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Called by the application to install in a new location. Generally, this 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# means that the application is running from a disk image and wants to be 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# copied to /Applications. The application, when running from the disk image, 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# will call this script to perform the copy. 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# This script will be run as root if the application determines that it would 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# not otherwise have permission to perform the copy. 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# When running as root, this script will be invoked with the real user ID set 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# to the user's ID, but the effective user ID set to 0 (root). bash -p is 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# used on the first line to prevent bash from setting the effective user ID to 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# the real user ID (dropping root privileges). 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)set -e 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# This script may run as root, so be paranoid about things like ${PATH}. 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)export PATH="/usr/bin:/usr/sbin:/bin:/sbin" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# If running as root, output the pid to stdout before doing anything else. 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# See chrome/browser/mac/authorization_util.h. 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)if [ ${EUID} -eq 0 ] ; then 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) echo "${$}" 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)fi 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)if [ ${#} -ne 2 ] ; then 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) echo "usage: ${0} SRC DEST" >& 2 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) exit 2 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)fi 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SRC=${1} 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DEST=${2} 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Make sure that SRC is an absolute path and that it exists. 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)if [ -z "${SRC}" ] || [ "${SRC:0:1}" != "/" ] || [ ! -d "${SRC}" ] ; then 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) echo "${0}: source ${SRC} sanity check failed" >& 2 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) exit 3 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)fi 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Make sure that DEST is an absolute path and that it doesn't yet exist. 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)if [ -z "${DEST}" ] || [ "${DEST:0:1}" != "/" ] || [ -e "${DEST}" ] ; then 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) echo "${0}: destination ${DEST} sanity check failed" >& 2 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) exit 4 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)fi 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Do the copy. 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)rsync -lrpt "${SRC}/" "${DEST}" 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# The remaining steps are not considered critical. 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)set +e 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Notify LaunchServices. 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CORESERVICES="/System/Library/Frameworks/CoreServices.framework" 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)LAUNCHSERVICES="${CORESERVICES}/Frameworks/LaunchServices.framework" 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)LSREGISTER="${LAUNCHSERVICES}/Support/lsregister" 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)"${LSREGISTER}" -f "${DEST}" 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# If this script is not running as root and the application is installed 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# somewhere under /Applications, try to make it writable by all admin users. 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# This will allow other admin users to update the application from their own 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# user Keystone instances even if the Keystone ticket is not promoted to 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# system level. 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# If the script is not running as root and the application is not installed 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# under /Applications, it might not be in a system-wide location, and it 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# probably won't be something that other users on the system are running, so 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# err on the side of safety and don't make it group-writable. 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# If this script is running as root, a Keystone ticket promotion is expected, 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# and future updates can be expected to be applied as root, so 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# admin-writeability is not a concern. Set the entire thing to be owned by 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# root in that case, regardless of where it's installed, and drop any group 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# and other write permission. 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# If this script is running as a user that is not a member of the admin group, 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# the chgrp operation will not succeed. Tolerate that case, because it's 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# better than the alternative, which is to make the application 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# world-writable. 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CHMOD_MODE="a+rX,u+w,go-w" 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)if [ ${EUID} -ne 0 ] ; then 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if [ "${DEST:0:14}" = "/Applications/" ] && 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chgrp -Rh admin "${DEST}" >& /dev/null ; then 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHMOD_MODE="a+rX,ug+w,o-w" 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fi 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)else 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chown -Rh root:wheel "${DEST}" >& /dev/null 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)fi 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)chmod -R "${CHMOD_MODE}" "${DEST}" >& /dev/null 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# On the Mac, or at least on HFS+, symbolic link permissions are significant, 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# but chmod -R and -h can't be used together. Do another pass to fix the 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# permissions on any symbolic links. 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)find "${DEST}" -type l -exec chmod -h "${CHMOD_MODE}" {} + >& /dev/null 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Host OS version check, to be able to take advantage of features on newer 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# systems and fall back to slow ways of doing things on older systems. 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)OS_VERSION=$(sw_vers -productVersion) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)OS_MAJOR=$(sed -Ene 's/^([0-9]+).*/\1/p' <<< ${OS_VERSION}) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)OS_MINOR=$(sed -Ene 's/^([0-9]+)\.([0-9]+).*/\2/p' <<< ${OS_VERSION}) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Because this script is launched by the application itself, the installation 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# process inherits the quarantine bit (LSFileQuarantineEnabled). Any files or 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# directories created during the update will be quarantined in that case, 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# which may cause Launch Services to display quarantine UI. That's bad, 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# especially if it happens when the outer .app launches a quarantined inner 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# helper. Since the user approved the application launch if quarantined, it 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# it can be assumed that the installed copy should not be quarantined. Use 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# xattr to drop the quarantine attribute. 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)QUARANTINE_ATTR=com.apple.quarantine 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)if [ ${OS_MAJOR} -gt 10 ] || 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ([ ${OS_MAJOR} -eq 10 ] && [ ${OS_MINOR} -ge 6 ]) ; then 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # On 10.6, xattr supports -r for recursive operation. 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) xattr -d -r "${QUARANTINE_ATTR}" "${DEST}" >& /dev/null 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)else 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # On earlier systems, xattr doesn't support -r, so run xattr via find. 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) find "${DEST}" -exec xattr -d "${QUARANTINE_ATTR}" {} + >& /dev/null 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)fi 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Great success! 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)exit 0 127