Alex Deymo | 2b19cfb | 2015-03-26 00:35:07 -0700 | [diff] [blame^] | 1 | #!/bin/bash |
| 2 | |
| 3 | # Copyright 2015 The Chromium OS Authors. All rights reserved. |
| 4 | # Use of this source code is governed by a BSD-style license that can be |
| 5 | # found in the LICENSE file. |
| 6 | |
| 7 | set -e |
| 8 | |
| 9 | # cleanup <path> |
| 10 | # Unmount and remove the mountpoint <path> |
| 11 | cleanup() { |
| 12 | if ! sudo umount "$1" 2>/dev/null; then |
| 13 | if mountpoint -q "$1"; then |
| 14 | sync && sudo umount "$1" |
| 15 | fi |
| 16 | fi |
| 17 | rmdir "$1" |
| 18 | } |
| 19 | |
| 20 | # generate_fs <filename> <size> [block_size] [block_groups] |
| 21 | generate_fs() { |
| 22 | local filename="$1" |
| 23 | local size="$2" |
| 24 | local block_size="${3:-4096}" |
| 25 | local block_groups="${4:-}" |
| 26 | |
| 27 | local mkfs_opts=( -q -F -b "${block_size}" -L "ROOT-TEST" -t ext2 ) |
| 28 | if [[ -n "${block_groups}" ]]; then |
| 29 | mkfs_opts+=( -G "${block_groups}" ) |
| 30 | fi |
| 31 | |
| 32 | local mntdir=$(mktemp --tmpdir -d generate_ext2.XXXXXX) |
| 33 | trap 'cleanup "${mntdir}"; rm -f "${filename}"' INT TERM EXIT |
| 34 | |
| 35 | # Cleanup old image. |
| 36 | if [[ -e "${filename}" ]]; then |
| 37 | rm -f "${filename}" |
| 38 | fi |
| 39 | truncate --size="${size}" "${filename}" |
| 40 | |
| 41 | mkfs.ext2 "${mkfs_opts[@]}" "${filename}" |
| 42 | sudo mount "${filename}" "${mntdir}" -o loop |
| 43 | |
| 44 | ### Generate the files used in unittest with descriptive names. |
| 45 | sudo touch "${mntdir}"/empty-file |
| 46 | |
| 47 | # regular: Regular files. |
| 48 | echo "small file" | sudo dd of="${mntdir}"/regular-small status=none |
| 49 | dd if=/dev/zero bs=1024 count=16 status=none | tr '\0' '\141' | |
| 50 | sudo dd of="${mntdir}"/regular-16k status=none |
| 51 | sudo dd if=/dev/zero of="${mntdir}"/regular-32k-zeros bs=1024 count=16 \ |
| 52 | status=none |
| 53 | |
| 54 | echo "with net_cap" | sudo dd of="${mntdir}"/regular-with_net_cap status=none |
| 55 | sudo setcap cap_net_raw=ep "${mntdir}"/regular-with_net_cap |
| 56 | |
| 57 | # sparse_empty: Files with no data blocks at all (only sparse holes). |
| 58 | sudo truncate --size=10240 "${mntdir}"/sparse_empty-10k |
| 59 | sudo truncate --size=$(( block_size * 2 )) "${mntdir}"/sparse_empty-2blocks |
| 60 | |
| 61 | # sparse: Files with some data blocks but also sparse holes. |
| 62 | echo -n "foo" | |
| 63 | sudo dd of="${mntdir}"/sparse-16k-last_block bs=1 \ |
| 64 | seek=$(( 16 * 1024 - 3)) status=none |
| 65 | |
| 66 | # ext2 inodes have 12 direct blocks, one indirect, one double indirect and |
| 67 | # one triple indirect. 10000 should be enough to have an indirect and double |
| 68 | # indirect block. |
| 69 | echo -n "foo" | |
| 70 | sudo dd of="${mntdir}"/sparse-10000blocks bs=1 \ |
| 71 | seek=$(( block_size * 10000 )) status=none |
| 72 | |
| 73 | sudo truncate --size=16384 "${mntdir}"/sparse-16k-first_block |
| 74 | echo "first block" | sudo dd of="${mntdir}"/sparse-16k-first_block status=none |
| 75 | |
| 76 | sudo truncate --size=16384 "${mntdir}"/sparse-16k-holes |
| 77 | echo "a" | sudo dd of="${mntdir}"/sparse-16k-holes bs=1 seek=100 status=none |
| 78 | echo "b" | sudo dd of="${mntdir}"/sparse-16k-holes bs=1 seek=10000 status=none |
| 79 | |
| 80 | # link: symlinks and hardlinks. |
| 81 | sudo ln -s "broken-link" "${mntdir}"/link-short_symlink |
| 82 | sudo ln -s $(dd if=/dev/zero bs=256 count=1 status=none | tr '\0' '\141') \ |
| 83 | "${mntdir}"/link-long_symlink |
| 84 | sudo ln "${mntdir}"/regular-16k "${mntdir}"/link-hard-regular-16k |
| 85 | |
| 86 | # Directories. |
| 87 | sudo mkdir -p "${mntdir}"/dir1/dir2/dir1 |
| 88 | echo "foo" | sudo tee "${mntdir}"/dir1/dir2/file >/dev/null |
| 89 | echo "bar" | sudo tee "${mntdir}"/dir1/file >/dev/null |
| 90 | |
| 91 | # removed: removed files that should not be listed. |
| 92 | echo "We will remove this file so it's contents will be somewhere in the " \ |
| 93 | "empty space data but it won't be all zeros." | |
| 94 | sudo dd of="${mntdir}"/removed conv=fsync status=none |
| 95 | sudo rm "${mntdir}"/removed |
| 96 | |
| 97 | cleanup "${mntdir}" |
| 98 | trap - INT TERM EXIT |
| 99 | } |
| 100 | |
| 101 | image_desc="${1:-}" |
| 102 | output_dir="${2:-}" |
| 103 | |
| 104 | if [[ ! -e "${image_desc}" || ! -d "${output_dir}" ]]; then |
| 105 | echo "Use: $0 <image_description.txt> <output_dir>" >&2 |
| 106 | exit 1 |
| 107 | fi |
| 108 | |
| 109 | args=( $(cat ${image_desc}) ) |
| 110 | dest_image="${output_dir}/$(basename ${image_desc} .txt).img" |
| 111 | generate_fs "${dest_image}" "${args[@]}" |