setup-bootable.in 6.22 KB
Newer Older
1
2
#!/bin/sh

3
prog=${0##*/}
4
version=@VERSION@
5

6
cleanup() {
7
	cd /
8
	if [ -n "$uninstalls" ]; then
9
10
		apk del -q syslinux
	fi
11
12
	if [ -n "$umounts" ]; then
		umount $umounts
13
14
15
16
17
18
19
20
21
	fi
}

die() {
	echo "$@" >&2
	cleanup
	exit 1
}

22
23
24
25
26
27
28
29
30
31
32
33
34
35
# find device for mountpoint
find_dev() {
	local mnt="${1%/}" # strip trailing /
	awk "\$2 == \"$mnt\" {print \$1}" /proc/mounts
}

# check if given device is on usb bus
on_usb_bus() {
	local dev="$1"
	[ -e /sys/block/$dev ] || return 1
	local sysdev=$(readlink -f /sys/block/$dev/device)
	test "${sysdev##*/usb[0-9]}" != "$sysdev"
}

36
37
38
39
40
41
42
43
44
45
46
# mount source as loopback and set srcdir
mount_srcdir() {
	local srcmnt=${MNT:-/mnt}
	mount -o loop -t iso9660 "$src" $srcmnt \
		|| die "Failed to mount loopback $src"
	umounts="$srcmnt"
	srcdir="$srcmnt"
	if ! [ -f "$srcdir"/.alpine-release ]; then
		die "No .alpine-release found on image $src"
	fi
}
47

48
49
usage() {
	cat <<__EOF__
50
$prog $version
51
usage: $prog [-hu] SOURCE [DEST]
52

53
54
55
Copy the contents of SOURCE to DEST and make DEST bootable.

SOURCE can be a directory or a ISO image. DEST can be a mounted directory 
56
or a device. If DEST is ommitted /media/usb will be used.
57
58

Options:
59
60
 -f  Force overwrite existing files. Will overwrite syslinux.cfg if upgrade.
 -h  Show this help.
61
62
 -k  Keep current alpine_dev in syslinux.cfg. Without this it will be replaced
     with the UUID.
63
64
 -u  Upgrade mode. Keep existing syslinux.cfg and don't run syslinux.
 -s  Force run syslinux, even if upgrade mode.
65
66
67
68
69
 -v  Verbose mode. Display whats going on.

__EOF__
	exit 1
}
70

71
while getopts "fhkusv" opt; do
72
	case "$opt" in
73
74
	f) force=1;;
	h) usage;;
75
	k) keep_alpine_dev=1;;
76
77
78
	u) upgrade=1;;
	s) syslinux=1;;
	v) verbose=1;;
79
80
	esac
done
81

82
shift $(($OPTIND - 1))
83

84
src=${1}
85
86
dest=${2:-/media/usb}

87

88
89
[ -z "$src" ] && usage

90
91
srcdir=
# Find the srcdir or srcurl. mount loopback if needed
92
if [ -f "$src"/.alpine-release ]; then
93
	srcdir="`echo $src | sed -r 's,/$,,'`"
94
else
95
96
97
98
99
100
101
102
	case "$src" in
	http://*|ftp://*) srcurl="$src";;
	*) mount_srcdir;;
	esac
fi

if [ -n "$srcdir" ]; then
	to_version=$(cat "$srcdir"/.alpine-release)
103
104
105
106
fi

# find target device
if [ -d "$dest" ]; then
107
	dest=${dest%/} # strip trailing /
108
109
110
111
112
	if ! awk '{print $2}' /proc/mounts | grep -q "^$dest\$"; then
		mount "$dest" || die "Failed to mount $dest"
		umounts="$umounts $dest"
	fi
	destdir="$dest"
113
	dest=$(find_dev "$destdir")
114
115
116
117
elif [ -b "$dest" ]; then
	destdir="/media/${dest##*/}"
	mkdir -p "$destdir"
	mount "$dest" "$destdir" || die "Failed to mount $dest on $destdir"
118
	umounts="$umounts $destdir"
119
fi
120

121
122
123
# fish out label, uuid and type
eval $(blkid $dest | cut -d: -f2-)

124
125
126
127
128
129
130
131
132
[ -n "$verbose" ] && echo "Using $dest as target (mounted on $destdir)"


# find parent device (i.e sda)
dev="$dest"
while [ -L "$dev" ]; do
	dev=$(readlink -f $dev)
done
parent_dev=/dev/$(basename $(dirname /sys/block/*/$(basename $dev)))
133

134
135
136
137
138
139
140
# check if this files exist and not in upgrade mode
if [ -z "$upgrade" ] && [ -z "$force" ]; then
	for i in boot apks syslinux.cfg .alpine-release; do
		[ -e "$destdir"/$i ] && die "$destdir/$i already exists. Aborting"
	done
fi

141
142
143
# check if its same version
if [ -n "$upgrade" ] && [ -e "$destdir"/.alpine-release ]; then
	from_version=$(cat "$destdir"/.alpine-release)
144
	if [ -z "$force" ] && [ -n "$to_version" ] && [ "$from_version" = "$to_version" ]; then
145
146
147
148
149
150
151
152
153
154
155
		die "Source and target seems to have same version ($from_version). Aborting."
	fi
fi

# Display what versions we are installing/upgrading
if [ -n "$from_version" ]; then
	echo "Upgrading $dest from $from_version to $to_version"
else
	echo "Copying $to_version to $dest (mounted on $destdir)"
fi

156
157
# remove partial upgrades if any.
rm -rf "$destdir"/.new "$destdir"/.old
158
mkdir -p "$destdir"/.new || die "Failed to create $destdir/.new"
159
160

# check that we have the space we need
161
162
163
164
165
166
167
# we calculate on MB since shell arthimetic gets problems with big disks
# and bytes.
free_blocks=$(stat -f -c "%f" "$destdir")
block_size=$(stat -f -c "%s" "$destdir")
blocks_per_mb=$(( 1024 * 1024 / $block_size))
available_space=$(( $free_blocks / $blocks_per_mb ))
[ -n "$verbose" ] && echo "Available space: $available_space MiB"
168

169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
if [ -n "$srcdir" ]; then
	needed_space=$(cd "$srcdir" && du -m -s -c boot apks syslinux.cfg .alpine-release | awk '$2 == "total" {print $1}')
	[ -n "$verbose" ] && echo "Needed space:    $needed_space MiB"
	[ $available_space -lt $needed_space ] \
		&& die "Not enough space on $destdir. Aborting."

	# copy the files to .new
	for i in boot apks syslinux.cfg .alpine-release; do
		[ -n "$verbose" ] && echo "Copying $srcdir/$i to $destdir/.new/"
		cp -a "$srcdir"/$i "$destdir"/.new/
	done
elif [ -n "$srcurl" ]; then
	cd "$destdir"/.new
	${WGET:-wget} -O - "$srcurl" | uniso \
		|| die "Failed to download or extract $srcurl"
fi
185
186

# make sure files are really there before we replace existing
187
[ -n "$verbose" ] && echo "Flushing cache..."
188
189
sync

190
[ -n "$verbose" ] && echo "Replacing existing files..."
191
192
193
194
195
196
mkdir -p "$destdir"/.old || die "Failed to create $destdir/.old"

# do we want keep existing syslinux.cfg?
tomove="boot apks .alpine-release"
if [ -n "$force" ] || ! [ -e "$destdir"/syslinux.cfg ]; then
	tomove="$tomove syslinux.cfg"
197
198
199
200
201
202
203
	# update syslinux.cfg unless device is on usb bus
	# this is so we can boot from CF's and harddisk 
	if ! on_usb_bus $parent_dev; then
		[ -n "$verbose" ] && echo "Updating syslinux.cfg to use $dest"
		sed -i -e "s/usbdisk/${dest##*/}/g" \
			"$destdir"/.new/syslinux.cfg
	fi
204
205
fi

206
207
208
209
210
211
212
213
214
215
216
217
# move current files to .old
for i in $tomove; do
	if [ -e "$destdir"/$i ]; then
		mv "$destdir"/$i "$destdir"/.old/ || die "Failed to move $destdir/$i to $destdir/.old/"
	fi
done

# move .new to current
for i in $tomove; do
	mv "$destdir"/.new/$i "$destdir"/ || die "Failed to move $destdir/.new/ to $destdir"
done

218
if [ -z "$keep_alpine_dev" ] && [ -n "$UUID" ]; then
219
	sed -i -e "s/alpine_dev=[^ \t:]\+/alpine_dev=UUID=$UUID/" \
220
221
222
		"$destdir"/syslinux.cfg
fi

223
224
225
226
227
# cleanup
[ -z "$keep_old" ] && rm -rf "$destdir"/.old "$destdir"/.new
sync

# If we only copy then we are done.
228
if [ -n "$upgrade" ] && [ -z "$syslinux" ]; then
229
230
231
	cleanup
	exit 0
fi
232

233
234
235
echo "Making $dest bootable..."

if ! [ -x "$(which syslinux)" ]; then
236
237
238
	apk add -q syslinux || die "Failed to install syslinux"
	uninstalls="syslinux"
fi
239

240
syslinux $dest
241

242
243
if [ -b $parent_dev ]; then
	dd if=/usr/share/syslinux/mbr.bin of=$parent_dev
244
else
245
	echo "Warning: Could not find the parent device for $dest"
246
247
248
fi

cleanup
249
sync