blob: e0b54ae9ca957856d5e24c12727b5eb4d3bf7f5b [file] [log] [blame]
Alex Deymo2b19cfb2015-03-26 00:35:07 -07001#!/bin/bash
2
Alex Deymoaea4c1c2015-08-19 20:24:43 -07003#
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 Deymo2b19cfb2015-03-26 00:35:07 -070018
Alex Deymo04ef2072015-08-13 08:19:16 -070019# 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 Deymo2b19cfb2015-03-26 00:35:07 -070024set -e
25
26# cleanup <path>
27# Unmount and remove the mountpoint <path>
28cleanup() {
Amin Hassanid7da8f42017-08-23 14:29:40 -070029 local path="$1"
30 if ! sudo umount "${path}" 2>/dev/null; then
31 if mountpoint -q "${path}"; then
32 sync && sudo umount "${path}"
Alex Deymo2b19cfb2015-03-26 00:35:07 -070033 fi
34 fi
Amin Hassanid7da8f42017-08-23 14:29:40 -070035 if [ -n "${path}" ]; then
36 sudo rm -rf "${path}"
37 fi
Alex Deymo2b19cfb2015-03-26 00:35:07 -070038}
39
Alex Deymo2e9533b2015-06-26 20:57:06 -070040# add_files_default <mntdir> <block_size>
41# Add several test files to the image mounted in <mntdir>.
42add_files_default() {
43 local mntdir="$1"
44 local block_size="$2"
Alex Deymo2b19cfb2015-03-26 00:35:07 -070045
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 Jiang990c27b2016-03-15 17:09:21 -070093 # FIFO
94 sudo mkfifo "${mntdir}"/fifo
95
96 # character special file
97 sudo mknod "${mntdir}"/cdev c 2 3
98
Alex Deymo2b19cfb2015-03-26 00:35:07 -070099 # 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 Deymo2e9533b2015-06-26 20:57:06 -0700104}
105
106# add_files_ue_settings <mntdir> <block_size>
107# Add the update_engine.conf settings file. This file contains the
108add_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
113PAYLOAD_MINOR_VERSION=1234
114EOF
115 # Example of a real lsb-release file released on link stable.
116 sudo tee "${mntdir}"/etc/lsb-release >/dev/null <<EOF
117CHROMEOS_AUSERVER=https://tools.google.com/service/update2
118CHROMEOS_BOARD_APPID={F26D159B-52A3-491A-AE25-B23670A66B32}
119CHROMEOS_CANARY_APPID={90F229CE-83E2-4FAF-8479-E368A34938B1}
120CHROMEOS_DEVSERVER=
121CHROMEOS_RELEASE_APPID={F26D159B-52A3-491A-AE25-B23670A66B32}
122CHROMEOS_RELEASE_BOARD=link-signed-mp-v4keys
123CHROMEOS_RELEASE_BRANCH_NUMBER=63
124CHROMEOS_RELEASE_BUILD_NUMBER=6946
125CHROMEOS_RELEASE_BUILD_TYPE=Official Build
126CHROMEOS_RELEASE_CHROME_MILESTONE=43
127CHROMEOS_RELEASE_DESCRIPTION=6946.63.0 (Official Build) stable-channel link
128CHROMEOS_RELEASE_NAME=Chrome OS
129CHROMEOS_RELEASE_PATCH_NUMBER=0
130CHROMEOS_RELEASE_TRACK=stable-channel
131CHROMEOS_RELEASE_VERSION=6946.63.0
132GOOGLE_RELEASE=6946.63.0
133EOF
134}
135
Alex Deymocbc22742016-03-04 17:53:02 -0800136add_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
144echo "I'm a postinstall program and I know how to write to stdout"
145echo "My call was $@"
146exit 0
147EOF
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
154exit 3
155EOF
156
157 sudo tee "${mntdir}"/bin/postinst_fail1 >/dev/null <<EOF
158#!/etc/../bin/sh
159exit 1
160EOF
161
Alex Deymod15c5462016-03-09 18:11:12 -0800162 # 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
165trap "{ 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.
168exec </dev/zero
169# Allow the signal handler to run every 100 ms.
170i=3000
171while [ \$i -ge 0 ]; do
172 sleep 0.1
173 i=\$((i-1))
174done
175exit 1
176EOF
177
Alex Deymo0d298542016-03-30 18:31:49 -0700178 # 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.
183echo global_progress 0.25 >&3
184echo global_progress 0.5 >&3
185echo global_progress 1.0 >&3
186exit 0
187EOF
188
Alex Deymocbc22742016-03-04 17:53:02 -0800189 # A postinstall bash program.
190 sudo tee "${mntdir}"/bin/self_check_context >/dev/null <<EOF
191#!/etc/../bin/sh
192echo "This is my context:"
193ls -lZ "\$0" | grep -F ' u:object_r:postinstall_file:s0 ' || exit 5
194exit 0
195EOF
196
197 sudo tee "${mntdir}"/postinst >/dev/null <<EOF
198#!/etc/../bin/sh
199echo "postinst"
200exit 0
201EOF
202
203 sudo chmod +x "${mntdir}"/postinst "${mntdir}"/bin/*
204}
205
Alex Deymo2e9533b2015-06-26 20:57:06 -0700206# generate_fs <filename> <kind> <size> [block_size] [block_groups]
207generate_fs() {
208 local filename="$1"
Amin Hassanid7da8f42017-08-23 14:29:40 -0700209 local type="$2"
210 local kind="$3"
211 local size="$4"
212 local block_size="${5:-4096}"
213 local block_groups="${6:-}"
Alex Deymo2e9533b2015-06-26 20:57:06 -0700214
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 Deymo2e9533b2015-06-26 20:57:06 -0700222 # Cleanup old image.
223 if [[ -e "${filename}" ]]; then
224 rm -f "${filename}"
225 fi
Alex Deymo2e9533b2015-06-26 20:57:06 -0700226
Amin Hassanid7da8f42017-08-23 14:29:40 -0700227 if [[ "${type}" == "ext2" ]]; then
228 truncate --size="${size}" "${filename}"
Alex Deymo2e9533b2015-06-26 20:57:06 -0700229
Amin Hassanid7da8f42017-08-23 14:29:40 -0700230 mkfs.ext2 "${mkfs_opts[@]}" "${filename}"
231 sudo mount "${filename}" "${mntdir}" -o loop
232 fi
Alex Deymo2e9533b2015-06-26 20:57:06 -0700233 case "${kind}" in
Alex Deymod15c5462016-03-09 18:11:12 -0800234 unittest)
Alex Deymo2e9533b2015-06-26 20:57:06 -0700235 add_files_ue_settings "${mntdir}" "${block_size}"
Alex Deymocbc22742016-03-04 17:53:02 -0800236 add_files_postinstall "${mntdir}" "${block_size}"
Alex Deymo2e9533b2015-06-26 20:57:06 -0700237 ;;
238 default)
239 add_files_default "${mntdir}" "${block_size}"
240 ;;
Alex Deymoc90be632016-02-17 19:25:20 -0800241 empty)
242 ;;
Alex Deymo2e9533b2015-06-26 20:57:06 -0700243 esac
Alex Deymo2b19cfb2015-03-26 00:35:07 -0700244
Amin Hassanid7da8f42017-08-23 14:29:40 -0700245 if [[ "${type}" == "sqfs" ]]; then
246 mksquashfs "${mntdir}" "${filename}"
247 fi
248
Alex Deymo2b19cfb2015-03-26 00:35:07 -0700249 cleanup "${mntdir}"
250 trap - INT TERM EXIT
251}
252
Alex Deymo04ef2072015-08-13 08:19:16 -0700253OUTPUT_DIR=$(dirname "$0")
254IMAGES=()
Alex Deymo2b19cfb2015-03-26 00:35:07 -0700255
Alex Deymo04ef2072015-08-13 08:19:16 -0700256# generate_image <image_name> [<image args> ...]
257generate_image() {
258 echo "Generating image $1.img"
259 IMAGES+=( "$1.img" )
260 generate_fs "${OUTPUT_DIR}/$1.img" "${@:2}"
261}
Alex Deymo2b19cfb2015-03-26 00:35:07 -0700262
Alex Deymo04ef2072015-08-13 08:19:16 -0700263main() {
264 # Add more sample images here.
Amin Hassanid7da8f42017-08-23 14:29:40 -0700265 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 Hassani77c25fc2019-01-29 10:24:19 -0800273 generate_image disk_sqfs_unittest sqfs unittest $((1024 * 4096)) 4096
Alex Deymo04ef2072015-08-13 08:19:16 -0700274
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 Deymoa3553e42016-03-04 18:55:05 -0800278 --sparse "${IMAGES[@]}"
Alex Deymo04ef2072015-08-13 08:19:16 -0700279 cd "${OUTPUT_DIR}"
280 rm "${IMAGES[@]}"
281}
282
283main