#!/bin/bash
#
# 20000710 bog@deol.ru
# 20011206 adapted to foreign root
# 20020103 adapted to gawk 3.1.0 (octal constants, --non-decimal-data dont work)
# 
#
# какие файлы принадлежат пакетам с разбивкой на линки, директории, устройства и обычные
# какие файлы менялись после установки пакетов
# предполагается, что в именах файлов не встречаются разделители полей (пробелы и др.)

root=$1
rpmdb_installed=${root}/var/lib/rpm

if [ -f ${rpmdb_installed}/packages.rpm ]
then
  installed_db='_dbapi 1'
else
  installed_db='_dbapi 3'
fi

if [ `id -u` != "0" ]
then
  echo switch user to root
  exit 1
fi

echo `date` generation file.installed.list
# увы, --dump не понимает моего желания съэкономить место с помощью --excludedoc или удаления ненужных locale
LANG= rpm --define "$installed_db" --dbpath ${rpmdb_installed} -qa -l --dump 2>/dev/null | awk '{if(NF == 11) print $1,$2,$3,$4,$5,$6,$7,$10,$11; if(NF == 10) print $1,$2,$3,0,$4,$5,$6,$9,$10};' | sort -k 1,1 > file.installed.list

echo `date` spliting file.installed.list 
# file.installed.list: fpath fsize fmtime fmd5sum fperm fowner fgroup frdev fsymlink
awk '{if ($5 >= 120000) print $1,$6,$7,$9 }' file.installed.list > file.installed.link.list
awk '{if ($5 >= 100000 && $5 < 120000) print $1,$3,$4,$5,$6,$7}' file.installed.list > file.installed.file.list
awk '{if ($5 >= 60000 && $5 < 100000) print $1,$5,$6,$7,$8}' file.installed.list > file.installed.bdev.list
awk '{if ($5 >= 40000 && $5 < 60000) print $1,$5,$6,$7}' file.installed.list > file.installed.dir.list
awk '{if ($5 >= 20000 && $5 < 40000) print $1,$5,$6,$7,$8}' file.installed.list > file.installed.cdev.list
awk '{if ($5 >= 10000 && $5 < 20000) print $1,$5,$6,$7}' file.installed.list > file.installed.pipe.list
awk '{if ($5 < 10000) print $1,$5 }' file.installed.list > file.installed.errortype.list

sort -k 1,1 file.installed.bdev.list file.installed.cdev.list > file.installed.rdev.list
rm file.installed.list file.installed.bdev.list file.installed.cdev.list

# file file.installed.link.list: fpath fowner fgroup fsymlink
echo `date` symbolic link
rm -f file.link.normal.list file.link.nonexist.list file.link.exist.list
touch file.link.nonexist.list file.link.exist.list
awk '{print $1}' file.installed.link.list | uniq > file.installed.link.names
cat file.installed.link.names | ./fileinfo -l -p ${root} | awk '{if( $2 == "error") print $1 >>"file.link.nonexist.list"; if( $2 == "ok" ) print $1, $3, $4, $5 >>"file.link.exist.list"}'
join -o 1.1,1.2,2.2,1.3,2.3 file.installed.link.list file.link.exist.list | awk '{if($2 != $3 || $4 != $5 )print $1}' > file.link.perm.list
awk '{print $1}' file.link.exist.list | cat - file.link.nonexist.list | sort | comm -2 -3 file.installed.link.names - | cat - file.link.perm.list | sort | uniq > file.link.modif.list
cat file.link.modif.list file.link.nonexist.list | sort | comm -2 -3 file.installed.link.names - > file.link.normal.list
rm file.installed.link.names file.link.exist.list

# file file.installed.file.list: fpath fmtime fmd5sum fperm fowner fgroup
echo `date` ordinary files
rm -f file.file.normal.list file.file.nonexist.list file.file.exist.list
touch file.file.nonexist.list file.file.exist.list
awk '{print $1}' file.installed.file.list | uniq > file.installed.file.names
cat file.installed.file.names | ./fileinfo -p ${root} | awk '{if( $2 == "error") print $1 >>"file.file.nonexist.list"; if( $2 == "ok" ) print $1, $3, $4, $5, $6 >>"file.file.exist.list"}'
awk '{print $1}' file.file.exist.list | awk '{print root $1}' root=${root} | xargs md5sum | awk '{print substr($2,length(root)+1), $1}' root=${root} | join -o 1.1,1.2,2.2,1.3,1.4,1.5 file.file.exist.list - > file.real.file.list
join -o 1.1,1.2,2.2 file.installed.file.list file.real.file.list | awk '{if($2 != $3) print $1}' > file.file.mtime.list
join -o 1.1,1.3,2.3 file.installed.file.list file.real.file.list | awk '{if($2 != $3) print $1}' > file.file.md5.list
join -o 1.1,1.4,2.4,1.5,2.5,1.6,2.6 file.installed.file.list file.real.file.list | awk '{if($2 != $3 || $4 != $5 || $6 != $7 )print $1}' > file.file.perm.list
awk '{print $1}' file.real.file.list | cat - file.file.nonexist.list | sort | comm -2 -3 file.installed.file.names - | cat - file.file.mtime.list file.file.md5.list file.file.perm.list | sort | uniq > file.file.modif.list
cat file.file.modif.list file.file.nonexist.list | sort | comm -2 -3 file.installed.file.names - > file.file.normal.list
rm file.installed.file.names file.file.exist.list file.real.file.list

# file file.installed.dir.list: fpath fperm fowner fgroup
echo `date` directories
rm -f file.dir.normal.list file.dir.nonexist.list file.dir.exist.list
touch file.dir.nonexist.list file.dir.exist.list
awk '{print $1}' file.installed.dir.list | uniq > file.installed.dir.names
cat file.installed.dir.names | ./fileinfo -p ${root} | awk '{if( $2 == "error") print $1 >>"file.dir.nonexist.list"; if( $2 == "ok" ) print $1, $4, $5, $6 >>"file.dir.exist.list"}'
join -o 1.1,1.2,2.2,1.3,2.3,1.4,2.4 file.installed.dir.list file.dir.exist.list | awk '{if($2 != $3 || $4 != $5 || $6 != $7 )print $1}' > file.dir.perm.list
awk '{print $1}' file.dir.exist.list | cat - file.dir.nonexist.list | sort | comm -2 -3 file.installed.dir.names - | cat - file.dir.perm.list | sort | uniq > file.dir.modif.list
cat file.dir.modif.list file.dir.nonexist.list | sort | comm -2 -3 file.installed.dir.names - > file.dir.normal.list
rm file.dir.exist.list

# file file.installed.rdev.list: fpath fperm fowner fgroup frdev
echo `date` device file
rm -f file.rdev.normal.list file.rdev.nonexist.list file.rdev.exist.list
touch file.rdev.nonexist.list file.rdev.exist.list
awk '{print $1}' file.installed.rdev.list | uniq > file.installed.rdev.names
cat file.installed.rdev.names | ./fileinfo -r -p ${root} | awk '{if( $2 == "error") print $1 >>"file.rdev.nonexist.list"; if( $2 == "ok" ) print $1, $3, $4, $5, $6 >>"file.rdev.exist.list"}'
join -o 1.1,1.2,2.2,1.3,2.3,1.4,2.4 file.installed.rdev.list file.rdev.exist.list | awk '{if($2 != $3 || $4 != $5 || $6 != $7 )print $1}' > file.rdev.perm.list
join -o 1.1,1.5,2.5 file.installed.rdev.list file.rdev.exist.list | awk '{if($2 != $3)print $1}' > file.rdev.device.list
awk '{print $1}' file.rdev.exist.list | cat - file.rdev.nonexist.list | sort | comm -2 -3 file.installed.rdev.names - | cat - file.rdev.perm.list file.rdev.device.list | sort | uniq > file.rdev.modif.list
cat file.rdev.modif.list file.rdev.nonexist.list | sort | comm -2 -3 file.installed.rdev.names - > file.rdev.normal.list
rm file.installed.rdev.names file.rdev.exist.list

# file file.installed.pipe.list: fpath fperm fowner fgroup
echo `date` pipes
rm -f file.pipe.normal.list file.pipe.nonexist.list file.pipe.exist.list
touch file.pipe.nonexist.list file.pipe.exist.list
awk '{print $1}' file.installed.pipe.list | uniq > file.installed.pipe.names
cat file.installed.pipe.names | ./fileinfo -p ${root} | awk '{if( $2 == "error") print $1 >>"file.pipe.nonexist.list"; if( $2 == "ok" ) print $1, $4, $5, $6 >>"file.pipe.exist.list"}'
join -o 1.1,1.2,2.2,1.3,2.3,1.4,2.4 file.installed.pipe.list file.pipe.exist.list | awk '{if($2 != $3 || $4 != $5 || $6 != $7 )print $1}' > file.pipe.perm.list
awk '{print $1}' file.pipe.exist.list | cat - file.pipe.nonexist.list | sort | comm -2 -3 file.installed.pipe.names - | cat - file.pipe.perm.list | sort | uniq > file.pipe.modif.list
cat file.pipe.modif.list file.pipe.nonexist.list | sort | comm -2 -3 file.installed.pipe.names - > file.pipe.normal.list
rm file.installed.pipe.names file.pipe.exist.list

echo `date` extra dir
cat file.dir.normal.list file.file.normal.list file.link.normal.list file.pipe.normal.list file.rdev.normal.list | sort| awk -F/ '{for(i=1;i<NF;i++) { for(j=1;j<=i;j++) printf "%s/",$j; printf "\n"}}' | awk '{if( length($0) > 1 ) print substr($0,1,length($0)-1)}' | sort -u | comm -1 -3 file.installed.dir.names - > file.dir.extra.list
rm file.installed.dir.names

echo `date` finish

