Alex Deymo | 2b19cfb | 2015-03-26 00:35:07 -0700 | [diff] [blame] | 1 | #!/bin/bash |
| 2 | |
Alex Deymo | aea4c1c | 2015-08-19 20:24:43 -0700 | [diff] [blame] | 3 | # |
| 4 | # Copyright (C) 2015 The Android Open Source Project |
| 5 | # |
| 6 | # Licensed under the Apache License, Version 2.0 (the "License"); |
| 7 | # you may not use this file except in compliance with the License. |
| 8 | # You may obtain a copy of the License at |
| 9 | # |
| 10 | # http://www.apache.org/licenses/LICENSE-2.0 |
| 11 | # |
| 12 | # Unless required by applicable law or agreed to in writing, software |
| 13 | # distributed under the License is distributed on an "AS IS" BASIS, |
| 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 15 | # See the License for the specific language governing permissions and |
| 16 | # limitations under the License. |
| 17 | # |
Alex Deymo | 2b19cfb | 2015-03-26 00:35:07 -0700 | [diff] [blame] | 18 | |
Alex Deymo | 04ef207 | 2015-08-13 08:19:16 -0700 | [diff] [blame] | 19 | # This script generates some sample images used in unittests and packages them |
| 20 | # in the sample_images.tar.bz2 file. The list of generated images and their |
| 21 | # options are described in the main() function. You need to manually run this |
| 22 | # script to update the generated images whenever you modify this script. |
| 23 | |
Alex Deymo | 2b19cfb | 2015-03-26 00:35:07 -0700 | [diff] [blame] | 24 | set -e |
| 25 | |
| 26 | # cleanup <path> |
| 27 | # Unmount and remove the mountpoint <path> |
| 28 | cleanup() { |
Amin Hassani | d7da8f4 | 2017-08-23 14:29:40 -0700 | [diff] [blame] | 29 | local path="$1" |
| 30 | if ! sudo umount "${path}" 2>/dev/null; then |
| 31 | if mountpoint -q "${path}"; then |
| 32 | sync && sudo umount "${path}" |
Alex Deymo | 2b19cfb | 2015-03-26 00:35:07 -0700 | [diff] [blame] | 33 | fi |
| 34 | fi |
Amin Hassani | d7da8f4 | 2017-08-23 14:29:40 -0700 | [diff] [blame] | 35 | if [ -n "${path}" ]; then |
| 36 | sudo rm -rf "${path}" |
| 37 | fi |
Alex Deymo | 2b19cfb | 2015-03-26 00:35:07 -0700 | [diff] [blame] | 38 | } |
| 39 | |
Alex Deymo | 2e9533b | 2015-06-26 20:57:06 -0700 | [diff] [blame] | 40 | # add_files_default <mntdir> <block_size> |
| 41 | # Add several test files to the image mounted in <mntdir>. |
| 42 | add_files_default() { |
| 43 | local mntdir="$1" |
| 44 | local block_size="$2" |
Alex Deymo | 2b19cfb | 2015-03-26 00:35:07 -0700 | [diff] [blame] | 45 | |
| 46 | ### Generate the files used in unittest with descriptive names. |
| 47 | sudo touch "${mntdir}"/empty-file |
| 48 | |
| 49 | # regular: Regular files. |
| 50 | echo "small file" | sudo dd of="${mntdir}"/regular-small status=none |
| 51 | dd if=/dev/zero bs=1024 count=16 status=none | tr '\0' '\141' | |
| 52 | sudo dd of="${mntdir}"/regular-16k status=none |
| 53 | sudo dd if=/dev/zero of="${mntdir}"/regular-32k-zeros bs=1024 count=16 \ |
| 54 | status=none |
| 55 | |
| 56 | echo "with net_cap" | sudo dd of="${mntdir}"/regular-with_net_cap status=none |
| 57 | sudo setcap cap_net_raw=ep "${mntdir}"/regular-with_net_cap |
| 58 | |
| 59 | # sparse_empty: Files with no data blocks at all (only sparse holes). |
| 60 | sudo truncate --size=10240 "${mntdir}"/sparse_empty-10k |
| 61 | sudo truncate --size=$(( block_size * 2 )) "${mntdir}"/sparse_empty-2blocks |
| 62 | |
| 63 | # sparse: Files with some data blocks but also sparse holes. |
| 64 | echo -n "foo" | |
| 65 | sudo dd of="${mntdir}"/sparse-16k-last_block bs=1 \ |
| 66 | seek=$(( 16 * 1024 - 3)) status=none |
| 67 | |
| 68 | # ext2 inodes have 12 direct blocks, one indirect, one double indirect and |
| 69 | # one triple indirect. 10000 should be enough to have an indirect and double |
| 70 | # indirect block. |
| 71 | echo -n "foo" | |
| 72 | sudo dd of="${mntdir}"/sparse-10000blocks bs=1 \ |
| 73 | seek=$(( block_size * 10000 )) status=none |
| 74 | |
| 75 | sudo truncate --size=16384 "${mntdir}"/sparse-16k-first_block |
| 76 | echo "first block" | sudo dd of="${mntdir}"/sparse-16k-first_block status=none |
| 77 | |
| 78 | sudo truncate --size=16384 "${mntdir}"/sparse-16k-holes |
| 79 | echo "a" | sudo dd of="${mntdir}"/sparse-16k-holes bs=1 seek=100 status=none |
| 80 | echo "b" | sudo dd of="${mntdir}"/sparse-16k-holes bs=1 seek=10000 status=none |
| 81 | |
| 82 | # link: symlinks and hardlinks. |
| 83 | sudo ln -s "broken-link" "${mntdir}"/link-short_symlink |
| 84 | sudo ln -s $(dd if=/dev/zero bs=256 count=1 status=none | tr '\0' '\141') \ |
| 85 | "${mntdir}"/link-long_symlink |
| 86 | sudo ln "${mntdir}"/regular-16k "${mntdir}"/link-hard-regular-16k |
| 87 | |
| 88 | # Directories. |
| 89 | sudo mkdir -p "${mntdir}"/dir1/dir2/dir1 |
| 90 | echo "foo" | sudo tee "${mntdir}"/dir1/dir2/file >/dev/null |
| 91 | echo "bar" | sudo tee "${mntdir}"/dir1/file >/dev/null |
| 92 | |
Sen Jiang | 990c27b | 2016-03-15 17:09:21 -0700 | [diff] [blame] | 93 | # FIFO |
| 94 | sudo mkfifo "${mntdir}"/fifo |
| 95 | |
| 96 | # character special file |
| 97 | sudo mknod "${mntdir}"/cdev c 2 3 |
| 98 | |
Alex Deymo | 2b19cfb | 2015-03-26 00:35:07 -0700 | [diff] [blame] | 99 | # removed: removed files that should not be listed. |
| 100 | echo "We will remove this file so it's contents will be somewhere in the " \ |
| 101 | "empty space data but it won't be all zeros." | |
| 102 | sudo dd of="${mntdir}"/removed conv=fsync status=none |
| 103 | sudo rm "${mntdir}"/removed |
Alex Deymo | 2e9533b | 2015-06-26 20:57:06 -0700 | [diff] [blame] | 104 | } |
| 105 | |
| 106 | # add_files_ue_settings <mntdir> <block_size> |
| 107 | # Add the update_engine.conf settings file. This file contains the |
| 108 | add_files_ue_settings() { |
| 109 | local mntdir="$1" |
| 110 | |
| 111 | sudo mkdir -p "${mntdir}"/etc >/dev/null |
| 112 | sudo tee "${mntdir}"/etc/update_engine.conf >/dev/null <<EOF |
| 113 | PAYLOAD_MINOR_VERSION=1234 |
| 114 | EOF |
| 115 | # Example of a real lsb-release file released on link stable. |
| 116 | sudo tee "${mntdir}"/etc/lsb-release >/dev/null <<EOF |
| 117 | CHROMEOS_AUSERVER=https://tools.google.com/service/update2 |
| 118 | CHROMEOS_BOARD_APPID={F26D159B-52A3-491A-AE25-B23670A66B32} |
| 119 | CHROMEOS_CANARY_APPID={90F229CE-83E2-4FAF-8479-E368A34938B1} |
| 120 | CHROMEOS_DEVSERVER= |
| 121 | CHROMEOS_RELEASE_APPID={F26D159B-52A3-491A-AE25-B23670A66B32} |
| 122 | CHROMEOS_RELEASE_BOARD=link-signed-mp-v4keys |
| 123 | CHROMEOS_RELEASE_BRANCH_NUMBER=63 |
| 124 | CHROMEOS_RELEASE_BUILD_NUMBER=6946 |
| 125 | CHROMEOS_RELEASE_BUILD_TYPE=Official Build |
| 126 | CHROMEOS_RELEASE_CHROME_MILESTONE=43 |
| 127 | CHROMEOS_RELEASE_DESCRIPTION=6946.63.0 (Official Build) stable-channel link |
| 128 | CHROMEOS_RELEASE_NAME=Chrome OS |
| 129 | CHROMEOS_RELEASE_PATCH_NUMBER=0 |
| 130 | CHROMEOS_RELEASE_TRACK=stable-channel |
| 131 | CHROMEOS_RELEASE_VERSION=6946.63.0 |
| 132 | GOOGLE_RELEASE=6946.63.0 |
| 133 | EOF |
| 134 | } |
| 135 | |
Alex Deymo | cbc2274 | 2016-03-04 17:53:02 -0800 | [diff] [blame] | 136 | add_files_postinstall() { |
| 137 | local mntdir="$1" |
| 138 | |
| 139 | sudo mkdir -p "${mntdir}"/bin >/dev/null |
| 140 | |
| 141 | # A postinstall bash program. |
| 142 | sudo tee "${mntdir}"/bin/postinst_example >/dev/null <<EOF |
| 143 | #!/etc/../bin/sh |
| 144 | echo "I'm a postinstall program and I know how to write to stdout" |
| 145 | echo "My call was $@" |
| 146 | exit 0 |
| 147 | EOF |
| 148 | |
| 149 | # A symlink to another program. This should also work. |
| 150 | sudo ln -s "postinst_example" "${mntdir}"/bin/postinst_link |
| 151 | |
| 152 | sudo tee "${mntdir}"/bin/postinst_fail3 >/dev/null <<EOF |
| 153 | #!/etc/../bin/sh |
| 154 | exit 3 |
| 155 | EOF |
| 156 | |
| 157 | sudo tee "${mntdir}"/bin/postinst_fail1 >/dev/null <<EOF |
| 158 | #!/etc/../bin/sh |
| 159 | exit 1 |
| 160 | EOF |
| 161 | |
Alex Deymo | d15c546 | 2016-03-09 18:11:12 -0800 | [diff] [blame] | 162 | # A program that succeeds if it is suspended during the first 5 minutes. |
| 163 | sudo tee "${mntdir}"/bin/postinst_suspend >/dev/null <<EOF |
| 164 | #!/etc/../bin/sh |
| 165 | trap "{ echo Got a SIGCONT; exit 0; }" CONT |
| 166 | # Signal that we are ready to receive the signal by redirecting our stdin to |
| 167 | # /dev/zero, the test can detect that. |
| 168 | exec </dev/zero |
| 169 | # Allow the signal handler to run every 100 ms. |
| 170 | i=3000 |
| 171 | while [ \$i -ge 0 ]; do |
| 172 | sleep 0.1 |
| 173 | i=\$((i-1)) |
| 174 | done |
| 175 | exit 1 |
| 176 | EOF |
| 177 | |
Alex Deymo | 0d29854 | 2016-03-30 18:31:49 -0700 | [diff] [blame] | 178 | # A program that reports back progress. |
| 179 | sudo tee "${mntdir}"/bin/postinst_progress >/dev/null <<EOF |
| 180 | #!/etc/../bin/sh |
| 181 | # These values have exact representation in IEEE 754 so we avoid rounding |
| 182 | # errors. |
| 183 | echo global_progress 0.25 >&3 |
| 184 | echo global_progress 0.5 >&3 |
| 185 | echo global_progress 1.0 >&3 |
| 186 | exit 0 |
| 187 | EOF |
| 188 | |
Alex Deymo | cbc2274 | 2016-03-04 17:53:02 -0800 | [diff] [blame] | 189 | # A postinstall bash program. |
| 190 | sudo tee "${mntdir}"/bin/self_check_context >/dev/null <<EOF |
| 191 | #!/etc/../bin/sh |
| 192 | echo "This is my context:" |
| 193 | ls -lZ "\$0" | grep -F ' u:object_r:postinstall_file:s0 ' || exit 5 |
| 194 | exit 0 |
| 195 | EOF |
| 196 | |
| 197 | sudo tee "${mntdir}"/postinst >/dev/null <<EOF |
| 198 | #!/etc/../bin/sh |
| 199 | echo "postinst" |
| 200 | exit 0 |
| 201 | EOF |
| 202 | |
| 203 | sudo chmod +x "${mntdir}"/postinst "${mntdir}"/bin/* |
| 204 | } |
| 205 | |
Alex Deymo | 2e9533b | 2015-06-26 20:57:06 -0700 | [diff] [blame] | 206 | # generate_fs <filename> <kind> <size> [block_size] [block_groups] |
| 207 | generate_fs() { |
| 208 | local filename="$1" |
Amin Hassani | d7da8f4 | 2017-08-23 14:29:40 -0700 | [diff] [blame] | 209 | local type="$2" |
| 210 | local kind="$3" |
| 211 | local size="$4" |
| 212 | local block_size="${5:-4096}" |
| 213 | local block_groups="${6:-}" |
Alex Deymo | 2e9533b | 2015-06-26 20:57:06 -0700 | [diff] [blame] | 214 | |
| 215 | local mkfs_opts=( -q -F -b "${block_size}" -L "ROOT-TEST" -t ext2 ) |
| 216 | if [[ -n "${block_groups}" ]]; then |
| 217 | mkfs_opts+=( -G "${block_groups}" ) |
| 218 | fi |
| 219 | |
| 220 | local mntdir=$(mktemp --tmpdir -d generate_ext2.XXXXXX) |
| 221 | trap 'cleanup "${mntdir}"; rm -f "${filename}"' INT TERM EXIT |
Alex Deymo | 2e9533b | 2015-06-26 20:57:06 -0700 | [diff] [blame] | 222 | # Cleanup old image. |
| 223 | if [[ -e "${filename}" ]]; then |
| 224 | rm -f "${filename}" |
| 225 | fi |
Alex Deymo | 2e9533b | 2015-06-26 20:57:06 -0700 | [diff] [blame] | 226 | |
Amin Hassani | d7da8f4 | 2017-08-23 14:29:40 -0700 | [diff] [blame] | 227 | if [[ "${type}" == "ext2" ]]; then |
| 228 | truncate --size="${size}" "${filename}" |
Alex Deymo | 2e9533b | 2015-06-26 20:57:06 -0700 | [diff] [blame] | 229 | |
Amin Hassani | d7da8f4 | 2017-08-23 14:29:40 -0700 | [diff] [blame] | 230 | mkfs.ext2 "${mkfs_opts[@]}" "${filename}" |
| 231 | sudo mount "${filename}" "${mntdir}" -o loop |
| 232 | fi |
Alex Deymo | 2e9533b | 2015-06-26 20:57:06 -0700 | [diff] [blame] | 233 | case "${kind}" in |
Alex Deymo | d15c546 | 2016-03-09 18:11:12 -0800 | [diff] [blame] | 234 | unittest) |
Alex Deymo | 2e9533b | 2015-06-26 20:57:06 -0700 | [diff] [blame] | 235 | add_files_ue_settings "${mntdir}" "${block_size}" |
Alex Deymo | cbc2274 | 2016-03-04 17:53:02 -0800 | [diff] [blame] | 236 | add_files_postinstall "${mntdir}" "${block_size}" |
Alex Deymo | 2e9533b | 2015-06-26 20:57:06 -0700 | [diff] [blame] | 237 | ;; |
| 238 | default) |
| 239 | add_files_default "${mntdir}" "${block_size}" |
| 240 | ;; |
Alex Deymo | c90be63 | 2016-02-17 19:25:20 -0800 | [diff] [blame] | 241 | empty) |
| 242 | ;; |
Alex Deymo | 2e9533b | 2015-06-26 20:57:06 -0700 | [diff] [blame] | 243 | esac |
Alex Deymo | 2b19cfb | 2015-03-26 00:35:07 -0700 | [diff] [blame] | 244 | |
Amin Hassani | d7da8f4 | 2017-08-23 14:29:40 -0700 | [diff] [blame] | 245 | if [[ "${type}" == "sqfs" ]]; then |
| 246 | mksquashfs "${mntdir}" "${filename}" |
| 247 | fi |
| 248 | |
Alex Deymo | 2b19cfb | 2015-03-26 00:35:07 -0700 | [diff] [blame] | 249 | cleanup "${mntdir}" |
| 250 | trap - INT TERM EXIT |
| 251 | } |
| 252 | |
Alex Deymo | 04ef207 | 2015-08-13 08:19:16 -0700 | [diff] [blame] | 253 | OUTPUT_DIR=$(dirname "$0") |
| 254 | IMAGES=() |
Alex Deymo | 2b19cfb | 2015-03-26 00:35:07 -0700 | [diff] [blame] | 255 | |
Alex Deymo | 04ef207 | 2015-08-13 08:19:16 -0700 | [diff] [blame] | 256 | # generate_image <image_name> [<image args> ...] |
| 257 | generate_image() { |
| 258 | echo "Generating image $1.img" |
| 259 | IMAGES+=( "$1.img" ) |
| 260 | generate_fs "${OUTPUT_DIR}/$1.img" "${@:2}" |
| 261 | } |
Alex Deymo | 2b19cfb | 2015-03-26 00:35:07 -0700 | [diff] [blame] | 262 | |
Alex Deymo | 04ef207 | 2015-08-13 08:19:16 -0700 | [diff] [blame] | 263 | main() { |
| 264 | # Add more sample images here. |
Amin Hassani | d7da8f4 | 2017-08-23 14:29:40 -0700 | [diff] [blame] | 265 | generate_image disk_ext2_1k ext2 default $((1024 * 1024)) 1024 |
| 266 | generate_image disk_ext2_4k ext2 default $((1024 * 4096)) 4096 |
| 267 | generate_image disk_ext2_4k_empty ext2 empty $((1024 * 4096)) 4096 |
| 268 | generate_image disk_ext2_unittest ext2 unittest $((1024 * 4096)) 4096 |
| 269 | |
| 270 | # Add squashfs sample images. |
| 271 | generate_image disk_sqfs_empty sqfs empty $((1024 * 4096)) 4096 |
| 272 | generate_image disk_sqfs_default sqfs default $((1024 * 4096)) 4096 |
Amin Hassani | 77c25fc | 2019-01-29 10:24:19 -0800 | [diff] [blame^] | 273 | generate_image disk_sqfs_unittest sqfs unittest $((1024 * 4096)) 4096 |
Alex Deymo | 04ef207 | 2015-08-13 08:19:16 -0700 | [diff] [blame] | 274 | |
| 275 | # Generate the tarball and delete temporary images. |
| 276 | echo "Packing tar file sample_images.tar.bz2" |
| 277 | tar -jcf "${OUTPUT_DIR}/sample_images.tar.bz2" -C "${OUTPUT_DIR}" \ |
Alex Deymo | a3553e4 | 2016-03-04 18:55:05 -0800 | [diff] [blame] | 278 | --sparse "${IMAGES[@]}" |
Alex Deymo | 04ef207 | 2015-08-13 08:19:16 -0700 | [diff] [blame] | 279 | cd "${OUTPUT_DIR}" |
| 280 | rm "${IMAGES[@]}" |
| 281 | } |
| 282 | |
| 283 | main |