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