Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | #!/bin/bash |
| 2 | # Copyright (C) Martin Schlemmer <azarah@nosferatu.za.org> |
| 3 | # Released under the terms of the GNU GPL |
| 4 | # |
| 5 | # Generate a newline separated list of entries from the file/directory |
| 6 | # supplied as an argument. |
| 7 | # |
| 8 | # If a file/directory is not supplied then generate a small dummy file. |
| 9 | # |
| 10 | # The output is suitable for gen_init_cpio built from usr/gen_init_cpio.c. |
| 11 | # |
| 12 | |
| 13 | default_initramfs() { |
| 14 | cat <<-EOF |
| 15 | # This is a very simple, default initramfs |
| 16 | |
| 17 | dir /dev 0755 0 0 |
| 18 | nod /dev/console 0600 0 0 c 5 1 |
| 19 | dir /root 0700 0 0 |
| 20 | EOF |
| 21 | } |
| 22 | |
| 23 | filetype() { |
| 24 | local argv1="$1" |
| 25 | |
| 26 | # symlink test must come before file test |
| 27 | if [ -L "${argv1}" ]; then |
| 28 | echo "slink" |
| 29 | elif [ -f "${argv1}" ]; then |
| 30 | echo "file" |
| 31 | elif [ -d "${argv1}" ]; then |
| 32 | echo "dir" |
| 33 | elif [ -b "${argv1}" -o -c "${argv1}" ]; then |
| 34 | echo "nod" |
| 35 | elif [ -p "${argv1}" ]; then |
| 36 | echo "pipe" |
| 37 | elif [ -S "${argv1}" ]; then |
| 38 | echo "sock" |
| 39 | else |
| 40 | echo "invalid" |
| 41 | fi |
| 42 | return 0 |
| 43 | } |
| 44 | |
| 45 | print_mtime() { |
| 46 | local argv1="$1" |
| 47 | local my_mtime="0" |
| 48 | |
| 49 | if [ -e "${argv1}" ]; then |
| 50 | my_mtime=$(find "${argv1}" -printf "%T@\n" | sort -r | head -n 1) |
| 51 | fi |
| 52 | |
| 53 | echo "# Last modified: ${my_mtime}" |
| 54 | echo |
| 55 | } |
| 56 | |
| 57 | parse() { |
| 58 | local location="$1" |
| 59 | local name="${location/${srcdir}//}" |
| 60 | # change '//' into '/' |
| 61 | name="${name//\/\///}" |
| 62 | local mode="$2" |
| 63 | local uid="$3" |
| 64 | local gid="$4" |
| 65 | local ftype=$(filetype "${location}") |
| 66 | # remap uid/gid to 0 if necessary |
| 67 | [ "$uid" -eq "$root_uid" ] && uid=0 |
| 68 | [ "$gid" -eq "$root_gid" ] && gid=0 |
| 69 | local str="${mode} ${uid} ${gid}" |
| 70 | |
| 71 | [ "${ftype}" == "invalid" ] && return 0 |
| 72 | [ "${location}" == "${srcdir}" ] && return 0 |
| 73 | |
| 74 | case "${ftype}" in |
| 75 | "file") |
| 76 | str="${ftype} ${name} ${location} ${str}" |
| 77 | ;; |
| 78 | "nod") |
| 79 | local dev_type= |
| 80 | local maj=$(LC_ALL=C ls -l "${location}" | \ |
| 81 | gawk '{sub(/,/, "", $5); print $5}') |
| 82 | local min=$(LC_ALL=C ls -l "${location}" | \ |
| 83 | gawk '{print $6}') |
| 84 | |
| 85 | if [ -b "${location}" ]; then |
| 86 | dev_type="b" |
| 87 | else |
| 88 | dev_type="c" |
| 89 | fi |
| 90 | str="${ftype} ${name} ${str} ${dev_type} ${maj} ${min}" |
| 91 | ;; |
| 92 | "slink") |
| 93 | local target=$(LC_ALL=C ls -l "${location}" | \ |
| 94 | gawk '{print $11}') |
| 95 | str="${ftype} ${name} ${target} ${str}" |
| 96 | ;; |
| 97 | *) |
| 98 | str="${ftype} ${name} ${str}" |
| 99 | ;; |
| 100 | esac |
| 101 | |
| 102 | echo "${str}" |
| 103 | |
| 104 | return 0 |
| 105 | } |
| 106 | |
| 107 | usage() { |
| 108 | printf "Usage:\n" |
| 109 | printf "$0 [ [-u <root_uid>] [-g <root_gid>] [-d | <cpio_source>] ] . . .\n" |
| 110 | printf "\n" |
| 111 | printf -- "-u <root_uid> User ID to map to user ID 0 (root).\n" |
| 112 | printf " <root_uid> is only meaningful if <cpio_source>\n" |
| 113 | printf " is a directory.\n" |
| 114 | printf -- "-g <root_gid> Group ID to map to group ID 0 (root).\n" |
| 115 | printf " <root_gid> is only meaningful if <cpio_source>\n" |
| 116 | printf " is a directory.\n" |
| 117 | printf "<cpio_source> File list or directory for cpio archive.\n" |
| 118 | printf " If <cpio_source> is not provided then a\n" |
| 119 | printf " a default list will be output.\n" |
| 120 | printf -- "-d Output the default cpio list. If no <cpio_source>\n" |
| 121 | printf " is given then the default cpio list will be output.\n" |
| 122 | printf "\n" |
| 123 | printf "All options may be repeated and are interpreted sequentially\n" |
| 124 | printf "and immediately. -u and -g states are preserved across\n" |
| 125 | printf "<cpio_source> options so an explicit \"-u 0 -g 0\" is required\n" |
| 126 | printf "to reset the root/group mapping.\n" |
| 127 | } |
| 128 | |
| 129 | build_list() { |
| 130 | printf "\n#####################\n# $cpio_source\n" |
| 131 | |
| 132 | if [ -f "$cpio_source" ]; then |
| 133 | print_mtime "$cpio_source" |
| 134 | cat "$cpio_source" |
| 135 | elif [ -d "$cpio_source" ]; then |
| 136 | srcdir=$(echo "$cpio_source" | sed -e 's://*:/:g') |
| 137 | dirlist=$(find "${srcdir}" -printf "%p %m %U %G\n" 2>/dev/null) |
| 138 | |
| 139 | # If $dirlist is only one line, then the directory is empty |
| 140 | if [ "$(echo "${dirlist}" | wc -l)" -gt 1 ]; then |
| 141 | print_mtime "$cpio_source" |
| 142 | |
| 143 | echo "${dirlist}" | \ |
| 144 | while read x; do |
| 145 | parse ${x} |
| 146 | done |
| 147 | else |
| 148 | # Failsafe in case directory is empty |
| 149 | default_initramfs |
| 150 | fi |
| 151 | else |
| 152 | echo " $0: Cannot open '$cpio_source'" >&2 |
| 153 | exit 1 |
| 154 | fi |
| 155 | } |
| 156 | |
| 157 | |
| 158 | root_uid=0 |
| 159 | root_gid=0 |
| 160 | |
| 161 | while [ $# -gt 0 ]; do |
| 162 | arg="$1" |
| 163 | shift |
| 164 | case "$arg" in |
| 165 | "-u") |
| 166 | root_uid="$1" |
| 167 | shift |
| 168 | ;; |
| 169 | "-g") |
| 170 | root_gid="$1" |
| 171 | shift |
| 172 | ;; |
| 173 | "-d") |
| 174 | default_list="$arg" |
| 175 | default_initramfs |
| 176 | ;; |
| 177 | "-h") |
| 178 | usage |
| 179 | exit 0 |
| 180 | ;; |
| 181 | *) |
| 182 | case "$arg" in |
| 183 | "-"*) |
| 184 | printf "ERROR: unknown option \"$arg\"\n" >&2 |
| 185 | printf "If the filename validly begins with '-', then it must be prefixed\n" >&2 |
| 186 | printf "by './' so that it won't be interpreted as an option." >&2 |
| 187 | printf "\n" >&2 |
| 188 | usage >&2 |
| 189 | exit 1 |
| 190 | ;; |
| 191 | *) |
| 192 | cpio_source="$arg" |
| 193 | build_list |
| 194 | ;; |
| 195 | esac |
| 196 | ;; |
| 197 | esac |
| 198 | done |
| 199 | |
| 200 | # spit out the default cpio list if a source hasn't been specified |
| 201 | [ -z "$cpio_source" -a -z "$default_list" ] && default_initramfs |
| 202 | |
| 203 | exit 0 |