1#! /bin/bash 2 3# Create a read-only disk image of the contents of a folder 4 5set -e; 6 7function pure_version() { 8 echo '1.0.0.2' 9} 10 11function version() { 12 echo "create-dmg $(pure_version)" 13} 14 15function usage() { 16 version 17 echo "Creates a fancy DMG file." 18 echo "Usage: $(basename $0) options... image.dmg source_folder" 19 echo "All contents of source_folder will be copied into the disk image." 20 echo "Options:" 21 echo " --volname name" 22 echo " set volume name (displayed in the Finder sidebar and window title)" 23 echo " --volicon icon.icns" 24 echo " set volume icon" 25 echo " --background pic.png" 26 echo " set folder background image (provide png, gif, jpg)" 27 echo " --window-pos x y" 28 echo " set position the folder window" 29 echo " --window-size width height" 30 echo " set size of the folder window" 31 echo " --icon-size icon_size" 32 echo " set window icons size (up to 128)" 33 echo " --icon file_name x y" 34 echo " set position of the file's icon" 35 echo " --hide-extension file_name" 36 echo " hide the extension of file" 37 echo " --custom-icon file_name custom_icon_or_sample_file x y" 38 echo " set position and custom icon" 39 echo " --app-drop-link x y" 40 echo " make a drop link to Applications, at location x,y" 41 echo " --eula eula_file" 42 echo " attach a license file to the dmg" 43 echo " --no-internet-enable" 44 echo " disable automatic mount©" 45 echo " --version show tool version number" 46 echo " -h, --help display this help" 47 exit 0 48} 49 50WINX=10 51WINY=60 52WINW=500 53WINH=350 54ICON_SIZE=128 55 56while test "${1:0:1}" = "-"; do 57 case $1 in 58 --volname) 59 VOLUME_NAME="$2" 60 shift; shift;; 61 --volicon) 62 VOLUME_ICON_FILE="$2" 63 shift; shift;; 64 --background) 65 BACKGROUND_FILE="$2" 66 BACKGROUND_FILE_NAME="$(basename $BACKGROUND_FILE)" 67 BACKGROUND_CLAUSE="set background picture of opts to file \".background:$BACKGROUND_FILE_NAME\"" 68 shift; shift;; 69 --icon-size) 70 ICON_SIZE="$2" 71 shift; shift;; 72 --window-pos) 73 WINX=$2; WINY=$3 74 shift; shift; shift;; 75 --window-size) 76 WINW=$2; WINH=$3 77 shift; shift; shift;; 78 --icon) 79 POSITION_CLAUSE="${POSITION_CLAUSE}set position of item \"$2\" to {$3, $4} 80" 81 shift; shift; shift; shift;; 82 --hide-extension) 83 HIDING_CLAUSE="${HIDING_CLAUSE}set the extension hidden of item \"$2\" to true" 84 shift; shift;; 85 --custom-icon) 86 shift; shift; shift; shift; shift;; 87 -h | --help) 88 usage;; 89 --version) 90 version; exit 0;; 91 --pure-version) 92 pure_version; exit 0;; 93 --app-drop-link) 94 APPLICATION_LINK=$2 95 APPLICATION_CLAUSE="set position of item \"Applications\" to {$2, $3} 96" 97 shift; shift; shift;; 98 --eula) 99 EULA_RSRC=$2 100 shift; shift;; 101 --no-internet-enable) 102 NOINTERNET=1 103 shift;; 104 -*) 105 echo "Unknown option $1. Run with --help for help." 106 exit 1;; 107 esac 108done 109 110test -z "$2" && { 111 echo "Not enough arguments. Invoke with --help for help." 112 exit 1 113} 114 115DMG_PATH="$1" 116DMG_DIRNAME="$(dirname "$DMG_PATH")" 117DMG_DIR="$(cd $DMG_DIRNAME > /dev/null; pwd)" 118DMG_NAME="$(basename "$DMG_PATH")" 119DMG_TEMP_NAME="$DMG_DIR/rw.${DMG_NAME}" 120SRC_FOLDER="$(cd "$2" > /dev/null; pwd)" 121test -z "$VOLUME_NAME" && VOLUME_NAME="$(basename "$DMG_PATH" .dmg)" 122 123AUX_PATH="$(dirname $0)/support" 124 125test -d "$AUX_PATH" || { 126 echo "Cannot find support directory: $AUX_PATH" 127 exit 1 128} 129 130if [ -f "$SRC_FOLDER/.DS_Store" ]; then 131 echo "Deleting any .DS_Store in source folder" 132 rm "$SRC_FOLDER/.DS_Store" 133fi 134 135# Create the image 136echo "Creating disk image..." 137test -f "${DMG_TEMP_NAME}" && rm -f "${DMG_TEMP_NAME}" 138ACTUAL_SIZE=`du -sm "$SRC_FOLDER" | sed -e 's/ .*//g'` 139DISK_IMAGE_SIZE=$(expr $ACTUAL_SIZE + 20) 140hdiutil create -srcfolder "$SRC_FOLDER" -volname "${VOLUME_NAME}" -fs HFS+ -fsargs "-c c=64,a=16,e=16" -format UDRW -size ${DISK_IMAGE_SIZE}m "${DMG_TEMP_NAME}" 141 142# mount it 143echo "Mounting disk image..." 144MOUNT_DIR="/Volumes/${VOLUME_NAME}" 145 146# try unmount dmg if it was mounted previously (e.g. developer mounted dmg, installed app and forgot to unmount it) 147echo "Unmounting disk image..." 148DEV_NAME=$(hdiutil info | egrep '^/dev/' | sed 1q | awk '{print $1}') 149test -d "${MOUNT_DIR}" && hdiutil detach "${DEV_NAME}" 150 151echo "Mount directory: $MOUNT_DIR" 152DEV_NAME=$(hdiutil attach -readwrite -noverify -noautoopen "${DMG_TEMP_NAME}" | egrep '^/dev/' | sed 1q | awk '{print $1}') 153echo "Device name: $DEV_NAME" 154 155if ! test -z "$BACKGROUND_FILE"; then 156 echo "Copying background file..." 157 test -d "$MOUNT_DIR/.background" || mkdir "$MOUNT_DIR/.background" 158 cp "$BACKGROUND_FILE" "$MOUNT_DIR/.background/$BACKGROUND_FILE_NAME" 159fi 160 161if ! test -z "$APPLICATION_LINK"; then 162 echo "making link to Applications dir" 163 echo $MOUNT_DIR 164 ln -s /Applications "$MOUNT_DIR/Applications" 165fi 166 167if ! test -z "$VOLUME_ICON_FILE"; then 168 echo "Copying volume icon file '$VOLUME_ICON_FILE'..." 169 cp "$VOLUME_ICON_FILE" "$MOUNT_DIR/.VolumeIcon.icns" 170 SetFile -c icnC "$MOUNT_DIR/.VolumeIcon.icns" 171fi 172 173# run applescript 174APPLESCRIPT=$(mktemp -t createdmg) 175cat "$AUX_PATH/template.applescript" | sed -e "s/WINX/$WINX/g" -e "s/WINY/$WINY/g" -e "s/WINW/$WINW/g" -e "s/WINH/$WINH/g" -e "s/BACKGROUND_CLAUSE/$BACKGROUND_CLAUSE/g" -e "s/ICON_SIZE/$ICON_SIZE/g" | perl -pe "s/POSITION_CLAUSE/$POSITION_CLAUSE/g" | perl -pe "s/APPLICATION_CLAUSE/$APPLICATION_CLAUSE/g" | perl -pe "s/HIDING_CLAUSE/$HIDING_CLAUSE/" >"$APPLESCRIPT" 176 177echo "Running Applescript: /usr/bin/osascript \"${APPLESCRIPT}\" \"${VOLUME_NAME}\"" 178"/usr/bin/osascript" "${APPLESCRIPT}" "${VOLUME_NAME}" || true 179echo "Done running the applescript..." 180sleep 4 181 182rm "$APPLESCRIPT" 183 184# make sure it's not world writeable 185echo "Fixing permissions..." 186chmod -Rf go-w "${MOUNT_DIR}" &> /dev/null || true 187echo "Done fixing permissions." 188 189# make the top window open itself on mount: 190echo "Blessing started" 191bless --folder "${MOUNT_DIR}" --openfolder "${MOUNT_DIR}" 192echo "Blessing finished" 193 194if ! test -z "$VOLUME_ICON_FILE"; then 195 # tell the volume that it has a special file attribute 196 SetFile -a C "$MOUNT_DIR" 197fi 198 199# unmount 200echo "Unmounting disk image..." 201hdiutil detach "${DEV_NAME}" 202 203# compress image 204echo "Compressing disk image..." 205hdiutil convert "${DMG_TEMP_NAME}" -format UDZO -imagekey zlib-level=9 -o "${DMG_DIR}/${DMG_NAME}" 206rm -f "${DMG_TEMP_NAME}" 207 208# adding EULA resources 209if [ ! -z "${EULA_RSRC}" -a "${EULA_RSRC}" != "-null-" ]; then 210 echo "adding EULA resources" 211 "${AUX_PATH}/dmg-license.py" "${DMG_DIR}/${DMG_NAME}" "${EULA_RSRC}" 212fi 213 214if [ ! -z "${NOINTERNET}" -a "${NOINTERNET}" == 1 ]; then 215 echo "not setting 'internet-enable' on the dmg" 216else 217 hdiutil internet-enable -yes "${DMG_DIR}/${DMG_NAME}" 218fi 219 220echo "Disk image done" 221exit 0 222