blob: ba5256f77dd7a3a7bcc8212f4d491324333eb311 [file] [log] [blame]
Kenny Root30c11022010-09-21 10:13:19 -07001#!/bin/bash
2#
3# Copyright (C) 2010 The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16#
17
18# mkobb.sh - Creates OBB files on Linux machines
19
20# Directory where we should temporarily mount the OBB loopback to copy files
21MOUNTDIR=/tmp
22
23# Presets. Changing these will probably break your OBB on the device
Kenny Root735de3b2010-09-30 14:11:39 -070024CRYPTO=twofish
Kenny Root30c11022010-09-21 10:13:19 -070025FS=vfat
26MKFS=mkfs.vfat
27LOSETUP=losetup
28BLOCK_SIZE=512
29SLOP=512 # Amount of filesystem slop in ${BLOCK_SIZE} blocks
30
31find_binaries() {
32 MKFSBIN=`which ${MKFS}`
33 LOSETUPBIN=`which ${LOSETUP}`
34 MOUNTBIN=`which mount`
35 UMOUNTBIN=`which umount`
36 DDBIN=`which dd`
37 RSYNCBIN=`which rsync`
38}
39
40check_prereqs() {
41 if [ "`uname -s`x" != "Linuxx" ]; then \
42 echo "ERROR: This script only works on Linux!"
43 exit 1
44 fi
45
46 if ! egrep -q "^cryptoloop " /proc/modules; then \
47 echo "ERROR: Could not find cryptoloop in the kernel."
48 echo "Perhaps you need to: modprobe cryptoloop"
49 exit 1
50 fi
51
52 if ! egrep -q "name\s*:\s*${CRYPTO}$" /proc/crypto; then \
53 echo "ERROR: Could not find crypto \`${CRYPTO}' in the kernel."
54 echo "Perhaps you need to: modprobe ${CRYPTO}"
55 exit 1
56 fi
57
58 if ! egrep -q "^\s*${FS}$" /proc/filesystems; then \
59 echo "ERROR: Could not find filesystem \`${FS}' in the kernel."
60 echo "Perhaps you need to: modprobe ${FS}"
61 exit 1
62 fi
63
64 if [ "${MKFSBIN}x" = "x" ]; then \
65 echo "ERROR: Could not find ${MKFS} in your path!"
66 exit 1
67 elif [ ! -x "${MKFSBIN}" ]; then \
68 echo "ERROR: ${MKFSBIN} is not executable!"
69 exit 1
70 fi
71
72 if [ "${LOSETUPBIN}x" = "x" ]; then \
73 echo "ERROR: Could not find ${LOSETUP} in your path!"
74 exit 1
75 elif [ ! -x "${LOSETUPBIN}" ]; then \
76 echo "ERROR: ${LOSETUPBIN} is not executable!"
77 exit 1
78 fi
79}
80
81cleanup() {
82 if [ "${loopdev}x" != "x" ]; then \
83 ${LOSETUPBIN} -d ${loopdev}
84 fi
85}
86
87hidden_prompt() {
88 unset output
89 prompt="$1"
90 outvar="$2"
91 while read -s -n 1 -p "$prompt" c; do \
92 if [ "x$c" = "x" ]; then \
93 break
94 fi
95 prompt='*'
96 output="${output}${c}"
97 done
98 echo
99 eval $outvar="$output"
100 unset output
101}
102
103read_key() {
104 hidden_prompt " Encryption key: " key
105
106 if [ "${key}x" = "x" ]; then \
107 echo "ERROR: An empty key is not allowed!"
108 exit 1
109 fi
110
111 hidden_prompt "Encryption key (again): " key2
112
113 if [ "${key}x" != "${key2}x" ]; then \
114 echo "ERROR: Encryption keys do not match!"
115 exit 1
116 fi
117}
118
119onexit() {
120 if [ "x${temp_mount}" != "x" ]; then \
121 ${UMOUNTBIN} ${temp_mount}
122 rmdir ${temp_mount}
123 fi
124 if [ "x${loop_dev}" != "x" ]; then \
Kenny Root735de3b2010-09-30 14:11:39 -0700125 if [ ${use_crypto} -eq 1 ]; then \
126 dmsetup remove -f ${loop_dev}
127 ${LOSETUPBIN} -d ${old_loop_dev}
128 else \
129 ${LOSETUPBIN} -d ${loop_dev}
130 fi
Kenny Root30c11022010-09-21 10:13:19 -0700131 fi
132 if [ "x${tempfile}" != "x" -a -f "${tempfile}" ]; then \
133 rm -f ${tempfile}
134 fi
135 if [ "x${keyfile}" != "x" -a -f "${keyfile}" ]; then \
136 rm -f ${keyfile}
137 fi
138 echo "Fatal error."
139 exit 1
140}
141
142usage() {
143 echo "mkobb.sh -- Create OBB files for use on Android"
144 echo ""
145 echo " -c Use an encrypted OBB; must specify key"
146 echo " -d <directory> Use <directory> as input for OBB files"
147 echo " -k <key> Use <key> to encrypt OBB file"
148 echo " -K Prompt for key to encrypt OBB file"
149 echo " -o <filename> Write OBB file out to <filename>"
150 echo " -v Verbose mode"
151 echo " -h Help; this usage screen"
152}
153
154find_binaries
155check_prereqs
156
157use_crypto=0
158
159args=`getopt -o cd:hk:Ko:v -- "$@"`
160eval set -- "$args"
161
162while true; do \
163 case "$1" in
Kenny Root30c11022010-09-21 10:13:19 -0700164 -d) directory=$2; shift 2;;
165 -h) usage; exit 1;;
Kenny Root12ffd9b2010-10-01 12:56:59 -0700166 -k) key=$2; use_crypto=1; shift 2;;
167 -K) prompt_key=1; use_crypto=1; shift;;
Kenny Root30c11022010-09-21 10:13:19 -0700168 -v) verbose=1; shift;;
169 -o) filename=$2; shift 2;;
170 --) shift; break;;
171 *) echo "ERROR: Invalid argument in option parsing! Cannot recover. Ever."; exit 1;;
172 esac
173done
174
175if [ "${directory}x" = "x" -o ! -d "${directory}" ]; then \
176 echo "ERROR: Must specify valid input directory"
177 echo ""
178 usage
179 exit 1;
180fi
181
182if [ "${filename}x" = "x" ]; then \
183 echo "ERROR: Must specify filename"
184 echo ""
185 usage
186 exit 1;
187fi
188
189if [ ${use_crypto} -eq 1 -a "${key}x" = "x" -a 0${prompt_key} -eq 0 ]; then \
190 echo "ERROR: Crypto desired, but no key supplied or requested to prompt for."
191 exit 1
192fi
193
194if [ 0${prompt_key} -eq 1 ]; then \
195 read_key
196fi
197
198outdir=`dirname ${filename}`
199if [ ! -d "${outdir}" ]; then \
200 echo "ERROR: Output directory does not exist: ${outdir}"
201 exit 1
202fi
203
204# Make sure we clean up any stuff we create from here on during error conditions
205trap onexit ERR
206
207tempfile=$(tempfile -d ${outdir}) || ( echo "ERROR: couldn't create temporary file in ${outdir}"; exit 1 )
208
Kenny Root735de3b2010-09-30 14:11:39 -0700209block_count=`du -s --apparent-size --block-size=512 ${directory} | awk '{ print $1; }'`
Kenny Root30c11022010-09-21 10:13:19 -0700210if [ $? -ne 0 ]; then \
211 echo "ERROR: Couldn't read size of input directory ${directory}"
212 exit 1
213fi
214
215echo "Creating temporary file..."
216${DDBIN} if=/dev/zero of=${tempfile} bs=${BLOCK_SIZE} count=$((${block_count} + ${SLOP})) > /dev/null 2>&1
217if [ $? -ne 0 ]; then \
218 echo "ERROR: creating temporary file: $?"
219fi
220
221loop_dev=$(${LOSETUPBIN} -f) || ( echo "ERROR: losetup wouldn't tell us the next unused device"; exit 1 )
222
Kenny Root735de3b2010-09-30 14:11:39 -0700223${LOSETUPBIN} ${loop_dev} ${tempfile} || ( echo "ERROR: couldn't create loopback device"; exit 1 )
224
Kenny Root30c11022010-09-21 10:13:19 -0700225if [ ${use_crypto} -eq 1 ]; then \
Kenny Root735de3b2010-09-30 14:11:39 -0700226 hashed_key=`echo -n "${key}" | md5sum | awk '{ print $1 }'`
227 unique_dm_name=`basename ${tempfile}`
228 echo "0 `blockdev --getsize ${loop_dev}` crypt ${CRYPTO} ${hashed_key} 0 ${loop_dev} 0" | dmsetup create ${unique_dm_name}
229 old_loop_dev=${loop_dev}
230 loop_dev=/dev/mapper/${unique_dm_name}
Kenny Root30c11022010-09-21 10:13:19 -0700231fi
232
233#
234# Create the filesystem
235#
236echo ""
237${MKFSBIN} -I ${loop_dev}
238echo ""
239
240#
241# Make the temporary mount point and mount it
242#
243temp_mount="${MOUNTDIR}/${RANDOM}"
244mkdir ${temp_mount}
245${MOUNTBIN} -t ${FS} -o loop ${loop_dev} ${temp_mount}
246
247#
248# rsync the files!
249#
250echo "Copying files:"
251${RSYNCBIN} -av --no-owner --no-group ${directory}/ ${temp_mount}/
252echo ""
253
254echo "Successfully created \`${filename}'"
255
256#
257# Undo all the temporaries
258#
259umount ${temp_mount}
260rmdir ${temp_mount}
Kenny Root735de3b2010-09-30 14:11:39 -0700261if [ ${use_crypto} -eq 1 ]; then \
262 dmsetup remove -f ${loop_dev}
263 ${LOSETUPBIN} -d ${old_loop_dev}
264else \
265 ${LOSETUPBIN} -d ${loop_dev}
266fi
Kenny Root30c11022010-09-21 10:13:19 -0700267mv ${tempfile} ${filename}
268
269trap - ERR
270
271exit 0