#!/bin/bash # Copyright (c) 2012 The Chromium OS Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # Abort on error. set -e LSB_FILE=/etc/lsb-release # Load common constants and variables. . "$(dirname "$0")/common.sh" usage() { echo "Usage $PROG image [config]" } # Usage: lsbval path-to-lsb-file key # Returns the value for the given lsb-release file variable. lsbval() { local lsbfile="$1" local key="$2" grep ^$key= "$lsbfile" | sed s/^$key=// } # Usage: lsbequals path-to-lsb-file key expected-value # Returns 0 if they match, 1 otherwise. # Also outputs a warning message if they don't match. lsbequals() { local lsbfile="$1" local key="$2" local expectval="$3" local realval=$(lsbval "$lsbfile" $key) if [ "$realval" != "$expectval" ]; then echo "$key mismatch. Expected '$expectval', image contains '$realval'" return 1 fi return 0 } # Usage: check_keyval_in_list lsbfile lsbkey [list of values] # Extracts the lsb-release value for the specified key, and confirms it # matches one of the whitelisted values specified in value_array. # Implementation note: # You can't really pass bash arrays to functions. Best you can do is either # serialize to string/pass/deserialize (e.g. using whitspace/IFS hacks), or, # let the array contents be received as multiple arguments to the target # function. We take the latter approach here, hence the shift's to get the # first 2 arguments out, before we process the rest of the varargs. check_keyval_in_list() { local lsbfile="$1" shift local lsbkey="$1" shift local lsbval=$(lsbval "$lsbfile" "$lsbkey") while [ $# -gt 0 ]; do if [ "$lsbval" == "$1" ]; then return 0 fi shift done # If we get here, it wasn't found echo "$lsbkey: Value '$lsbval' was not recognized" return 1 } # Usage: lsb_syntaxcheck path-to-lsb-file # Enforces a number of basic sanity checks on the overall format and contents # of the lsb-release file: # - Every line is "key=value". # - No space after key, no space before value. # - key is all A-Z or _, but not starting with _. # - value is made up of printable characters, or is empty. # - Each line is a reasonable size (<255 bytes). # - The whole file is a reasonable size (4kb). lsb_syntaxcheck() { local lsbfile="$1" syntaxbad=0 # Checks for key being A-Z_, 1 or more characters, not starting with _. # Also checks for = with no spaces on either side. # Checks that the value contains printables (and not starting with space). # Alternatively, the value is permitted to be empty (0 chars) too. badlines=$(grep -Ev '^[A-Z][A-Z_]*=([[:graph:]][[:print:]]*)?$' "$lsbfile") if [ -n "$badlines" ]; then syntaxbad=1 echo "$lsbfile: Some lines seem non-well-formed:" echo "$badlines" fi # Checks for a lines exceeding a reasonable overall length. badlines=$(grep -E '^.{255}' "$lsbfile") if [ -n "$badlines" ]; then syntaxbad=1 echo "$lsbfile: Some lsb-release lines seem unreasonably long:" echo "$badlines" fi # Overall file size check: size=$(ls -sk "$lsbfile" | cut -d ' ' -f 1) if [ $size -gt 4 ]; then syntaxbad=1 echo "$lsbfile: This file exceeds 4kb" fi return $syntaxbad } main() { # We want to catch all the discrepancies, not just the first one. # So, any time we find one, we set testfail=1 and continue. # When finished we will use testfail to determine our exit value. local testfail=0 if [ $# -ne 1 ] && [ $# -ne 2 ]; then usage exit 1 fi local image="$1" # Default config location: same directory as this script. local configfile="$(dirname "$0")/default_lsb_release.config" # Or, maybe a config was provided on the command line. if [ $# -eq 2 ]; then configfile="$2" fi # Either way, load test-expectations data from config. echo -n "Loading config from $configfile... " . "$configfile" || return 1 echo "Done." local rootfs=$(make_temp_dir) mount_image_partition_ro "$image" 3 "$rootfs" local lsb="$rootfs/$LSB_FILE" # Basic syntax check first. lsb_syntaxcheck "$lsb" || testfail=1 lsbequals $lsb CHROMEOS_AUSERVER "$expected_auserver" || testfail=1 lsbequals $lsb CHROMEOS_RELEASE_NAME "$expected_release_name" || testfail=1 check_keyval_in_list $lsb CHROMEOS_RELEASE_TRACK \ "${expected_release_tracks[@]}" || testfail=1 if check_keyval_in_list $lsb CHROMEOS_RELEASE_BOARD \ "${expected_boards[@]}"; then # Pick the right set of test-expectation data to use. The cuts # turn e.g. x86-foo-pvtkeys into x86-foo. local board=$(lsbval $lsb CHROMEOS_RELEASE_BOARD | cut -d = -f 2 | cut -d - -f 1,2) # a copy of the board string with '-' squished to variable-name-safe '_'. local boardvar=${board//-/_} channel=$(lsbval $lsb CHROMEOS_RELEASE_TRACK) # For a canary or dogfood channel, appid maybe a different default value. if [ $channel = 'canary-channel' ] || [ $channel = 'dogfood-channel' ]; then eval "expected_appid=\"\$expected_appid_${channel%\-channel}\"" else eval "expected_appid=\"\$expected_appid_$boardvar\"" fi lsbequals $lsb CHROMEOS_RELEASE_APPID "$expected_appid" || testfail=1 else # unrecognized board testfail=1 fi exit $testfail } main "$@"