Home | History | Annotate | Download | only in sample_images
      1 #!/bin/bash
      2 
      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 #
     18 
     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 
     24 set -e
     25 
     26 # cleanup <path>
     27 # Unmount and remove the mountpoint <path>
     28 cleanup() {
     29   if ! sudo umount "$1" 2>/dev/null; then
     30     if mountpoint -q "$1"; then
     31       sync && sudo umount "$1"
     32     fi
     33   fi
     34   rmdir "$1"
     35 }
     36 
     37 # add_files_default <mntdir> <block_size>
     38 # Add several test files to the image mounted in <mntdir>.
     39 add_files_default() {
     40   local mntdir="$1"
     41   local block_size="$2"
     42 
     43   ### Generate the files used in unittest with descriptive names.
     44   sudo touch "${mntdir}"/empty-file
     45 
     46   # regular: Regular files.
     47   echo "small file" | sudo dd of="${mntdir}"/regular-small status=none
     48   dd if=/dev/zero bs=1024 count=16 status=none | tr '\0' '\141' |
     49     sudo dd of="${mntdir}"/regular-16k status=none
     50   sudo dd if=/dev/zero of="${mntdir}"/regular-32k-zeros bs=1024 count=16 \
     51     status=none
     52 
     53   echo "with net_cap" | sudo dd of="${mntdir}"/regular-with_net_cap status=none
     54   sudo setcap cap_net_raw=ep "${mntdir}"/regular-with_net_cap
     55 
     56   # sparse_empty: Files with no data blocks at all (only sparse holes).
     57   sudo truncate --size=10240 "${mntdir}"/sparse_empty-10k
     58   sudo truncate --size=$(( block_size * 2 )) "${mntdir}"/sparse_empty-2blocks
     59 
     60   # sparse: Files with some data blocks but also sparse holes.
     61   echo -n "foo" |
     62     sudo dd of="${mntdir}"/sparse-16k-last_block bs=1 \
     63       seek=$(( 16 * 1024 - 3)) status=none
     64 
     65   # ext2 inodes have 12 direct blocks, one indirect, one double indirect and
     66   # one triple indirect. 10000 should be enough to have an indirect and double
     67   # indirect block.
     68   echo -n "foo" |
     69     sudo dd of="${mntdir}"/sparse-10000blocks bs=1 \
     70       seek=$(( block_size * 10000 )) status=none
     71 
     72   sudo truncate --size=16384 "${mntdir}"/sparse-16k-first_block
     73   echo "first block" | sudo dd of="${mntdir}"/sparse-16k-first_block status=none
     74 
     75   sudo truncate --size=16384 "${mntdir}"/sparse-16k-holes
     76   echo "a" | sudo dd of="${mntdir}"/sparse-16k-holes bs=1 seek=100 status=none
     77   echo "b" | sudo dd of="${mntdir}"/sparse-16k-holes bs=1 seek=10000 status=none
     78 
     79   # link: symlinks and hardlinks.
     80   sudo ln -s "broken-link" "${mntdir}"/link-short_symlink
     81   sudo ln -s $(dd if=/dev/zero bs=256 count=1 status=none | tr '\0' '\141') \
     82     "${mntdir}"/link-long_symlink
     83   sudo ln "${mntdir}"/regular-16k "${mntdir}"/link-hard-regular-16k
     84 
     85   # Directories.
     86   sudo mkdir -p "${mntdir}"/dir1/dir2/dir1
     87   echo "foo" | sudo tee "${mntdir}"/dir1/dir2/file >/dev/null
     88   echo "bar" | sudo tee "${mntdir}"/dir1/file >/dev/null
     89 
     90   # removed: removed files that should not be listed.
     91   echo "We will remove this file so it's contents will be somewhere in the " \
     92     "empty space data but it won't be all zeros." |
     93     sudo dd of="${mntdir}"/removed conv=fsync status=none
     94   sudo rm "${mntdir}"/removed
     95 }
     96 
     97 # add_files_ue_settings <mntdir> <block_size>
     98 # Add the update_engine.conf settings file. This file contains the
     99 add_files_ue_settings() {
    100   local mntdir="$1"
    101 
    102   sudo mkdir -p "${mntdir}"/etc >/dev/null
    103   sudo tee "${mntdir}"/etc/update_engine.conf >/dev/null <<EOF
    104 PAYLOAD_MINOR_VERSION=1234
    105 EOF
    106   # Example of a real lsb-release file released on link stable.
    107   sudo tee "${mntdir}"/etc/lsb-release >/dev/null <<EOF
    108 CHROMEOS_AUSERVER=https://tools.google.com/service/update2
    109 CHROMEOS_BOARD_APPID={F26D159B-52A3-491A-AE25-B23670A66B32}
    110 CHROMEOS_CANARY_APPID={90F229CE-83E2-4FAF-8479-E368A34938B1}
    111 CHROMEOS_DEVSERVER=
    112 CHROMEOS_RELEASE_APPID={F26D159B-52A3-491A-AE25-B23670A66B32}
    113 CHROMEOS_RELEASE_BOARD=link-signed-mp-v4keys
    114 CHROMEOS_RELEASE_BRANCH_NUMBER=63
    115 CHROMEOS_RELEASE_BUILD_NUMBER=6946
    116 CHROMEOS_RELEASE_BUILD_TYPE=Official Build
    117 CHROMEOS_RELEASE_CHROME_MILESTONE=43
    118 CHROMEOS_RELEASE_DESCRIPTION=6946.63.0 (Official Build) stable-channel link
    119 CHROMEOS_RELEASE_NAME=Chrome OS
    120 CHROMEOS_RELEASE_PATCH_NUMBER=0
    121 CHROMEOS_RELEASE_TRACK=stable-channel
    122 CHROMEOS_RELEASE_VERSION=6946.63.0
    123 GOOGLE_RELEASE=6946.63.0
    124 EOF
    125 }
    126 
    127 add_files_postinstall() {
    128   local mntdir="$1"
    129 
    130   sudo mkdir -p "${mntdir}"/bin >/dev/null
    131 
    132   # A postinstall bash program.
    133   sudo tee "${mntdir}"/bin/postinst_example >/dev/null <<EOF
    134 #!/etc/../bin/sh
    135 echo "I'm a postinstall program and I know how to write to stdout"
    136 echo "My call was $@"
    137 exit 0
    138 EOF
    139 
    140   # A symlink to another program. This should also work.
    141   sudo ln -s "postinst_example" "${mntdir}"/bin/postinst_link
    142 
    143   sudo tee "${mntdir}"/bin/postinst_fail3 >/dev/null <<EOF
    144 #!/etc/../bin/sh
    145 exit 3
    146 EOF
    147 
    148   sudo tee "${mntdir}"/bin/postinst_fail1 >/dev/null <<EOF
    149 #!/etc/../bin/sh
    150 exit 1
    151 EOF
    152 
    153   # A program that succeeds if it is suspended during the first 5 minutes.
    154   sudo tee "${mntdir}"/bin/postinst_suspend >/dev/null <<EOF
    155 #!/etc/../bin/sh
    156 trap "{ echo Got a SIGCONT; exit 0; }" CONT
    157 # Signal that we are ready to receive the signal by redirecting our stdin to
    158 # /dev/zero, the test can detect that.
    159 exec </dev/zero
    160 # Allow the signal handler to run every 100 ms.
    161 i=3000
    162 while [ \$i -ge 0 ]; do
    163   sleep 0.1
    164   i=\$((i-1))
    165 done
    166 exit 1
    167 EOF
    168 
    169   # A program that reports back progress.
    170   sudo tee "${mntdir}"/bin/postinst_progress >/dev/null <<EOF
    171 #!/etc/../bin/sh
    172 # These values have exact representation in IEEE 754 so we avoid rounding
    173 # errors.
    174 echo global_progress 0.25 >&3
    175 echo global_progress 0.5 >&3
    176 echo global_progress 1.0 >&3
    177 exit 0
    178 EOF
    179 
    180   # A postinstall bash program.
    181   sudo tee "${mntdir}"/bin/self_check_context >/dev/null <<EOF
    182 #!/etc/../bin/sh
    183 echo "This is my context:"
    184 ls -lZ "\$0" | grep -F ' u:object_r:postinstall_file:s0 ' || exit 5
    185 exit 0
    186 EOF
    187 
    188   sudo tee "${mntdir}"/postinst >/dev/null <<EOF
    189 #!/etc/../bin/sh
    190 echo "postinst"
    191 exit 0
    192 EOF
    193 
    194   sudo chmod +x "${mntdir}"/postinst "${mntdir}"/bin/*
    195 }
    196 
    197 # generate_fs <filename> <kind> <size> [block_size] [block_groups]
    198 generate_fs() {
    199   local filename="$1"
    200   local kind="$2"
    201   local size="$3"
    202   local block_size="${4:-4096}"
    203   local block_groups="${5:-}"
    204 
    205   local mkfs_opts=( -q -F -b "${block_size}" -L "ROOT-TEST" -t ext2 )
    206   if [[ -n "${block_groups}" ]]; then
    207     mkfs_opts+=( -G "${block_groups}" )
    208   fi
    209 
    210   local mntdir=$(mktemp --tmpdir -d generate_ext2.XXXXXX)
    211   trap 'cleanup "${mntdir}"; rm -f "${filename}"' INT TERM EXIT
    212 
    213   # Cleanup old image.
    214   if [[ -e "${filename}" ]]; then
    215     rm -f "${filename}"
    216   fi
    217   truncate --size="${size}" "${filename}"
    218 
    219   mkfs.ext2 "${mkfs_opts[@]}" "${filename}"
    220   sudo mount "${filename}" "${mntdir}" -o loop
    221 
    222   case "${kind}" in
    223     unittest)
    224       add_files_ue_settings "${mntdir}" "${block_size}"
    225       add_files_postinstall "${mntdir}" "${block_size}"
    226       ;;
    227     default)
    228       add_files_default "${mntdir}" "${block_size}"
    229       ;;
    230     empty)
    231       ;;
    232   esac
    233 
    234   cleanup "${mntdir}"
    235   trap - INT TERM EXIT
    236 }
    237 
    238 OUTPUT_DIR=$(dirname "$0")
    239 IMAGES=()
    240 
    241 # generate_image <image_name> [<image args> ...]
    242 generate_image() {
    243   echo "Generating image $1.img"
    244   IMAGES+=( "$1.img" )
    245   generate_fs "${OUTPUT_DIR}/$1.img" "${@:2}"
    246 }
    247 
    248 main() {
    249   # Add more sample images here.
    250   generate_image disk_ext2_1k default 16777216 1024
    251   generate_image disk_ext2_4k default 16777216 4096
    252   generate_image disk_ext2_4k_empty empty $((1024 * 4096)) 4096
    253   generate_image disk_ext2_unittest unittest $((1024 * 4096)) 4096
    254 
    255   # Generate the tarball and delete temporary images.
    256   echo "Packing tar file sample_images.tar.bz2"
    257   tar -jcf "${OUTPUT_DIR}/sample_images.tar.bz2" -C "${OUTPUT_DIR}" \
    258     --sparse "${IMAGES[@]}"
    259   cd "${OUTPUT_DIR}"
    260   rm "${IMAGES[@]}"
    261 }
    262 
    263 main
    264