OLD | NEW |
1 #!/bin/bash | 1 #!/bin/bash |
2 | 2 |
3 # Copyright (c) 2009 The Chromium OS Authors. All rights reserved. | 3 # Copyright (c) 2009 The Chromium OS Authors. All rights reserved. |
4 # Use of this source code is governed by a BSD-style license that can be | 4 # Use of this source code is governed by a BSD-style license that can be |
5 # found in the LICENSE file. | 5 # found in the LICENSE file. |
6 | 6 |
7 # This script can be used to replace the "dpkg" binary as far as the | 7 # This script can be used to replace the "dpkg" binary as far as the |
8 # "apt-get install" command is concerned. When "apt-get install foo" | 8 # "apt-get install" command is concerned. When "apt-get install foo" |
9 # runs it will make two calls to dpkg like: | 9 # runs it will make two calls to dpkg like: |
10 # dpkg --status-fd ## --unpack --auto-deconfigure /path/to/foo.deb | 10 # dpkg --status-fd ## --unpack --auto-deconfigure /path/to/foo.deb |
11 # dpkg --status-fd ## --configure foo | 11 # dpkg --status-fd ## --configure foo |
12 # This script will extract the .deb file and make it appear to be installed | 12 # This script will extract the .deb file and make it appear to be installed |
13 # successfully. It will skip the maintainer scripts and configure steps. | 13 # successfully. It will skip the maintainer scripts and configure steps. |
14 # | 14 # |
15 # As a one-off test, you can run like: | 15 # As a one-off test, you can run like: |
16 # apt-get -o="Dir::Bin::dpkg=/path/to/this" install foo | 16 # apt-get -o="Dir::Bin::dpkg=/path/to/this" install foo |
17 | 17 |
18 # Load common constants. This should be the first executable line. | 18 # Load common constants. This should be the first executable line. |
19 # The path to common.sh should be relative to your script's location. | 19 # The path to common.sh should be relative to your script's location. |
20 . "$(dirname "$0")/common.sh" | 20 . "$(dirname "$0")/common.sh" |
21 | 21 |
22 # Flags | 22 # Flags |
23 DEFINE_string root "" \ | 23 DEFINE_string root "" \ |
24 "The target rootfs directory in which to install packages." | 24 "The target rootfs directory in which to install packages." |
| 25 DEFINE_boolean dpkg_fallback $FLAGS_TRUE \ |
| 26 "Run normal dpkg if maintainer scripts are not whitelisted." |
25 DEFINE_string status_fd "" \ | 27 DEFINE_string status_fd "" \ |
26 "The file descriptor to report status on; ignored." | 28 "The file descriptor to report status on; ignored." |
27 DEFINE_boolean unpack $FLAGS_FALSE "Is the action 'unpack'?" | 29 DEFINE_boolean unpack $FLAGS_FALSE "Is the action 'unpack'?" |
28 DEFINE_boolean configure $FLAGS_FALSE "Is the action 'configure'?" | 30 DEFINE_boolean configure $FLAGS_FALSE "Is the action 'configure'?" |
29 DEFINE_boolean remove $FLAGS_FALSE "Is the action 'remove'?" | 31 DEFINE_boolean remove $FLAGS_FALSE "Is the action 'remove'?" |
30 DEFINE_boolean auto_deconfigure $FLAGS_FALSE "Ignored" | 32 DEFINE_boolean auto_deconfigure $FLAGS_FALSE "Ignored" |
31 DEFINE_boolean force_depends $FLAGS_FALSE "Ignored" | 33 DEFINE_boolean force_depends $FLAGS_FALSE "Ignored" |
32 DEFINE_boolean force_remove_essential $FLAGS_FALSE "Ignored" | 34 DEFINE_boolean force_remove_essential $FLAGS_FALSE "Ignored" |
33 | 35 |
34 # Fix up the command line and parse with shflags. | 36 # Fix up the command line and parse with shflags. |
35 FIXED_FLAGS="$@" | 37 FIXED_FLAGS="$@" |
36 FIXED_FLAGS=${FIXED_FLAGS/status-fd/status_fd} | 38 FIXED_FLAGS=${FIXED_FLAGS/status-fd/status_fd} |
37 FIXED_FLAGS=${FIXED_FLAGS/auto-deconfigure/auto_deconfigure} | 39 FIXED_FLAGS=${FIXED_FLAGS/auto-deconfigure/auto_deconfigure} |
38 FIXED_FLAGS=${FIXED_FLAGS/force-depends/force_depends} | 40 FIXED_FLAGS=${FIXED_FLAGS/force-depends/force_depends} |
39 FIXED_FLAGS=${FIXED_FLAGS/force-remove-essential/force_remove_essential} | 41 FIXED_FLAGS=${FIXED_FLAGS/force-remove-essential/force_remove_essential} |
40 FLAGS $FIXED_FLAGS || exit 1 | 42 FLAGS $FIXED_FLAGS || exit 1 |
41 eval set -- "${FLAGS_ARGV}" | 43 eval set -- "${FLAGS_ARGV}" |
42 | 44 |
43 # Die on any errors. | 45 # Die on any errors. |
44 set -e | 46 set -e |
45 | 47 |
46 if [ $FLAGS_configure -eq $FLAGS_TRUE ]; then | 48 # Returns true if the input file is whitelisted. |
47 # We ignore configure requests. | 49 # |
48 exit 0 | 50 # $1 - The file to check |
49 fi | 51 is_whitelisted() { |
50 if [ $FLAGS_remove -eq $FLAGS_TRUE ]; then | 52 local whitelist="${SRC_ROOT}/package_scripts/package.whitelist" |
51 # We log but ignore remove requests. | 53 test -f "$whitelist" || return |
52 echo "dpkg_no_scripts, remove: $@" | 54 |
53 exit 0 | 55 local checksum=$(md5sum "$1" | awk '{ print $1 }') |
54 fi | 56 local count=$(grep -c "$checksum" "${whitelist}" || /bin/true) |
55 if [ $FLAGS_unpack -ne $FLAGS_TRUE ]; then | 57 test $count -ne 0 |
56 # Ignore unknown command line. | 58 } |
57 echo "Unexpected command line: $@" | 59 |
58 exit 0 | 60 # Returns true if either of the two given files exist and are not whitelisted. |
59 fi | 61 # |
| 62 # $1 - The package name. |
| 63 # $2 - The path to the preinst file if it were to exist. |
| 64 # $3 - The path to the postinst file if it were to exist. |
| 65 has_missing_whitelist() { |
| 66 local package=$1 |
| 67 local preinst=$2 |
| 68 local postinst=$3 |
| 69 local missing_whitelist=0 |
| 70 |
| 71 if [ -f "$preinst" ]; then |
| 72 if ! is_whitelisted "$preinst"; then |
| 73 missing_whitelist=1 |
| 74 echo "Warning: Missing whitelist entry for ${package}.preinst" |
| 75 fi |
| 76 fi |
| 77 if [ -f "$postinst" ]; then |
| 78 if ! is_whitelisted "$postinst"; then |
| 79 missing_whitelist=1 |
| 80 echo "Warning: Missing whitelist entry for ${package}.postinst" |
| 81 fi |
| 82 fi |
| 83 test $missing_whitelist -ne 0 |
| 84 } |
| 85 |
| 86 do_configure() { |
| 87 local dpkg_info="$FLAGS_root/var/lib/dpkg/info/" |
| 88 local fallback_packages="" |
| 89 |
| 90 for p in "$@"; do |
| 91 echo "Configuring: $p" |
| 92 |
| 93 # Make sure that any .preinst or .postinst files are whitelisted. |
| 94 local preinst="${dpkg_info}/${p}.preinst" |
| 95 local postinst="${dpkg_info}/${p}.postinst" |
| 96 if has_missing_whitelist "$p" "$preinst" "$postinst"; then |
| 97 if [ $FLAGS_dpkg_fallback -eq $FLAGS_TRUE ]; then |
| 98 echo "** Warning: Will run full maintainer scripts for ${p}." |
| 99 fallback_packages="$fallback_packages $p" |
| 100 continue |
| 101 else |
| 102 # TODO: Eventually should be upgraded to a full error. |
| 103 echo "** Warning: Ignoring missing whitelist for ${p}." |
| 104 fi |
| 105 fi |
| 106 |
| 107 # Run our maintainer script for this package if we have one. |
| 108 local chromium_postinst="${SRC_ROOT}/package_scripts/${p}.postinst" |
| 109 if [ -f "$chromium_postinst" ]; then |
| 110 echo "Running: $chromium_postinst" |
| 111 ROOT="$FLAGS_root" SRC_ROOT="$SRC_ROOT" sh -x $chromium_postinst |
| 112 fi |
| 113 done |
| 114 |
| 115 if [ -n "$fallback_packages" ]; then |
| 116 dpkg --root="$FLAGS_root" --configure $fallback_packages |
| 117 fi |
| 118 } |
| 119 |
| 120 do_unpack() { |
| 121 local dpkg_status="$FLAGS_root/var/lib/dpkg/status" |
| 122 local dpkg_info="$FLAGS_root/var/lib/dpkg/info/" |
| 123 |
| 124 for p in "$@"; do |
| 125 local package=$(dpkg-deb --field "$p" Package) |
| 126 local tmpdir=$(mktemp -d) |
| 127 |
| 128 dpkg-deb --control "$p" "$tmpdir" |
| 129 |
| 130 local preinst="${tmpdir}/preinst" |
| 131 local postinst="${tmpdir}/postinst" |
| 132 if has_missing_whitelist "$package" "$preinst" "$postinst"; then |
| 133 if [ $FLAGS_dpkg_fallback -eq $FLAGS_TRUE ]; then |
| 134 echo "** Warning: Running full maintainer scripts for ${package}." |
| 135 dpkg --root="$FLAGS_root" --unpack --auto-deconfigure "$p" |
| 136 rm -rf "$tmpdir" |
| 137 continue |
| 138 else |
| 139 # TODO: Eventually should be upgraded to a full error. |
| 140 echo "** Warning: Ignoring missing whitelist for ${p}." |
| 141 fi |
| 142 fi |
| 143 |
| 144 # Copy the info files |
| 145 local files=$(ls "$tmpdir" | grep -v control) |
| 146 for f in $files; do |
| 147 cp "${tmpdir}/${f}" "${dpkg_info}/${package}.${f}" |
| 148 done |
| 149 touch "${dpkg_info}/${package}.list" # TODO: Proper .list files. |
| 150 |
| 151 # Mark the package as installed successfully. |
| 152 echo "Status: install ok installed" >> "$dpkg_status" |
| 153 cat "${tmpdir}/control" >> "$dpkg_status" |
| 154 echo "" >> "$dpkg_status" |
| 155 |
| 156 rm -rf "$tmpdir" |
| 157 |
| 158 # Run our maintainer script for this package if we have one. |
| 159 local chromium_postinst="${SRC_ROOT}/package_scripts/${package}.preinst" |
| 160 if [ -f "$chromium_preinst" ]; then |
| 161 echo "Running: ${chromium_preinst}" |
| 162 ROOT="$FLAGS_root" SRC_ROOT="$SRC_ROOT" $chromium_preinst |
| 163 fi |
| 164 |
| 165 echo "Unpacking: $p" |
| 166 dpkg-deb --extract "$p" "$FLAGS_root" |
| 167 done |
| 168 } |
| 169 |
| 170 # This script requires at least "--root=" |
60 if [ -z "$FLAGS_root" ]; then | 171 if [ -z "$FLAGS_root" ]; then |
61 echo "Missing root directory." | 172 echo "dpkg_no_scripts: Missing root directory." |
62 exit 0 | 173 exit 1 |
63 fi | 174 fi |
64 | 175 |
65 DPKG_STATUS="" | 176 if [ $FLAGS_configure -eq $FLAGS_TRUE ]; then |
66 if [ -d "$FLAGS_root/var/lib/dpkg" ]; then | 177 do_configure $@ |
67 DPKG_STATUS="$FLAGS_root/var/lib/dpkg/status" | 178 elif [ $FLAGS_unpack -eq $FLAGS_TRUE ]; then |
68 DPKG_INFO="$FLAGS_root/var/lib/dpkg/info/" | 179 do_unpack $@ |
| 180 elif [ $FLAGS_remove -eq $FLAGS_TRUE ]; then |
| 181 # We log but ignore remove requests. |
| 182 echo "Ignoring remove: $@" |
| 183 else |
| 184 echo "dpkg_no_scripts.sh: Unknown or missing command." |
| 185 exit 1 |
69 fi | 186 fi |
70 | 187 |
71 for p in "$@"; do | 188 exit 0 |
72 echo "Extracting $p" | |
73 dpkg-deb --extract "$p" "$FLAGS_root" | |
74 | |
75 if [ -n "$DPKG_STATUS" ]; then | |
76 TMPDIR=$(mktemp -d) | |
77 dpkg-deb --control "$p" "$TMPDIR" | |
78 | |
79 # Copy the info files | |
80 PACKAGE=$(dpkg-deb --field "$p" Package) | |
81 FILES=$(ls "$TMPDIR" | grep -v control) | |
82 for f in $FILES; do | |
83 cp "${TMPDIR}/$f" "${DPKG_INFO}/$PACKAGE.$f" | |
84 done | |
85 touch "${DPKG_INFO}/$PACKAGE.list" | |
86 | |
87 # Mark the package as installed successfully. | |
88 echo "Status: install ok installed" >> "$DPKG_STATUS" | |
89 cat "${TMPDIR}/control" >> "$DPKG_STATUS" | |
90 echo "" >> "$DPKG_STATUS" | |
91 | |
92 rm -rf "$TMPDIR" | |
93 fi | |
94 done | |
OLD | NEW |