Commit | Line | Data |
---|---|---|
d8b9a3d7 MW |
1 | #! /bin/sh |
2 | ### | |
3 | ### Fetch an archive, and unpack it into a directory in a safe manner. | |
4 | ||
5 | set -e | |
6 | ||
7 | ## Parse the command line. | |
8 | case $# in | |
9 | 3) ;; | |
10 | *) echo >&2 "usage: $0 DIR LABEL URL"; exit 1 ;; | |
11 | esac | |
12 | dir=$1 label=$2 url=$3 | |
13 | cd "$dir" | |
14 | ||
15 | ## Fetch the archive. | |
16 | rm -rf tmp; mkdir tmp | |
17 | curl -s -o tmp/"$label.tar.gz" "$url" | |
18 | ||
19 | ## Check the archive for unpleasantness. The GNU and FreeBSD versions of | |
20 | ## tar(1) do something vaguely sensible with `..' components in the pathnames | |
21 | ## of archive members. (Specifically, FreeBSD simply ignores the affected | |
22 | ## members; GNU strips leading components in a bizarre way.) But OpenBSD | |
23 | ## gets a special security award for cheerily following the `..' components. | |
24 | ## So we have to do this complicated laundering thing. | |
25 | ## | |
26 | ## The archive ought to unpack everything into a single directory and not | |
27 | ## contain anythig weird. So check. Actually, this won't catch newlines in | |
28 | ## member names, so we'll have to be careful about those. The regular | |
29 | ## expression insists that everything be in a single directory identified by | |
30 | ## the LABEL, and that the rest of the name contains no two adjacent dots. | |
31 | ## We use the LABEL as part of an ERE, so it ought not contain bad things. | |
32 | if | |
33 | tar tzf tmp/"$label.tar.gz" | | |
34 | grep -Ev "^$label/([^.]+|\.[^.])*$" >&2 | |
35 | then | |
36 | echo >&2 "$0: archive has bad member pathnames" | |
37 | exit 1 | |
38 | fi | |
39 | ||
40 | ## Unpack the archive now that we know it's safe. | |
41 | (cd tmp; tar xzf "$label.tar.gz") | |
42 | ||
43 | ## Replace any existing tree with the new one. | |
44 | rm -rf "$label" | |
45 | mv tmp/"$label" . | |
46 | rm -rf tmp |