1 #!/bin/bash 2 3 # Copyright (c) 2012 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 # Abort on error. 8 set -e 9 10 LSB_FILE=/etc/lsb-release 11 12 # Load common constants and variables. 13 . "$(dirname "$0")/common.sh" 14 15 usage() { 16 echo "Usage $PROG image [config]" 17 } 18 19 # Usage: lsbval path-to-lsb-file key 20 # Returns the value for the given lsb-release file variable. 21 lsbval() { 22 local lsbfile="$1" 23 local key="$2" 24 grep ^$key= "$lsbfile" | sed s/^$key=// 25 } 26 27 # Usage: lsbequals path-to-lsb-file key expected-value 28 # Returns 0 if they match, 1 otherwise. 29 # Also outputs a warning message if they don't match. 30 lsbequals() { 31 local lsbfile="$1" 32 local key="$2" 33 local expectval="$3" 34 local realval=$(lsbval "$lsbfile" $key) 35 if [ "$realval" != "$expectval" ]; then 36 echo "$key mismatch. Expected '$expectval', image contains '$realval'" 37 return 1 38 fi 39 return 0 40 } 41 42 # Usage: check_keyval_in_list lsbfile lsbkey [list of values] 43 # Extracts the lsb-release value for the specified key, and confirms it 44 # matches one of the whitelisted values specified in value_array. 45 # Implementation note: 46 # You can't really pass bash arrays to functions. Best you can do is either 47 # serialize to string/pass/deserialize (e.g. using whitspace/IFS hacks), or, 48 # let the array contents be received as multiple arguments to the target 49 # function. We take the latter approach here, hence the shift's to get the 50 # first 2 arguments out, before we process the rest of the varargs. 51 check_keyval_in_list() { 52 local lsbfile="$1" 53 shift 54 local lsbkey="$1" 55 shift 56 local lsbval=$(lsbval "$lsbfile" "$lsbkey") 57 while [ $# -gt 0 ]; do 58 if [ "$lsbval" == "$1" ]; then 59 return 0 60 fi 61 shift 62 done 63 # If we get here, it wasn't found 64 echo "$lsbkey: Value '$lsbval' was not recognized" 65 return 1 66 } 67 68 # Usage: lsb_syntaxcheck path-to-lsb-file 69 # Enforces a number of basic sanity checks on the overall format and contents 70 # of the lsb-release file: 71 # - Every line is "key=value". 72 # - No space after key, no space before value. 73 # - key is all A-Z or _, but not starting with _. 74 # - value is made up of printable characters, or is empty. 75 # - Each line is a reasonable size (<255 bytes). 76 # - The whole file is a reasonable size (4kb). 77 lsb_syntaxcheck() { 78 local lsbfile="$1" 79 syntaxbad=0 80 # Checks for key being A-Z_, 1 or more characters, not starting with _. 81 # Also checks for = with no spaces on either side. 82 # Checks that the value contains printables (and not starting with space). 83 # Alternatively, the value is permitted to be empty (0 chars) too. 84 badlines=$(grep -Ev '^[A-Z][A-Z_]*=([[:graph:]][[:print:]]*)?$' "$lsbfile") 85 if [ -n "$badlines" ]; then 86 syntaxbad=1 87 echo "$lsbfile: Some lines seem non-well-formed:" 88 echo "$badlines" 89 fi 90 91 # Checks for a lines exceeding a reasonable overall length. 92 badlines=$(grep -E '^.{255}' "$lsbfile") 93 if [ -n "$badlines" ]; then 94 syntaxbad=1 95 echo "$lsbfile: Some lsb-release lines seem unreasonably long:" 96 echo "$badlines" 97 fi 98 # Overall file size check: 99 size=$(ls -sk "$lsbfile" | cut -d ' ' -f 1) 100 if [ $size -gt 4 ]; then 101 syntaxbad=1 102 echo "$lsbfile: This file exceeds 4kb" 103 fi 104 return $syntaxbad 105 } 106 107 main() { 108 # We want to catch all the discrepancies, not just the first one. 109 # So, any time we find one, we set testfail=1 and continue. 110 # When finished we will use testfail to determine our exit value. 111 local testfail=0 112 113 if [ $# -ne 1 ] && [ $# -ne 2 ]; then 114 usage 115 exit 1 116 fi 117 118 local image="$1" 119 120 # Default config location: same directory as this script. 121 local configfile="$(dirname "$0")/default_lsb_release.config" 122 # Or, maybe a config was provided on the command line. 123 if [ $# -eq 2 ]; then 124 configfile="$2" 125 fi 126 # Either way, load test-expectations data from config. 127 echo -n "Loading config from $configfile... " 128 . "$configfile" || return 1 129 echo "Done." 130 131 local rootfs=$(make_temp_dir) 132 mount_image_partition_ro "$image" 3 "$rootfs" 133 local lsb="$rootfs/$LSB_FILE" 134 135 # Basic syntax check first. 136 lsb_syntaxcheck "$lsb" || testfail=1 137 138 lsbequals $lsb CHROMEOS_AUSERVER "$expected_auserver" || testfail=1 139 lsbequals $lsb CHROMEOS_RELEASE_NAME "$expected_release_name" || testfail=1 140 check_keyval_in_list $lsb CHROMEOS_RELEASE_TRACK \ 141 "${expected_release_tracks[@]}" || testfail=1 142 143 if check_keyval_in_list $lsb CHROMEOS_RELEASE_BOARD \ 144 "${expected_boards[@]}"; then 145 # Pick the right set of test-expectation data to use. The cuts 146 # turn e.g. x86-foo-pvtkeys into x86-foo. 147 local board=$(lsbval $lsb CHROMEOS_RELEASE_BOARD | 148 cut -d = -f 2 | 149 cut -d - -f 1,2) 150 # a copy of the board string with '-' squished to variable-name-safe '_'. 151 local boardvar=${board//-/_} 152 channel=$(lsbval $lsb CHROMEOS_RELEASE_TRACK) 153 # For a canary or dogfood channel, appid maybe a different default value. 154 if [ $channel = 'canary-channel' ] || [ $channel = 'dogfood-channel' ]; then 155 eval "expected_appid=\"\$expected_appid_${channel%\-channel}\"" 156 else 157 eval "expected_appid=\"\$expected_appid_$boardvar\"" 158 fi 159 lsbequals $lsb CHROMEOS_RELEASE_APPID "$expected_appid" || testfail=1 160 else # unrecognized board 161 testfail=1 162 fi 163 164 exit $testfail 165 } 166 167 main "$@" 168