-
Notifications
You must be signed in to change notification settings - Fork 2
/
vmware-patch.sh
255 lines (224 loc) · 8 KB
/
vmware-patch.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
#!/bin/bash -e
# Source common functions
. /usr/share/vmware-patch/common-functions.sh
# Help message
usage() {
echo "Usage: $(basename $0) [-f|-v|-V|-h]"
echo "Automate the compilation of VMware modules for Arch Linux."
echo
echo "Available options:"
echo " -a, --all Build for all kernels"
echo " -f, --force Force reinstallation, even if modules are already built"
echo " -k, --kernel Select which kernel(s) to build to from menu"
echo " -v, --verbose Use verbose output in patching and vmware-modconfig"
echo " -V, --version Print version information"
echo " -h, --help Print this help"
}
# Flags
while [[ $1 ]]; do
# Can't change $1
opt=$1
# Parse current one
while [[ $opt != - ]]; do
# Define actions
case $opt in
-a* | --all-kernels) all=1 ;;
-f* | --force) force=1 ;;
-k* | --kernel) kernel=1 ;;
-v* | --verbose) verbose=1 ;;
-V* | --version) print_version; exit 0 ;;
-h* | --help) usage; exit 0 ;;
-*) echo "$(basename $0): error: bad argument: $opt"
echo
usage $1; exit 0 ;;
*) break ;;
esac
# Support single dash (vmware-patch -fv)
# ${opt#-:[*]}: Remove first match
nextopt=${opt#-[afkv]}
if [[ $opt != $nextopt ]]; then
# Multiple short flags
opt=-$nextopt
else
# Long form (--force/--verbose)
break
fi
done
shift
done
# Make sure we are root
root_check
# Is a VMware product installed?
vmware_check
# Product name
set_product_name
# Use VMware's bundled libcurl.so.4 to prevent crashes at startup/checking for updates
if [[ $ver != 12.* ]]; then
for script in vmware vmplayer; do
if [[ -f /usr/bin/$script ]]; then
if ! grep -q "libcurl" /usr/bin/$script; then
sed '/$vmmon/a\ export LD_LIBRARY_PATH=/usr/lib/vmware/lib/libcurl.so.4' \
-i /usr/bin/$script
fi
fi
done
fi
# Make sure there's a version in /etc/arch-release for Workstation 9 / Player 5
# https://wiki.archlinux.org/index.php?title=VMware&oldid=274532#2.29_The_vmware-usbarbitrator_binary_is_segfaulting
if [[ $ver = 9.* ]] || [[ $ver = 5.* ]]; then
if [[ ! $(cat /etc/arch-release) ]]; then
msg "Updating /etc/arch-release.."
curl -s https://www.archlinux.org/releng/releases/ | grep -Pom1 'for \K[^"]*' > /etc/arch-release
fi
fi
# Fix VMCI/VSOCK loading
if [[ $ver != 12.* ]] && [[ $ver != 11.* ]] && [[ $ver != 7.* ]]; then
if grep -q '$vsock_alias' /etc/init.d/vmware; then
sed -e 's/mod=$(vmwareRealModName $vmci $vmci_alias)/mod=vmci/' \
-e 's/mod=$(vmwareRealModName $vsock $vsock_alias)/mod=vsock/' \
-i /etc/init.d/vmware
fi
fi
# Remove leftover module locations
remove_leftover_module_dirs
cd /usr/lib/vmware/modules/
# Remove old backups
remove_old_backups
# Available kernels
kernels_all=($(cat /usr/lib/modules/extramodules-*/version))
# Kernel(s) to build to
if [[ ! $all ]]; then
if [[ ! $kernel ]]; then
kernels=$(uname -r)
else
list_kernels
fi
else
kernels=${kernels_all[@]}
fi
# Build for however many kernels specified
for kernel in ${kernels[@]}; do
# Make sure the directory exists
if [[ ! -d /usr/lib/modules/$kernel/ ]]; then
error "/usr/lib/modules/$kernel/ not found. Exiting.."
exit 1
fi
# Support the '-f' flag
# 1) Have we already built (vmnet is built last)?
# 2) Don't check this until we've removed the leftovers
if [[ ! $force ]] && [[ -f /usr/lib/modules/$kernel/misc/vmnet.ko ]]; then
if [[ $verbose ]]; then
msg "Verifying current state.."
fi
error "VMware modules already installed (use '-f' to override). Exiting.."
exit 1
fi
# Unload conflicting in-kernel modules in less than Workstation 11 / Player (Pro) 7
if [[ $ver != 12.* ]] && [[ $ver != 11.* ]] && [[ $ver != 7.* ]]; then
rmmod "vsock" "vmw_vsock_vmci_transport" "vmw_vmci" 2>/dev/null || true
fi
# Detect applicable patches (/usr/lib/vmware/modules/patches/[mod]-[ver]-[kernel].patch)
unset patches
for patch in patches/*; do
# Some variables
ver_patch=$(echo $patch | cut -d "-" -f2)
kernel_patch=$(echo $patch | grep -Po ".*-\K\d+\.\d+")
kernel_major=$(echo $kernel | cut -d "." -f-2)
# Sync VMware Player (Pro / Plus) version by incrementing by 4
ver2=$ver
if [[ $name =~ Player ]] && [[ $ver != 12.* ]]; then
major=$(( ${ver/.*} + 4 ))
ver2=$major.${ver#*.}
fi
# Is product version not lower and kernel version not higher in patch name?
if (( $(vercmp "$ver_patch" "$ver2") >= 0 )) && (( $(vercmp "$kernel_patch" "$kernel_major") <= 0 )); then
patches+=("$patch")
fi
done
# Patch
# 1) Make sure we can build
# 2) &>/dev/null: hide all output (STDIN/STDERR)
msg "Patching $name v$ver for kernel $kernel.."
if [[ $patches ]]; then
# Create a backup/Revert
if [[ ! -d source-$ver ]]; then
msg2_yellow "Backing up.."
cp -r source/ "source-$ver/"
else
# Get the original sources from the backup (invalidate the need for 'vmware-unpatch')
cp "source-$ver/"* source/
fi
# cd in place
cd source
# Loop modules that require patching (vmci, vmmon, vmnet and/or vsock)
# sort -u: prevent duplicate entries
for mod in $(echo ${patches[@]} | grep -Po "s/\K[^-]*" | sort -u); do
# Print name
msg2 "[$mod]"
# Untar
if [[ $verbose ]]; then
msg3 "Extracting archives.."
fi
tar -xf "$mod.tar"
# Loop through applicable patches
# printf '%s\n': print ${patches[@]} in separate lines for grepping
for patch in $(printf '%s\n' "${patches[@]}" | grep "$mod"); do
# Patch
if ! patch_sources; then
error "Failed to apply '$(basename "$patch")'"
read_msg2 "Continue? (Y/n) "
if [[ $REPLY != [Yy] ]]; then
# Revert
msg "Reverting.."
cd ..
rm -r source/
mv "source-$ver/" source/
# Exit
msg2 "Done."
exit 1
fi
fi
done
# Tar patched modules
if [[ $verbose ]]; then
msg3 "Recreating archives.."
fi
tar -cf "$mod.tar" "$mod-only"
# Leftovers
rm -r "$mod-only"
done
# Return
cd ..
else
msg2 "No patching required.."
fi
# Install
msg "Installing modules.."
if [[ $verbose ]]; then
# Run vmware-modconfig
if ! vmware-modconfig --console --install-all -k "$kernel"; then
# See logs
if ls /tmp/vmware-root/vmware-[0-9]*.log &>/dev/null; then
error "Unable to build. See:"
print_logs
else
error "Unable to build. See logs in /tmp/vmware-root/"
fi
else
msg2 "Done."
fi
else
# Run vmware-modconfig
if ! vmware-modconfig --console --install-all -k "$kernel" &>/dev/null; then
# See logs
if ls /tmp/vmware-root/vmware-*.log &>/dev/null; then
error "Unable to build. Re-run with '-v' (--verbose) or see:"
print_logs
else
error "Unable to build. See logs in /tmp/vmware-root/"
fi
else
msg2 "Done."
fi
fi
done