1#!/bin/bash 2 3# Copyright (C) 2021 The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16# 17 18set -xeuo pipefail 19 20apexer_tool_path="${RUNFILES_DIR}/__main__/external/make_injection/host/linux-x86/bin" 21avb_tool_path="${RUNFILES_DIR}/__main__/external/avb" 22android_jar="${RUNFILES_DIR}/__main__/prebuilts/sdk/current/public/android.jar" 23 24input_dir=$(mktemp -d) 25output_dir=$(mktemp -d) 26 27function cleanup { 28 rm -rf ${input_dir} 29 rm -rf ${output_dir} 30} 31 32trap cleanup ERR 33############################################# 34# prepare the inputs 35############################################# 36# Create the input directory with 37# 1. a file with random bits 38# 2. a file installed sub dir with random bits 39# 3. a one-level symlink 40# 4. a two-level symlink with "execroot/__main__" in the path 41# 5. a two-level sumlink without "execroot/__main__" in the path 42# 6. a three-level symlink with "execroot/__main__" in the path 43echo "test file1" > "${input_dir}/file1" 44echo "test file2" > "${input_dir}/file2" 45mkdir -p "${input_dir}/execroot/__main__" 46ln -s "${input_dir}/file1" "${input_dir}/one_level_sym" 47ln -s "${input_dir}/file2" "${input_dir}/execroot/__main__/middle_sym" 48ln -s "${input_dir}/execroot/__main__/middle_sym" "${input_dir}/two_level_sym_in_execroot" 49ln -s "${input_dir}/one_level_sym" "${input_dir}/two_level_sym_not_in_execroot" 50ln -s "${input_dir}/two_level_sym_in_execroot" "${input_dir}/three_level_sym_in_execroot" 51 52# Create the APEX manifest file 53manifest_dir=$(mktemp -d) 54manifest_file="${manifest_dir}/apex_manifest.pb" 55echo '{"name": "com.android.example.apex", "version": 1}' > "${manifest_dir}/apex_manifest.json" 56"${apexer_tool_path}/conv_apex_manifest" proto "${manifest_dir}/apex_manifest.json" -o ${manifest_file} 57 58# Create the file_contexts file 59file_contexts_file=$(mktemp) 60echo ' 61(/.*)? u:object_r:root_file:s0 62/execroot(/.*)? u:object_r:execroot_file:s0 63' > ${file_contexts_file} 64 65output_file="${output_dir}/test.apex" 66 67# Create the wrapper manifest file 68bazel_apexer_wrapper_manifest_file=$(mktemp) 69echo " 70dir1,file1,"${input_dir}/file1" 71dir2/dir3,file2,"${input_dir}/file2" 72dir4,one_level_sym,"${input_dir}/one_level_sym" 73dir5,two_level_sym_in_execroot,"${input_dir}/two_level_sym_in_execroot" 74dir6,two_level_sym_not_in_execroot,"${input_dir}/two_level_sym_not_in_execroot" 75dir7,three_level_sym_in_execroot,"${input_dir}/three_level_sym_in_execroot" 76" > ${bazel_apexer_wrapper_manifest_file} 77 78############################################# 79# run bazel_apexer_wrapper 80############################################# 81"${RUNFILES_DIR}/__main__/build/bazel/rules/apex/bazel_apexer_wrapper" \ 82 --manifest ${manifest_file} \ 83 --file_contexts ${file_contexts_file} \ 84 --key "${RUNFILES_DIR}/__main__/build/bazel/rules/apex/test.pem" \ 85 --apexer_path ${apexer_tool_path} \ 86 --apexer_tool_paths ${apexer_tool_path}:${avb_tool_path} \ 87 --apex_output_file ${output_file} \ 88 --bazel_apexer_wrapper_manifest ${bazel_apexer_wrapper_manifest_file} \ 89 --android_jar_path ${android_jar} 90 91############################################# 92# check the result 93############################################# 94"${apexer_tool_path}/deapexer" --debugfs_path="${apexer_tool_path}/debugfs" extract ${output_file} ${output_dir} 95 96# The expected mounted tree should be something like this: 97# /tmp/tmp.9u7ViPlMr7 98# ├── apex_manifest.pb 99# ├── apex_payload.img 100# ├── mnt 101# │ ├── apex_manifest.pb 102# │ ├── dir1 103# │ │ └── file1 104# │ ├── dir2 105# │ │ └── dir3 106# │ │ └── file2 107# │ ├── dir4 108# │ │ └── one_level_sym 109# (one level symlinks always resolve) 110# │ ├── dir5 111# │ │ └── two_level_sym_in_execroot 112# (two level symlink resolve if the path contains execroot/__main__) 113# │ ├── dir6 114# │ │ └── two_level_sym_not_in_execroot -> /tmp/tmp.evJh21oYGG/file1 115# (two level symlink resolve only one level otherwise) 116# │ ├── dir7 117# │ │ └── three_level_sym_in_execroot 118# (three level symlink resolve if the path contains execroot/__main__) 119# └── test.apex 120 121# b/215129834: 122# https://android-review.googlesource.com/c/platform/system/apex/+/1944264 made 123# it such that the hash of non-payload files in the APEX (like 124# AndroidManifest.xml) will be included as part of the apex_manifest.pb via the 125# apexContainerFilesHash string to ensure that changes to AndroidManifest.xml 126# results in changes in content hash for the apex_payload.img. Since this is 127# potentially fragile, we skip diffing the apex_manifest.pb, and just check that 128# it exists. 129test -f "${output_dir}/apex_manifest.pb" || echo "expected apex_manifest.pb to exist" 130 131# check the contents with diff for the rest of the files 132diff ${input_dir}/file1 ${output_dir}/dir1/file1 133diff ${input_dir}/file2 ${output_dir}/dir2/dir3/file2 134diff ${input_dir}/file1 ${output_dir}/dir4/one_level_sym 135diff ${input_dir}/file2 ${output_dir}/dir5/two_level_sym_in_execroot 136[ `readlink ${output_dir}/dir6/two_level_sym_not_in_execroot` = "${input_dir}/file1" ] 137diff ${input_dir}/file2 ${output_dir}/dir7/three_level_sym_in_execroot 138 139cleanup 140 141echo "Passed for all test cases" 142