ea0de33aa466ba0d2789808c156929fc16d30d88
[etcdiff.git] / etcdiff.sh
1 #!/bin/sh
2 #
3 # Version 0.2
4 #
5 # etcdiff (deb-etcdiff?) shows how your current /etc dir
6 # diverges from the debian distribution standard one.
7 #
8 # Copyright (C) 2008,2009 Antonio Ospite <ospite@studenti.unina.it>
9 # License: GPLv2 or later
10
11
12 # TODO:
13 #   Add per package etcdiff, using dpkg -L
14 #   Add per distro etcdiff using dpkg --get-selections
15 #
16 # Note that the first method can't consider files not in original packages,
17 # unless some smart trick is used (new files could be in same /etc subdir of
18 # the provided configuration files)
19 #
20 # The second one could even speedup the whole etcdiffing by recreating an etc
21 # dir as per packages defaults, and do one big diff.
22
23 set -x
24
25 #PROMPT_RM=-i
26
27 DEBIANMIRROR="http://ftp.it.debian.org/debian"
28
29 rm $PROMPT_RM -rf temp     && mkdir temp
30 rm $PROMPT_RM -rf archives && mkdir archives
31 rm $PROMPT_RM -rf conf     && mkdir conf
32
33 # Examples of file query
34
35 # by list
36 #FILES="/etc/sysctl.conf /etc/init.d/procps /etc/passwd-"
37
38 # by command
39 FILES=$(find /etc/apache2 -type f $USERMODE | grep -v '.dpkg-')
40
41 # by command, public files, limited
42 #USERMODE="-perm /o+r"
43 #MAXDEPTH="-maxdepth 1"
44 #FILES=$(find /etc/ $MAXDEPTH -type f $USERMODE | grep -v '.dpkg-')
45
46 # by package name
47 #FILES=$(dpkg -L apache2.2-common | grep '^/etc')
48
49 for file in ${FILES};
50 do
51   if [ ! -e $file ];
52   then
53     echo "ERROR, file $file does not exist."
54     exit 1;
55   fi
56   echo "-> $file"
57
58   # Find out which installed package provides the config file
59   PACKAGE=$(dpkg-query -S "$file" | cut -d ':' -f 1 | uniq 2> /dev/null)
60
61   # Copy the whole file if it is not provided by default
62   if [ "x$PACKAGE" == "x" ];
63   then
64     DESTDIR=`dirname $file`
65     # strip trailing slash
66     [ ${DESTDIR:0:1} == '/' ] && DESTDIR=${DESTDIR:1}
67
68     # RECREATE the destination dir 
69     [ -d conf/$DESTDIR ] || mkdir -p conf/$DESTDIR
70     cp "$file" conf/$DESTDIR
71
72     continue
73   fi
74
75   # Get the package from the repository and diff
76
77   FILENAME=$(apt-cache show $PACKAGE | grep ^Filename | cut -d ' ' -f 2-)
78   ARCHIVE=$(basename $FILENAME)
79
80   if [ ! -f archives/$ARCHIVE ];
81   then
82     ( cd archives &&
83         wget -q -nc -c $DEBIANMIRROR/$FILENAME &&
84         mkdir ../temp/$PACKAGE
85         dpkg -x $ARCHIVE ../temp/$PACKAGE
86     )
87   fi
88
89   # Check for file existence before diffing, the file is not provided in
90   # package archive, but it could have been generated by package installation
91   # scripts
92   if [ ! -f temp/$PACKAGE/$file ];
93   then
94     echo "Warning: '$file' can't be found in package!"
95   fi
96
97
98   # TODO: diff only once and check filesize
99   TMPDIFF_FILE=`mktemp /tmp/etcdiff.XXXXXXXXXX`
100   diff -u temp/$PACKAGE/$file $file > $TMPDIFF_FILE
101   if [ `stat -c '%s' $TMPDIFF_FILE` -eq 0 ];
102   then
103     echo "$file: not changed"
104     rm -f $TMPDIFF_FILE
105   else
106     DESTDIR=`dirname $file`
107     # strip trailing slash
108     [ ${DESTDIR:0:1} == '/' ] && DESTDIR=${DESTDIR:1}
109
110     # RECREATE the destination dir 
111     [ -d conf/$DESTDIR ] || mkdir -p conf/$DESTDIR
112     cp $TMPDIFF_FILE conf/$DESTDIR/$(basename $file).patch
113
114     rm -f $TMPDIFF_FILE
115   fi
116
117 done