Tue, 06 Jan 2015 21:39:09 +0100
Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
michael@0 | 1 | #!/bin/bash |
michael@0 | 2 | # This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 3 | # License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 4 | # file, You can obtain one at http://mozilla.org/MPL/2.0/. |
michael@0 | 5 | |
michael@0 | 6 | # |
michael@0 | 7 | # This tool generates incremental update packages for the update system. |
michael@0 | 8 | # Author: Darin Fisher |
michael@0 | 9 | # |
michael@0 | 10 | |
michael@0 | 11 | . $(dirname "$0")/common.sh |
michael@0 | 12 | |
michael@0 | 13 | # ----------------------------------------------------------------------------- |
michael@0 | 14 | |
michael@0 | 15 | print_usage() { |
michael@0 | 16 | notice "Usage: $(basename $0) [OPTIONS] ARCHIVE FROMDIR TODIR" |
michael@0 | 17 | notice "" |
michael@0 | 18 | notice "The differences between FROMDIR and TODIR will be stored in ARCHIVE." |
michael@0 | 19 | notice "" |
michael@0 | 20 | notice "Options:" |
michael@0 | 21 | notice " -h show this help text" |
michael@0 | 22 | notice " -f clobber this file in the installation" |
michael@0 | 23 | notice " Must be a path to a file to clobber in the partial update." |
michael@0 | 24 | notice " -q be less verbose" |
michael@0 | 25 | notice "" |
michael@0 | 26 | } |
michael@0 | 27 | |
michael@0 | 28 | check_for_forced_update() { |
michael@0 | 29 | force_list="$1" |
michael@0 | 30 | forced_file_chk="$2" |
michael@0 | 31 | |
michael@0 | 32 | local f |
michael@0 | 33 | |
michael@0 | 34 | if [ "$forced_file_chk" = "precomplete" ]; then |
michael@0 | 35 | ## "true" *giggle* |
michael@0 | 36 | return 0; |
michael@0 | 37 | fi |
michael@0 | 38 | |
michael@0 | 39 | if [ "${forced_file_chk##*.}" = "chk" ] |
michael@0 | 40 | then |
michael@0 | 41 | ## "true" *giggle* |
michael@0 | 42 | return 0; |
michael@0 | 43 | fi |
michael@0 | 44 | |
michael@0 | 45 | for f in $force_list; do |
michael@0 | 46 | #echo comparing $forced_file_chk to $f |
michael@0 | 47 | if [ "$forced_file_chk" = "$f" ]; then |
michael@0 | 48 | ## "true" *giggle* |
michael@0 | 49 | return 0; |
michael@0 | 50 | fi |
michael@0 | 51 | |
michael@0 | 52 | # If the file in the skip list ends with /*, do a prefix match. |
michael@0 | 53 | # This allows TorBrowser/Data/Browser/profile.default/extensions/https-everywhere@eff.org/* to be used to force all HTTPS Everywhere files to be updated. |
michael@0 | 54 | f_suffix=${f##*/} |
michael@0 | 55 | if [[ $f_suffix = "*" ]]; then |
michael@0 | 56 | f_prefix="${f%\/\*}"; |
michael@0 | 57 | if [[ $forced_file_chk == $f_prefix* ]]; then |
michael@0 | 58 | ## 0 means "true" |
michael@0 | 59 | return 0; |
michael@0 | 60 | fi |
michael@0 | 61 | fi |
michael@0 | 62 | done |
michael@0 | 63 | ## 'false'... because this is bash. Oh yay! |
michael@0 | 64 | return 1; |
michael@0 | 65 | } |
michael@0 | 66 | |
michael@0 | 67 | if [ $# = 0 ]; then |
michael@0 | 68 | print_usage |
michael@0 | 69 | exit 1 |
michael@0 | 70 | fi |
michael@0 | 71 | |
michael@0 | 72 | # The last .xpi is NoScript. |
michael@0 | 73 | ext_path='TorBrowser/Data/Browser/profile.default/extensions'; |
michael@0 | 74 | # TODO: it would be better to pass this as a command line option. |
michael@0 | 75 | exts='https-everywhere@eff.org/* tor-launcher@torproject.org.xpi torbutton@torproject.org.xpi uriloader@pdf.js.xpi {73a6fe31-595d-460b-a920-fcc0f8843232}.xpi' |
michael@0 | 76 | requested_forced_updates='Contents/MacOS/TorBrowser.app/Contents/MacOS/firefox' |
michael@0 | 77 | for ext in $exts; do |
michael@0 | 78 | requested_forced_updates="$requested_forced_updates $ext_path/$ext" |
michael@0 | 79 | done |
michael@0 | 80 | |
michael@0 | 81 | |
michael@0 | 82 | # TODO: it would be better to pass this as a command line option. |
michael@0 | 83 | directories_to_remove='TorBrowser/Data/Browser/profile.default/extensions/https-everywhere@eff.org' |
michael@0 | 84 | |
michael@0 | 85 | while getopts "hqf:" flag |
michael@0 | 86 | do |
michael@0 | 87 | case "$flag" in |
michael@0 | 88 | h) print_usage; exit 0 |
michael@0 | 89 | ;; |
michael@0 | 90 | q) QUIET=1 |
michael@0 | 91 | ;; |
michael@0 | 92 | f) requested_forced_updates="$requested_forced_updates $OPTARG" |
michael@0 | 93 | ;; |
michael@0 | 94 | ?) print_usage; exit 1 |
michael@0 | 95 | ;; |
michael@0 | 96 | esac |
michael@0 | 97 | done |
michael@0 | 98 | |
michael@0 | 99 | # ----------------------------------------------------------------------------- |
michael@0 | 100 | |
michael@0 | 101 | let arg_start=$OPTIND-1 |
michael@0 | 102 | shift $arg_start |
michael@0 | 103 | |
michael@0 | 104 | archive="$1" |
michael@0 | 105 | olddir="$2" |
michael@0 | 106 | newdir="$3" |
michael@0 | 107 | # Prevent the workdir from being inside the targetdir so it isn't included in |
michael@0 | 108 | # the update mar. |
michael@0 | 109 | if [ $(echo "$newdir" | grep -c '\/$') = 1 ]; then |
michael@0 | 110 | # Remove the / |
michael@0 | 111 | newdir=$(echo "$newdir" | sed -e 's:\/$::') |
michael@0 | 112 | fi |
michael@0 | 113 | workdir="$newdir.work" |
michael@0 | 114 | updatemanifestv2="$workdir/updatev2.manifest" |
michael@0 | 115 | updatemanifestv3="$workdir/updatev3.manifest" |
michael@0 | 116 | archivefiles="updatev2.manifest updatev3.manifest" |
michael@0 | 117 | |
michael@0 | 118 | mkdir -p "$workdir" |
michael@0 | 119 | |
michael@0 | 120 | # On Mac, the precomplete file added by Bug 386760 will cause OS X to reload the |
michael@0 | 121 | # Info.plist so it launches the right architecture, bug 600098 |
michael@0 | 122 | |
michael@0 | 123 | # Generate a list of all files in the target directory. |
michael@0 | 124 | pushd "$olddir" |
michael@0 | 125 | if test $? -ne 0 ; then |
michael@0 | 126 | exit 1 |
michael@0 | 127 | fi |
michael@0 | 128 | |
michael@0 | 129 | list_files oldfiles |
michael@0 | 130 | list_symlinks oldsymlinks oldsymlink_targets |
michael@0 | 131 | list_dirs olddirs |
michael@0 | 132 | |
michael@0 | 133 | popd |
michael@0 | 134 | |
michael@0 | 135 | pushd "$newdir" |
michael@0 | 136 | if test $? -ne 0 ; then |
michael@0 | 137 | exit 1 |
michael@0 | 138 | fi |
michael@0 | 139 | |
michael@0 | 140 | if [ ! -f "precomplete" ]; then |
michael@0 | 141 | notice "precomplete file is missing!" |
michael@0 | 142 | exit 1 |
michael@0 | 143 | fi |
michael@0 | 144 | |
michael@0 | 145 | list_dirs newdirs |
michael@0 | 146 | list_files newfiles |
michael@0 | 147 | list_symlinks newsymlinks newsymlink_targets |
michael@0 | 148 | |
michael@0 | 149 | popd |
michael@0 | 150 | |
michael@0 | 151 | # Add the type of update to the beginning of the update manifests. |
michael@0 | 152 | notice "" |
michael@0 | 153 | notice "Adding type instruction to update manifests" |
michael@0 | 154 | > "$updatemanifestv2" |
michael@0 | 155 | > "$updatemanifestv3" |
michael@0 | 156 | notice " type partial" |
michael@0 | 157 | echo "type \"partial\"" >> "$updatemanifestv2" |
michael@0 | 158 | echo "type \"partial\"" >> "$updatemanifestv3" |
michael@0 | 159 | |
michael@0 | 160 | # If removal of any old, existing directories is desired, emit the appropriate |
michael@0 | 161 | # rmrfdir commands. |
michael@0 | 162 | notice "" |
michael@0 | 163 | notice "Adding directory removal instructions to update manifests" |
michael@0 | 164 | for dir_to_remove in $directories_to_remove; do |
michael@0 | 165 | # rmrfdir requires a trailing slash, so add one if missing. |
michael@0 | 166 | if ! [[ "$dir_to_remove" =~ /$ ]]; then |
michael@0 | 167 | dir_to_remove="${dir_to_remove}/" |
michael@0 | 168 | fi |
michael@0 | 169 | echo "rmrfdir \"$dir_to_remove\"" >> "$updatemanifestv2" |
michael@0 | 170 | echo "rmrfdir \"$dir_to_remove\"" >> "$updatemanifestv3" |
michael@0 | 171 | done |
michael@0 | 172 | |
michael@0 | 173 | notice "" |
michael@0 | 174 | notice "Adding file patch and add instructions to update manifests" |
michael@0 | 175 | |
michael@0 | 176 | num_oldfiles=${#oldfiles[*]} |
michael@0 | 177 | remove_array= |
michael@0 | 178 | num_removes=0 |
michael@0 | 179 | |
michael@0 | 180 | for ((i=0; $i<$num_oldfiles; i=$i+1)); do |
michael@0 | 181 | f="${oldfiles[$i]}" |
michael@0 | 182 | |
michael@0 | 183 | # This file is created by Talkback, so we can ignore it |
michael@0 | 184 | if [ "$f" = "readme.txt" ]; then |
michael@0 | 185 | continue 1 |
michael@0 | 186 | fi |
michael@0 | 187 | |
michael@0 | 188 | # removed-files is excluded by make_incremental_updates.py so it is excluded |
michael@0 | 189 | # here for consistency. |
michael@0 | 190 | if [ "`basename "$f"`" = "removed-files" ]; then |
michael@0 | 191 | continue 1 |
michael@0 | 192 | fi |
michael@0 | 193 | |
michael@0 | 194 | # If this file exists in the new directory as well, then check if it differs. |
michael@0 | 195 | if [ -f "$newdir/$f" ]; then |
michael@0 | 196 | |
michael@0 | 197 | if check_for_add_if_not_update "$f"; then |
michael@0 | 198 | # The full workdir may not exist yet, so create it if necessary. |
michael@0 | 199 | mkdir -p `dirname "$workdir/$f"` |
michael@0 | 200 | $BZIP2 -cz9 "$newdir/$f" > "$workdir/$f" |
michael@0 | 201 | copy_perm "$newdir/$f" "$workdir/$f" |
michael@0 | 202 | make_add_if_not_instruction "$f" "$updatemanifestv3" |
michael@0 | 203 | archivefiles="$archivefiles \"$f\"" |
michael@0 | 204 | continue 1 |
michael@0 | 205 | fi |
michael@0 | 206 | |
michael@0 | 207 | if check_for_forced_update "$requested_forced_updates" "$f"; then |
michael@0 | 208 | # The full workdir may not exist yet, so create it if necessary. |
michael@0 | 209 | mkdir -p `dirname "$workdir/$f"` |
michael@0 | 210 | $BZIP2 -cz9 "$newdir/$f" > "$workdir/$f" |
michael@0 | 211 | copy_perm "$newdir/$f" "$workdir/$f" |
michael@0 | 212 | make_add_instruction "$f" "$updatemanifestv2" "$updatemanifestv3" 1 |
michael@0 | 213 | archivefiles="$archivefiles \"$f\"" |
michael@0 | 214 | continue 1 |
michael@0 | 215 | fi |
michael@0 | 216 | |
michael@0 | 217 | if ! diff "$olddir/$f" "$newdir/$f" > /dev/null; then |
michael@0 | 218 | # Compute both the compressed binary diff and the compressed file, and |
michael@0 | 219 | # compare the sizes. Then choose the smaller of the two to package. |
michael@0 | 220 | dir=$(dirname "$workdir/$f") |
michael@0 | 221 | mkdir -p "$dir" |
michael@0 | 222 | notice "diffing \"$f\"" |
michael@0 | 223 | $MBSDIFF "$olddir/$f" "$newdir/$f" "$workdir/$f.patch" |
michael@0 | 224 | $BZIP2 -z9 "$workdir/$f.patch" |
michael@0 | 225 | $BZIP2 -cz9 "$newdir/$f" > "$workdir/$f" |
michael@0 | 226 | copy_perm "$newdir/$f" "$workdir/$f" |
michael@0 | 227 | patchfile="$workdir/$f.patch.bz2" |
michael@0 | 228 | patchsize=$(get_file_size "$patchfile") |
michael@0 | 229 | fullsize=$(get_file_size "$workdir/$f") |
michael@0 | 230 | |
michael@0 | 231 | if [ $patchsize -lt $fullsize ]; then |
michael@0 | 232 | make_patch_instruction "$f" "$updatemanifestv2" "$updatemanifestv3" |
michael@0 | 233 | mv -f "$patchfile" "$workdir/$f.patch" |
michael@0 | 234 | rm -f "$workdir/$f" |
michael@0 | 235 | archivefiles="$archivefiles \"$f.patch\"" |
michael@0 | 236 | else |
michael@0 | 237 | make_add_instruction "$f" "$updatemanifestv2" "$updatemanifestv3" |
michael@0 | 238 | rm -f "$patchfile" |
michael@0 | 239 | archivefiles="$archivefiles \"$f\"" |
michael@0 | 240 | fi |
michael@0 | 241 | fi |
michael@0 | 242 | else |
michael@0 | 243 | # remove instructions are added after add / patch instructions for |
michael@0 | 244 | # consistency with make_incremental_updates.py |
michael@0 | 245 | remove_array[$num_removes]=$f |
michael@0 | 246 | (( num_removes++ )) |
michael@0 | 247 | fi |
michael@0 | 248 | done |
michael@0 | 249 | |
michael@0 | 250 | # Remove and re-add symlinks |
michael@0 | 251 | notice "" |
michael@0 | 252 | notice "Adding symlink remove/add instructions to update manifests" |
michael@0 | 253 | num_oldsymlinks=${#oldsymlinks[*]} |
michael@0 | 254 | for ((i=0; $i<$num_oldsymlinks; i=$i+1)); do |
michael@0 | 255 | link="${oldsymlinks[$i]}" |
michael@0 | 256 | verbose_notice " remove: $link" |
michael@0 | 257 | echo "remove \"$link\"" >> "$updatemanifestv2" |
michael@0 | 258 | echo "remove \"$link\"" >> "$updatemanifestv3" |
michael@0 | 259 | done |
michael@0 | 260 | |
michael@0 | 261 | num_newsymlinks=${#newsymlinks[*]} |
michael@0 | 262 | for ((i=0; $i<$num_newsymlinks; i=$i+1)); do |
michael@0 | 263 | link="${newsymlinks[$i]}" |
michael@0 | 264 | target="${newsymlink_targets[$i]}" |
michael@0 | 265 | make_addsymlink_instruction "$link" "$target" "$updatemanifestv2" "$updatemanifestv3" |
michael@0 | 266 | done |
michael@0 | 267 | |
michael@0 | 268 | # Newly added files |
michael@0 | 269 | notice "" |
michael@0 | 270 | notice "Adding file add instructions to update manifests" |
michael@0 | 271 | num_newfiles=${#newfiles[*]} |
michael@0 | 272 | |
michael@0 | 273 | for ((i=0; $i<$num_newfiles; i=$i+1)); do |
michael@0 | 274 | f="${newfiles[$i]}" |
michael@0 | 275 | |
michael@0 | 276 | # removed-files is excluded by make_incremental_updates.py so it is excluded |
michael@0 | 277 | # here for consistency. |
michael@0 | 278 | if [ "`basename "$f"`" = "removed-files" ]; then |
michael@0 | 279 | continue 1 |
michael@0 | 280 | fi |
michael@0 | 281 | |
michael@0 | 282 | # If we've already tested this file, then skip it |
michael@0 | 283 | for ((j=0; $j<$num_oldfiles; j=$j+1)); do |
michael@0 | 284 | if [ "$f" = "${oldfiles[j]}" ]; then |
michael@0 | 285 | continue 2 |
michael@0 | 286 | fi |
michael@0 | 287 | done |
michael@0 | 288 | |
michael@0 | 289 | dir=$(dirname "$workdir/$f") |
michael@0 | 290 | mkdir -p "$dir" |
michael@0 | 291 | |
michael@0 | 292 | $BZIP2 -cz9 "$newdir/$f" > "$workdir/$f" |
michael@0 | 293 | copy_perm "$newdir/$f" "$workdir/$f" |
michael@0 | 294 | |
michael@0 | 295 | if check_for_add_if_not_update "$f"; then |
michael@0 | 296 | make_add_if_not_instruction "$f" "$updatemanifestv3" |
michael@0 | 297 | else |
michael@0 | 298 | make_add_instruction "$f" "$updatemanifestv2" "$updatemanifestv3" |
michael@0 | 299 | fi |
michael@0 | 300 | |
michael@0 | 301 | |
michael@0 | 302 | archivefiles="$archivefiles \"$f\"" |
michael@0 | 303 | done |
michael@0 | 304 | |
michael@0 | 305 | notice "" |
michael@0 | 306 | notice "Adding file remove instructions to update manifests" |
michael@0 | 307 | for ((i=0; $i<$num_removes; i=$i+1)); do |
michael@0 | 308 | f="${remove_array[$i]}" |
michael@0 | 309 | notice " remove \"$f\"" |
michael@0 | 310 | echo "remove \"$f\"" >> "$updatemanifestv2" |
michael@0 | 311 | echo "remove \"$f\"" >> "$updatemanifestv3" |
michael@0 | 312 | done |
michael@0 | 313 | |
michael@0 | 314 | # Add remove instructions for any dead files. |
michael@0 | 315 | notice "" |
michael@0 | 316 | notice "Adding file and directory remove instructions from file 'removed-files'" |
michael@0 | 317 | append_remove_instructions "$newdir" "$updatemanifestv2" "$updatemanifestv3" |
michael@0 | 318 | |
michael@0 | 319 | notice "" |
michael@0 | 320 | notice "Adding directory remove instructions for directories that no longer exist" |
michael@0 | 321 | num_olddirs=${#olddirs[*]} |
michael@0 | 322 | |
michael@0 | 323 | for ((i=0; $i<$num_olddirs; i=$i+1)); do |
michael@0 | 324 | f="${olddirs[$i]}" |
michael@0 | 325 | # If this dir doesn't exist in the new directory remove it. |
michael@0 | 326 | if [ ! -d "$newdir/$f" ]; then |
michael@0 | 327 | notice " rmdir $f/" |
michael@0 | 328 | echo "rmdir \"$f/\"" >> "$updatemanifestv2" |
michael@0 | 329 | echo "rmdir \"$f/\"" >> "$updatemanifestv3" |
michael@0 | 330 | fi |
michael@0 | 331 | done |
michael@0 | 332 | |
michael@0 | 333 | $BZIP2 -z9 "$updatemanifestv2" && mv -f "$updatemanifestv2.bz2" "$updatemanifestv2" |
michael@0 | 334 | $BZIP2 -z9 "$updatemanifestv3" && mv -f "$updatemanifestv3.bz2" "$updatemanifestv3" |
michael@0 | 335 | |
michael@0 | 336 | eval "$MAR -C \"$workdir\" -c output.mar $archivefiles" |
michael@0 | 337 | mv -f "$workdir/output.mar" "$archive" |
michael@0 | 338 | |
michael@0 | 339 | # cleanup |
michael@0 | 340 | rm -fr "$workdir" |
michael@0 | 341 | |
michael@0 | 342 | notice "" |
michael@0 | 343 | notice "Finished" |
michael@0 | 344 | notice "" |