blob: f4cae9a1999f2525d19f072051f7deb10e58769c [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
24CRYPTO=blowfish
25FS=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 \
125 ${LOSETUPBIN} -d ${loop_dev}
126 fi
127 if [ "x${tempfile}" != "x" -a -f "${tempfile}" ]; then \
128 rm -f ${tempfile}
129 fi
130 if [ "x${keyfile}" != "x" -a -f "${keyfile}" ]; then \
131 rm -f ${keyfile}
132 fi
133 echo "Fatal error."
134 exit 1
135}
136
137usage() {
138 echo "mkobb.sh -- Create OBB files for use on Android"
139 echo ""
140 echo " -c Use an encrypted OBB; must specify key"
141 echo " -d <directory> Use <directory> as input for OBB files"
142 echo " -k <key> Use <key> to encrypt OBB file"
143 echo " -K Prompt for key to encrypt OBB file"
144 echo " -o <filename> Write OBB file out to <filename>"
145 echo " -v Verbose mode"
146 echo " -h Help; this usage screen"
147}
148
149find_binaries
150check_prereqs
151
152use_crypto=0
153
154args=`getopt -o cd:hk:Ko:v -- "$@"`
155eval set -- "$args"
156
157while true; do \
158 case "$1" in
159 -c) use_crypto=1; shift;;
160 -d) directory=$2; shift 2;;
161 -h) usage; exit 1;;
162 -k) key=$2; shift 2;;
163 -K) prompt_key=1; shift;;
164 -v) verbose=1; shift;;
165 -o) filename=$2; shift 2;;
166 --) shift; break;;
167 *) echo "ERROR: Invalid argument in option parsing! Cannot recover. Ever."; exit 1;;
168 esac
169done
170
171if [ "${directory}x" = "x" -o ! -d "${directory}" ]; then \
172 echo "ERROR: Must specify valid input directory"
173 echo ""
174 usage
175 exit 1;
176fi
177
178if [ "${filename}x" = "x" ]; then \
179 echo "ERROR: Must specify filename"
180 echo ""
181 usage
182 exit 1;
183fi
184
185if [ ${use_crypto} -eq 1 -a "${key}x" = "x" -a 0${prompt_key} -eq 0 ]; then \
186 echo "ERROR: Crypto desired, but no key supplied or requested to prompt for."
187 exit 1
188fi
189
190if [ 0${prompt_key} -eq 1 ]; then \
191 read_key
192fi
193
194outdir=`dirname ${filename}`
195if [ ! -d "${outdir}" ]; then \
196 echo "ERROR: Output directory does not exist: ${outdir}"
197 exit 1
198fi
199
200# Make sure we clean up any stuff we create from here on during error conditions
201trap onexit ERR
202
203tempfile=$(tempfile -d ${outdir}) || ( echo "ERROR: couldn't create temporary file in ${outdir}"; exit 1 )
204
205block_count=`du --apparent-size --block-size=512 ${directory} | awk '{ print $1; }'`
206if [ $? -ne 0 ]; then \
207 echo "ERROR: Couldn't read size of input directory ${directory}"
208 exit 1
209fi
210
211echo "Creating temporary file..."
212${DDBIN} if=/dev/zero of=${tempfile} bs=${BLOCK_SIZE} count=$((${block_count} + ${SLOP})) > /dev/null 2>&1
213if [ $? -ne 0 ]; then \
214 echo "ERROR: creating temporary file: $?"
215fi
216
217loop_dev=$(${LOSETUPBIN} -f) || ( echo "ERROR: losetup wouldn't tell us the next unused device"; exit 1 )
218
219if [ ${use_crypto} -eq 1 ]; then \
220 keyfile=$(tempfile -d ${outdir}) || ( echo "ERROR: could not create temporary key file"; exit 1 )
221 ${LOSETUPBIN} -p 5 -e ${CRYPTO} ${loop_dev} ${tempfile} 5< ${keyfile} || ( echo "ERROR: couldn't create loopback device"; exit 1 )
222 rm -f ${keyfile}
223else \
224 ${LOSETUPBIN} ${loop_dev} ${tempfile} || ( echo "ERROR: couldn't create loopback device"; exit 1 )
225fi
226
227#
228# Create the filesystem
229#
230echo ""
231${MKFSBIN} -I ${loop_dev}
232echo ""
233
234#
235# Make the temporary mount point and mount it
236#
237temp_mount="${MOUNTDIR}/${RANDOM}"
238mkdir ${temp_mount}
239${MOUNTBIN} -t ${FS} -o loop ${loop_dev} ${temp_mount}
240
241#
242# rsync the files!
243#
244echo "Copying files:"
245${RSYNCBIN} -av --no-owner --no-group ${directory}/ ${temp_mount}/
246echo ""
247
248echo "Successfully created \`${filename}'"
249
250#
251# Undo all the temporaries
252#
253umount ${temp_mount}
254rmdir ${temp_mount}
255${LOSETUPBIN} -d ${loop_dev}
256mv ${tempfile} ${filename}
257
258trap - ERR
259
260exit 0