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