3
# This script is used to compare the images to spot differences
14
Compare two images. Example:
15
./img-diff old.img new.img
20
error() { echo "$@" 1>&2; }
22
[ -z "${old_loop_dm}" ] || { umount "${old_mp}" ; kpartx -d "${old_loop}"; }
23
[ -z "${new_loop_dm}" ] || { umount "${new_mp}" ; kpartx -d "${new_loop}"; }
24
[ -z "${old_loop}" ] || { losetup -d "${old_loop}"; }
25
[ -z "${new_loop}" ] || { losetup -d "${new_loop}"; }
27
rm -rf ${old_mp} ${new_mp}
41
[ ! -z "${oldimg}" ] || useage
42
[ ! -z "${newimg}" ] || useage
43
[ "${oldimg}" != "${newimg}" ] || fail "Images must be different"
44
[ -e "$oldimg" ] || fail "${oldimg} must exist"
45
[ -e "$newimg" ] || fail "${newimg} must exist"
46
[ "${EUID}" = 0 ] || fail "This program must run as root"
48
working_old_img="${oldimg}"
49
working_new_img="${newimg}"
51
# Convert the image into something usable
52
if [ $( file ${oldimg} | awk '/Qemu Image/ {print$NF}' ) -eq "2" ]; then
53
echo "Converting ${oldimg} to ${oldimg}.raw "
54
qemu-img convert -O raw ${oldimg} ${oldimg}.raw
55
working_old_img="${oldimg}.raw"
56
elif [ $( file ${oldimg} | awk '/VMware/ {print$2}' ) = "VMware4" ]; then
57
echo "Converting ${oldimg} to ${oldimg}.raw "
58
vboxmange clonehd -O raw ${oldimg} ${oldimg}.raw
59
working_old_img="${oldimg}.raw"
61
working_old_img="${oldimg}"
64
if [ $( file ${newimg} | awk '/Qemu Image/ {print$NF}' ) -eq "2" ]; then
65
echo "Converting ${newimg} to ${newimg}.raw "
66
qemu-img convert -O raw ${newimg} ${newimg}.raw
67
working_new_img="${newimg}.raw"
68
elif [ $( file ${newimg} | awk '/VMware/ {print$2}' ) = "VMware4" ]; then
69
echo "Converting ${newimg} to ${newimg}.raw "
70
vboxmanage clonehd --format RAW ${newimg} ${newimg}.raw
71
working_new_img="${newimg}.raw"
73
working_new_img="${newimg}"
77
echo "Setting up device mapper for ${working_old_img}"
78
kpartx -a "${working_old_img}" || fail "unable to add device mapping for ${working_old_img}"
79
old_loop=$( kpartx -l "${working_old_img}" | head -n1 | awk '{print$5}' ) || fail "unable to determine loop device for ${working_old_img}"
80
old_loop_dm="/dev/mapper/$(kpartx -l "${working_old_img}" | head -n1 | awk '{print$1}')" || fail "unable to determine DM loop for ${working_old_img}"
81
echo " setup on ${old_loop}"
82
echo " device mapper setup on ${old_loop_dm}"
84
echo "Setting up device mapper for ${working_new_img}"
85
kpartx -a "${working_new_img}" || fail "unable to add device mapping for ${working_new_img}"
86
new_loop=$( kpartx -l "${working_new_img}" | head -n1 | awk '{print$5}' ) || fail "unable to determine loop device for ${working_new_img}"
87
new_loop_dm="/dev/mapper/$(kpartx -l "${working_new_img}" | head -n1 | awk '{print$1}')" || fail "unable to determine DM loop for ${working_new_img}"
88
echo " setup on ${new_loop}"
89
echo " device mapper setup on ${new_loop_dm}"
91
# Determine the image labels
92
old_label=$(blkid "${old_loop_dm}" | awk '/LABEL/ {print$2}') || error "Unable to determine label for ${old_loop_dm}"
93
new_label=$(blkid "${new_loop_dm}" | awk '/LABEL/ {print$2}') || error "Unable to determine label for ${new_loop_dm}"
95
echo "Old Image Label: ${old_label}"
96
echo "New Image Label: ${new_label}"
99
[ -e "${old_loop_dm}" ] || fail "unable to find ${old_loop_dm}"
100
[ -e "${new_loop_dm}" ] || fail "unable to find ${new_loop_dm}"
102
mount "${old_loop_dm}" "${old_mp}" || fail "unable to mount ${old_loop_dm}"
103
mount "${new_loop_dm}" "${new_mp}" || fail "unable to mount ${new_loop_dm}"
110
exclude='egrep -v "/lib/modules|/usr/share|/var/log|/lib/firmware|/var/lib/dpkg|/var/cache/man|/var/cache/apt"'
113
# Calculate the differences
116
echo "Calculating for $what image"
119
new) md5="${new_md5}"; perms="${new_perms}"; pkgs="${new_pkgs}"; mp="${new_mp}" ;;
120
old) md5="${old_md5}"; perms="${old_perms}"; pkgs="${old_pkgs}"; mp="${old_mp}" ;;
124
chroot "${mp}" sh -c 'find . -type f | xargs md5sum 2>/dev/null | sort -k2' | $exclude > "${md5}" ||
125
error "Unable to calculate MD5 for old image"
127
printf "...permissions"
128
chroot "${mp}" find . -type f -printf "%h/%f\t\t %M\n" 2> /dev/null | $exclude | sort -k1 > "${perms}" ||
129
error "Unable to report file persmissions for old image"
132
chroot "${mp}" dpkg-query -W --showformat='${Package} ${Version}\n' > "${pkgs}" ||
133
error "Unable to report packages installed on old image"
139
echo -e "\nPackage Diff"
140
diff "${old_pkgs}" "${new_pkgs}"
142
echo -e "\n\nPermissions Diff"
143
diff "${old_perms}" "${new_perms}"
145
echo -e "\n\nFile System Diff"
146
echo -e "\nOLD versus NEW"
147
diff "${old_md5}" "${new_md5}"
156
divline="_______________________________________________________________________________"
157
minline="-------------------------------------------------------------------------------"
158
for f in $( diff "${old_md5}" "${new_md5}" | grep "./" | awk '{print$3}' | sort | uniq ); do
159
[ ! -e "${old_mp}/${f}" -a -e "${new_mp}/$f" ] && { newfiles="${newfiles}\n$f"; continue; }
160
[ ! -e "${new_mp}/${f}" -a -e "${old_mp}/$f" ] && { missing="${missing}\n$f"; continue; }
162
comment="BEGIN DIFF of OLD to NEW ${f}"
163
[ -e "${old_mp}/${f}" -o -e "${new_mp}/${f}" ] || continue
164
diff_comment="$(diff -u ${old_mp}/${f} ${new_mp}/${f})"
166
[ $(expr match "${diff_comment}" "Binary files") -ne "0" ] && { binary="${binary}\n${f}"; continue; } ||
167
{ comment="${comment}\n${diff_comment}\nEND DIFF of ${f}\n${minline}\n"; compared="${compared}\n${comment}"; changed="${changed}\n${f}"; }
170
echo -e "${divline}\nNEW FILES added to NEW IMAGE\n${newfiles}\n\n"
171
echo -e "${divline}\nMISSING FILES from OLD to NEW \n${missing}\n\n"
172
echo -e "${divline}\nSIMPLE LIST OF CHANGED\n${changed}\n\n"
173
echo -e "${divline}\nBINARY UNDIFFED \n${binary}\n\n"
174
echo -e "${divline}\nDIFFED \n${compared}"
180
rm -rf "${old_pkgs}" "${new_pkgs}" "${new_md5}" "${old_md5}" "${old_mp}" "${new_mp}" "${old_perms}" "${new_perms}"