Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 #!/bin/sh | |
| 2 # | |
| 3 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. | |
| 4 # Use of this source code is governed by a BSD-style license that can be | |
| 5 # found in the LICENSE file. | |
| 6 # | |
| 7 # This attempts to guide linux users through the process of putting a recovery | |
| 8 # image onto a removeable USB drive. | |
| 9 # | |
| 10 # We may not need root privileges if we have the right permissions. | |
|
Sumit
2010/12/04 00:26:07
Won't dd require sudo?
| |
| 11 # | |
| 12 set -eu | |
| 13 | |
| 14 ############################################################################## | |
| 15 # Configuration goes here | |
| 16 | |
| 17 # Where should we do our work? Use 'WORKDIR=' to make a temporary directory, | |
| 18 # but using a persistent location may let us resume interrupted downloads or | |
| 19 # run again without needing to download a second time. | |
| 20 WORKDIR=/tmp/tmp.crosrec | |
| 21 | |
| 22 # Where do we look for the config file? | |
| 23 CONFIGURL='http://www.chromium.org/some/random/place.cfg' | |
| 24 | |
| 25 # What version is this script? It must match the 'recovery_tool_version=' value | |
| 26 # in the config file that we'll download. | |
| 27 MYVERSION='1.0' | |
|
Sumit
2010/12/04 00:26:07
Lets decrease the version here, I will ask Scot to
| |
| 28 | |
| 29 | |
| 30 ############################################################################## | |
| 31 # Some temporary filenames | |
| 32 debug='debug.log' | |
| 33 tmpfile='tmp.txt' | |
| 34 config='config.txt' | |
| 35 version='verson.txt' | |
| 36 | |
| 37 ############################################################################## | |
| 38 # Various warning messages | |
| 39 | |
| 40 DEBUG() { | |
| 41 echo "DEBUG: $@" >>"$debug" | |
| 42 } | |
| 43 | |
| 44 warn() { | |
| 45 echo "$@" 1>&2 | |
| 46 } | |
| 47 | |
| 48 quit() { | |
| 49 warn "quitting..." | |
| 50 exit 1 | |
| 51 } | |
| 52 | |
| 53 fatal() { | |
| 54 warn "ERROR: $@" | |
| 55 exit 1 | |
| 56 } | |
| 57 | |
| 58 ufatal() { | |
| 59 warn " | |
| 60 ERROR: $@ | |
| 61 | |
| 62 You may need to run this program as a different user. If that doesn't help, try | |
| 63 using a different computer, or ask a knowledgeable friend for help. | |
| 64 | |
| 65 " | |
| 66 exit 1 | |
| 67 } | |
| 68 | |
| 69 gfatal() { | |
| 70 warn " | |
| 71 ERROR: $@ | |
| 72 | |
| 73 You may need to run this program as a different user. If that doesn't help, it | |
| 74 may be a networking problem or a problem with the images provided by Google. | |
| 75 You might want to check to see if there is a newer version of this tool | |
| 76 available, or if someone else has already reported a problem. | |
| 77 | |
| 78 If all else fails, you could try using a different computer, or ask a | |
| 79 knowledgeable friend for help. | |
| 80 | |
| 81 " | |
| 82 exit 1 | |
| 83 } | |
| 84 | |
| 85 ############################################################################## | |
| 86 # Identify the external utilities that we MUST have available. | |
| 87 # | |
| 88 # I'd like to keep the set of external *NIX commands to an absolute minimum, | |
| 89 # but I have to balance that against producing mysterious errors because the | |
| 90 # shell can't always do everything. Let's make sure that these utilities are | |
| 91 # all in our $PATH, or die with an error. | |
| 92 # | |
| 93 # This also sets the following global variables to select alternative utilities | |
| 94 # when there is more than one equivalent tool available: | |
| 95 # | |
| 96 # FETCH = name of utility used to download files from the web | |
| 97 # FETCHNEW = command to invoke to download fresh each time | |
| 98 # FETCHCONT = command to invoke to download with resume if possible | |
| 99 # CHECK = command to invoke to generate checksums on a file | |
| 100 # | |
| 101 require_utils() { | |
| 102 local external | |
| 103 local errors | |
| 104 local tool | |
| 105 local tmp | |
| 106 | |
| 107 external='cat cut dd grep ls mkdir mount readlink sed sync umount unzip wc' | |
| 108 if [ -z "$WORKDIR" ]; then | |
| 109 external="$external mktemp" | |
| 110 fi | |
| 111 errors= | |
| 112 | |
| 113 for tool in $external ; do | |
| 114 if ! type "$tool" >/dev/null 2>&1 ; then | |
| 115 warn "ERROR: can't find \"$tool\"" | |
| 116 errors=yes | |
| 117 fi | |
| 118 done | |
| 119 | |
| 120 # We also need to a way to fetch files from teh internets. Note that the args | |
| 121 # are different depending on which utility we find. We'll use two variants, | |
| 122 # one to fetch fresh every time and one to try again from where we left off. | |
| 123 FETCH= | |
| 124 if [ -z "$FETCH" ] && tmp=$(type curl 2>/dev/null) ; then | |
| 125 FETCH=curl | |
| 126 FETCHNEW="curl -f -s -S -o" | |
| 127 FETCHCONT="curl -f -C - -o" | |
| 128 fi | |
| 129 if [ -z "$FETCH" ] && tmp=$(type wget 2>/dev/null) ; then | |
| 130 FETCH=wget | |
| 131 FETCHNEW="wget -nv -O" | |
| 132 FETCHCONT="wget -c -O" | |
| 133 fi | |
| 134 if [ -z "$FETCH" ]; then | |
| 135 warn "ERROR: can't find \"curl\" or \"wget\"" | |
| 136 errors=yes | |
| 137 fi | |
| 138 | |
| 139 # Once we've fetched a file we need to compute its checksum. There are a | |
| 140 # couple of possiblities here too. | |
| 141 CHECK= | |
| 142 if [ -z "$CHECK" ] && tmp=$(type md5sum 2>/dev/null) ; then | |
| 143 CHECK="md5sum" | |
| 144 fi | |
| 145 if [ -z "$CHECK" ] && tmp=$(type sha1sum 2>/dev/null) ; then | |
| 146 CHECK="sha1sum" | |
| 147 fi | |
| 148 if [ -z "$CHECK" ]; then | |
| 149 warn "ERROR: can't find \"md5sum\" or \"sha1sum\"" | |
| 150 errors=yes | |
| 151 fi | |
| 152 | |
| 153 if [ -n "$errors" ]; then | |
| 154 ufatal "Some required linux utilities are missing." | |
| 155 fi | |
| 156 } | |
| 157 | |
| 158 ############################################################################## | |
| 159 # Helper functions to handle the config file and image tarball. | |
| 160 | |
| 161 # Each paragraph in the config file should describe a new image. Let's make | |
| 162 # sure it follows all the rules. This scans the config file and returns success | |
| 163 # if it looks valid. As a side-effect, it lists the line numbers of the start | |
| 164 # and end of each stanza in the global variables 'start_lines' and 'end_lines' | |
| 165 # and saves the total number of images in the global variable 'num_images'. | |
| 166 good_config() { | |
| 167 local line | |
| 168 local key | |
| 169 local val | |
| 170 local display_name | |
| 171 local file | |
| 172 local size | |
| 173 local url | |
| 174 local md5 | |
| 175 local sha1 | |
| 176 local skipping | |
| 177 local errors | |
| 178 local count | |
| 179 local line_num | |
| 180 | |
| 181 display_name= | |
| 182 file= | |
| 183 size= | |
| 184 url= | |
| 185 md5= | |
| 186 sha1= | |
| 187 skipping=yes | |
| 188 errors= | |
| 189 count=0 | |
| 190 line_num=0 | |
| 191 | |
| 192 # global | |
| 193 start_lines= | |
| 194 end_lines= | |
| 195 | |
| 196 while read line; do | |
| 197 line_num=$(( line_num + 1 )) | |
| 198 | |
| 199 # We might have some empty lines before the first stanza. Skip them. | |
| 200 if [ -n "$skipping" ] && [ -z "$line" ]; then | |
| 201 continue | |
| 202 fi | |
| 203 | |
| 204 # Got something... | |
| 205 if [ -n "$line" ]; then | |
| 206 key=${line%=*} | |
| 207 val=${line#*=} | |
| 208 if [ -z "$key" ] || [ -z "$val" ] || [ "$key=$val" != "$line" ]; then | |
| 209 DEBUG "ignoring $line" | |
| 210 continue | |
| 211 fi | |
| 212 | |
| 213 # right, looks good | |
| 214 if [ -n "$skipping" ]; then | |
| 215 skipping= | |
| 216 start_lines="$start_lines $line_num" | |
| 217 fi | |
| 218 | |
| 219 case $key in | |
| 220 display_name) | |
| 221 if [ -n "$display_name" ]; then | |
| 222 DEBUG "duplicate $key" | |
| 223 errors=yes | |
| 224 fi | |
| 225 display_name="$val" | |
| 226 ;; | |
| 227 file) | |
| 228 if [ -n "$file" ]; then | |
| 229 DEBUG "duplicate $key" | |
| 230 errors=yes | |
| 231 fi | |
| 232 file="$val" | |
| 233 ;; | |
| 234 size) | |
| 235 if [ -n "$size" ]; then | |
| 236 DEBUG "duplicate $key" | |
| 237 errors=yes | |
| 238 fi | |
| 239 size="$val" | |
| 240 ;; | |
| 241 url) | |
| 242 url="$val" | |
| 243 ;; | |
| 244 md5) | |
| 245 md5="$val" | |
| 246 ;; | |
| 247 sha1) | |
| 248 sha1="$val" | |
| 249 ;; | |
| 250 esac | |
| 251 else | |
| 252 # Between paragraphs. Time to check what we've found so far. | |
| 253 end_lines="$end_lines $line_num" | |
| 254 count=$(( count + 1)) | |
| 255 | |
| 256 if [ -z "$display_name" ]; then | |
| 257 DEBUG "image $count is missing display_name" | |
| 258 errors=yes | |
| 259 fi | |
| 260 if [ -z "$file" ]; then | |
| 261 DEBUG "image $count is missing file" | |
| 262 errors=yes | |
| 263 fi | |
| 264 if [ -z "$size" ]; then | |
| 265 DEBUG "image $count is missing size" | |
| 266 errors=yes | |
| 267 fi | |
| 268 if [ -z "$url" ]; then | |
| 269 DEBUG "image $count is missing url" | |
| 270 errors=yes | |
| 271 fi | |
| 272 if [ "$CHECK" = "md5sum" ] && [ -z "$md5" ]; then | |
| 273 DEBUG "image $count is missing required md5" | |
| 274 errors=yes | |
| 275 fi | |
| 276 if [ "$CHECK" = "sha1sum" ] && [ -z "$sha1" ]; then | |
| 277 DEBUG "image $count is missing required sha1" | |
| 278 errors=yes | |
| 279 fi | |
| 280 | |
| 281 # Prepare for next stanza | |
| 282 display_name= | |
| 283 file= | |
| 284 size= | |
| 285 url= | |
| 286 md5= | |
| 287 sha1= | |
| 288 skipping=yes | |
| 289 fi | |
| 290 done < "$config" | |
| 291 | |
| 292 DEBUG "$count images found" | |
| 293 num_images="$count" | |
| 294 | |
| 295 DEBUG "start_lines=($start_lines)" | |
| 296 DEBUG "end_lines=($end_lines)" | |
| 297 | |
| 298 # return error status | |
| 299 [ "$count" != "0" ] && [ -z "$errors" ] | |
| 300 } | |
| 301 | |
| 302 | |
| 303 # Make the user pick an image to download. On success, it sets the global | |
| 304 # variable 'user_choice' to the selected image number. | |
| 305 choose_image() { | |
| 306 local show | |
| 307 local count | |
| 308 local line | |
| 309 local num | |
| 310 | |
| 311 show=yes | |
| 312 while true; do | |
| 313 if [ -n "$show" ]; then | |
| 314 echo | |
| 315 echo "There are $num_images recovery images to choose from:" | |
| 316 echo | |
| 317 count=0 | |
| 318 echo "0 - <quit>" | |
| 319 grep '^display_name=' "$config" | while read line; do | |
| 320 count=$(( count + 1 )) | |
| 321 echo "$line" | sed "s/display_name=/$count - /" | |
| 322 done | |
| 323 echo | |
| 324 show= | |
| 325 fi | |
| 326 echo -n "Please select a recovery image to download: " | |
| 327 read num | |
| 328 if [ -z "$num" ] || [ "$num" = "?" ]; then | |
| 329 show=yes | |
| 330 elif echo "$num" | grep -q '[^0-9]'; then | |
| 331 echo "Sorry, I didn't understand that." | |
| 332 else | |
| 333 if [ "$num" -lt "0" ] || [ "$num" -gt "$num_images" ]; then | |
| 334 echo "That's not one of the choices." | |
| 335 elif [ "$num" -eq 0 ]; then | |
| 336 quit | |
| 337 else | |
| 338 break; | |
| 339 fi | |
| 340 fi | |
| 341 done | |
| 342 echo | |
| 343 | |
| 344 # global | |
| 345 user_choice="$num" | |
| 346 } | |
| 347 | |
| 348 # Fetch and verify the user's chosen image. On success, it sets the global | |
| 349 # variable 'image_file' to indicate the local name of the unpacked binary that | |
| 350 # should be written to the USB drive. | |
| 351 fetch_image() { | |
| 352 local start | |
| 353 local end | |
| 354 local line | |
| 355 local key | |
| 356 local val | |
| 357 local file | |
| 358 local size | |
| 359 local url | |
| 360 local md5 | |
| 361 local sha1 | |
| 362 local line_num | |
| 363 local tarball | |
| 364 local err | |
| 365 local sum | |
| 366 | |
| 367 file= | |
| 368 size= | |
| 369 url= | |
| 370 md5= | |
| 371 sha1= | |
| 372 line_num="0" | |
| 373 | |
| 374 # Convert image number to line numbers within config file. | |
| 375 start=$(echo $start_lines | cut -d' ' -f$1) | |
| 376 end=$(echo $end_lines | cut -d' ' -f$1) | |
| 377 | |
| 378 while read line; do | |
| 379 # Skip to the start of the desired stanza | |
| 380 line_num=$(( line_num + 1 )) | |
| 381 if [ "$line_num" -lt "$start" ] || [ "$line_num" -ge "$end" ]; then | |
| 382 continue; | |
| 383 fi | |
| 384 | |
| 385 # Process the stanza. | |
| 386 if [ -n "$line" ]; then | |
| 387 key=${line%=*} | |
| 388 val=${line#*=} | |
| 389 if [ -z "$key" ] || [ -z "$val" ] || [ "$key=$val" != "$line" ]; then | |
| 390 DEBUG "ignoring $line" | |
| 391 continue | |
| 392 fi | |
| 393 | |
| 394 case $key in | |
| 395 # The descriptive stuff we'll just save for later. | |
| 396 file) | |
| 397 file="$val" | |
| 398 ;; | |
| 399 size) | |
| 400 size="$val" | |
| 401 ;; | |
| 402 md5) | |
| 403 md5="$val" | |
| 404 ;; | |
| 405 sha1) | |
| 406 sha1="$val" | |
| 407 ;; | |
| 408 url) | |
| 409 # Try to download each url until one works. | |
| 410 if [ -n "$url" ]; then | |
| 411 # We've already got one (it's very nice). | |
| 412 continue; | |
| 413 fi | |
| 414 warn "Downloading image tarball from $val" | |
| 415 warn | |
| 416 tarball=${val##*/} | |
| 417 if $FETCHCONT "$tarball" "$val"; then | |
| 418 # Got it. | |
| 419 url="$val" | |
| 420 else | |
| 421 # If you give curl the '-C -' option but the file you want is | |
| 422 # already complete and the server doesn't report the total size | |
| 423 # correctly, it will report an error instead of just doing nothing. | |
| 424 # We'll try to work around that. | |
| 425 err=$? | |
| 426 if [ "$FETCH" = "curl" ] && [ "$err" = "18" ]; then | |
| 427 warn "Ignoring spurious complaint" | |
| 428 url="$val" | |
| 429 fi | |
| 430 fi | |
| 431 ;; | |
| 432 esac | |
| 433 fi | |
| 434 done < "$config" | |
| 435 | |
| 436 if [ -z "$url" ]; then | |
| 437 DEBUG "couldn't fetch tarball" | |
| 438 return 1 | |
| 439 fi | |
| 440 | |
| 441 # Verify the tarball | |
| 442 if ! ls -l "$tarball" | grep -q "$size"; then | |
| 443 DEBUG "size is wrong" | |
| 444 return 1 | |
| 445 fi | |
| 446 sum=$($CHECK "$tarball" | cut -d' ' -f1) | |
| 447 DEBUG "$CHECK is $sum" | |
| 448 if [ "$CHECK" = "md5sum" ] && [ "$sum" != "$md5" ]; then | |
| 449 DEBUG "wrong $CHECK" | |
| 450 return 1 | |
| 451 elif [ "$CHECK" = "sha1sum" ] && [ "$sum" != "$sha1" ]; then | |
| 452 DEBUG "wrong $CHECK" | |
| 453 return 1 | |
| 454 fi | |
| 455 | |
| 456 # Unpack the file | |
| 457 warn "Unpacking the tarball" | |
| 458 rm -f "$file" | |
| 459 if ! unzip "$tarball" "$file"; then | |
| 460 DEBUG "Can't unpack the tarball" | |
| 461 return 1 | |
| 462 fi | |
| 463 | |
| 464 # global | |
| 465 image_file="$file" | |
| 466 } | |
| 467 | |
| 468 ############################################################################## | |
| 469 # Helper functions to manage USB drives. | |
| 470 | |
| 471 # Return a list of base device names ("sda sdb ...") for all USB drives | |
| 472 get_devlist() { | |
| 473 local dev | |
| 474 local t | |
| 475 local r | |
| 476 | |
| 477 for dev in $(cat /proc/partitions); do | |
| 478 [ -r "/sys/block/$dev/device/type" ] && | |
| 479 t=$(cat "/sys/block/$dev/device/type") && | |
| 480 [ "$t" = "0" ] && | |
| 481 r=$(cat "/sys/block/$dev/removable") && | |
| 482 [ "$r" = "1" ] && | |
| 483 readlink -f "/sys/block/$dev" | grep -q -i usb && | |
| 484 echo "$dev" || true | |
| 485 done | |
| 486 } | |
| 487 | |
| 488 # Return descriptions for each provided base device name ("sda sdb ...") | |
| 489 get_devinfo() { | |
| 490 local dev | |
| 491 local v | |
| 492 local m | |
| 493 local s | |
| 494 local ss | |
| 495 | |
| 496 for dev in $1; do | |
| 497 v=$(cat "/sys/block/$dev/device/vendor") && | |
| 498 m=$(cat "/sys/block/$dev/device/model") && | |
| 499 s=$(cat "/sys/block/$dev/size") && ss=$(( $s * 512 / 1000000 )) && | |
| 500 echo "/dev/$dev ${ss}MB $v $m" | |
| 501 done | |
| 502 } | |
| 503 | |
| 504 # Enumerate and descript the specified base device names ("sda sdb ...") | |
| 505 get_choices() { | |
| 506 local dev | |
| 507 local desc | |
| 508 local count | |
| 509 | |
| 510 count=1 | |
| 511 echo "0 - <quit>" | |
| 512 for dev in $1; do | |
| 513 desc=$(get_devinfo "$dev") | |
| 514 echo "$count - Use $desc" | |
| 515 count=$(( count + 1 )) | |
| 516 done | |
| 517 } | |
| 518 | |
| 519 # Make the user pick a USB drive to write to. On success, it sets the global | |
| 520 # variable 'user_choice' to the selected device name ("sda", "sdb", etc.) | |
| 521 choose_drive() { | |
| 522 local show | |
| 523 local devlist | |
| 524 local choices | |
| 525 local num_drives | |
| 526 local msg | |
| 527 local num | |
| 528 | |
| 529 show=yes | |
| 530 while true; do | |
| 531 if [ -n "$show" ]; then | |
| 532 devlist=$(get_devlist) | |
| 533 choices=$(get_choices "$devlist") | |
| 534 if [ -z "$devlist" ]; then | |
| 535 num_drives="0" | |
| 536 msg="I can't seem to find a valid USB drive." | |
| 537 else | |
| 538 num_drives=$(echo "$devlist" | wc -l) | |
| 539 if [ "$num_drives" != "1" ]; then | |
| 540 msg="I found $num_drives USB drives" | |
| 541 else | |
| 542 msg="I found $num_drives USB drive" | |
| 543 fi | |
| 544 fi | |
| 545 echo -n " | |
| 546 | |
| 547 $msg | |
| 548 | |
| 549 $choices | |
| 550 | |
| 551 " | |
| 552 show= | |
| 553 fi | |
| 554 echo -n "Tell me what to do (or just press Enter to scan again): " | |
| 555 read num | |
| 556 if [ -z "$num" ] || [ "$num" = "?" ]; then | |
| 557 show=yes | |
| 558 elif echo "$num" | grep -q '[^0-9]'; then | |
| 559 echo "Sorry, I didn't understand that." | |
| 560 else | |
| 561 if [ "$num" -lt "0" ] || [ "$num" -gt "$num_drives" ]; then | |
| 562 echo "That's not one of the choices." | |
| 563 elif [ "$num" -eq 0 ]; then | |
| 564 quit | |
| 565 else | |
| 566 break; | |
| 567 fi | |
| 568 fi | |
| 569 done | |
| 570 | |
| 571 # global | |
| 572 user_choice=$(echo $devlist | cut -d' ' -f$num) | |
| 573 } | |
| 574 | |
| 575 | |
| 576 ############################################################################## | |
| 577 # Okay, do something... | |
| 578 | |
| 579 # Make sure we have the tools we need | |
| 580 require_utils | |
| 581 | |
| 582 # Need a place to work. We prefer a fixed location so we can try to resume any | |
| 583 # interrupted downloads. | |
| 584 if [ -n "$WORKDIR" ]; then | |
| 585 if [ ! -d "$WORKDIR" ] && ! mkdir "$WORKDIR" ; then | |
| 586 warn "Using temporary directory" | |
| 587 WORKDIR= | |
| 588 fi | |
| 589 fi | |
| 590 if [ -z "$WORKDIR" ]; then | |
| 591 WORKDIR=$(mktemp -d) | |
| 592 # Clean up temporary directory afterwards | |
| 593 trap "cd; rm -rf ${WORKDIR}" EXIT | |
| 594 fi | |
| 595 | |
| 596 cd "$WORKDIR" | |
| 597 warn "Working in $WORKDIR/" | |
| 598 rm -f "$debug" | |
| 599 | |
| 600 # Download the config file to see what choices we have. | |
| 601 warn "Downloading config file from $CONFIGURL" | |
| 602 $FETCHNEW "$tmpfile" "$CONFIGURL" || \ | |
| 603 gfatal "Unable to download the config file" | |
| 604 | |
| 605 # Un-DOS-ify the config file and separate the version info from the images | |
| 606 sed 's/\r//g' "$tmpfile" | grep '^recovery_tool' > "$version" | |
| 607 sed 's/\r//g' "$tmpfile" | grep -v '^#' | grep -v '^recovery_tool' > "$config" | |
| 608 # Add one empty line to the config file to terminate the last stanza | |
| 609 echo >> "$config" | |
| 610 | |
| 611 # Make sure that the config file version matches this script version | |
| 612 tmp=$(grep '^recovery_tool_version=' "$version") || \ | |
| 613 gfatal "The config file doesn't contain a version string." | |
| 614 filevers=${tmp#*=} | |
| 615 if [ "$filevers" != "$MYVERSION" ]; then | |
| 616 tmp=$(grep '^recovery_tool_update=' "$version"); | |
| 617 msg=${tmp#*=} | |
| 618 warn "This tool is version $MYVERSION." \ | |
| 619 "The config file is for version $filevers." | |
| 620 fatal ${msg:-Please download a matching version of the tool and try again.} | |
| 621 fi | |
| 622 | |
| 623 # Check the config file to be sure it's valid. As a side-effect, this sets the | |
| 624 # global variable 'num_images' with the number of image stanzas read, but | |
| 625 # that's independent of whether the config is valid. | |
| 626 good_config || gfatal "The config file isn't valid." | |
| 627 | |
| 628 # Make the user pick an image to download, or exit. | |
| 629 choose_image | |
| 630 | |
| 631 # Download the user's choice | |
| 632 fetch_image "$user_choice" || \ | |
| 633 gfatal "Unable to download a valid recovery image." | |
| 634 | |
| 635 # Make the user pick a USB drive, or exit. | |
| 636 choose_drive | |
| 637 | |
| 638 # Be sure | |
| 639 dev_desc=$(get_devinfo "$user_choice") | |
| 640 echo " | |
| 641 Is this the device you want to put the recovery image on? | |
| 642 | |
| 643 $dev_desc | |
| 644 " | |
| 645 echo -n "You must enter 'YES' to continue: " | |
| 646 read tmp | |
| 647 if [ "$tmp" != "YES" ]; then | |
| 648 quit | |
| 649 fi | |
| 650 | |
| 651 # Be very sure | |
| 652 echo " | |
| 653 | |
| 654 I'm really going to erase this device. This will permanently ERASE | |
| 655 whatever you may have on that drive. You won't be able to undo it. | |
| 656 | |
| 657 $dev_desc | |
| 658 " | |
| 659 | |
| 660 echo -n "If you're sure that's the device to use, enter 'DoIt' now: " | |
| 661 read tmp | |
| 662 if [ "$tmp" != "DoIt" ]; then | |
| 663 quit | |
| 664 fi | |
| 665 echo " | |
| 666 | |
| 667 Installing the recovery image | |
| 668 | |
| 669 " | |
| 670 | |
| 671 # Unmount anything on that device. | |
| 672 echo "unmounting..." | |
| 673 for tmp in $(mount | grep ^"/dev/${user_choice}" | sed 's/[ \t].*//'); do | |
| 674 umount $tmp || ufatal "Unable to unmount $tmp." | |
| 675 done | |
| 676 | |
| 677 # Write it. | |
| 678 echo "copying... (this may take several minutes)" | |
| 679 dd of=/dev/${user_choice} if="$image_file" || | |
| 680 ufatal "Unable to write the image." | |
| 681 sync | |
| 682 | |
| 683 echo " | |
| 684 | |
| 685 Done. Remove the USB drive and insert it in your Chrome OS netbook. | |
| 686 | |
| 687 " | |
| 688 | |
| 689 exit 0 | |
| OLD | NEW |