From: eanders+@CMU.EDU (Eric A. Anderson)
Newsgroups: comp.sys.sun.admin
Subject: Re: Partition Getting Messed up
Date: 12 Jan 93 14:08:11 GMT
Article-I.D.: andrew.MfIppf_00Zk2RYFv0H
	<0fIPPoq00Zk2M1EtxV@andrew.cmu.edu>
Organization: Carnegie Mellon, Pittsburgh, PA

Since a number of people have asked for it, here is the program which
checks partitions for overlapping.
I didn't get it from the original author.  The person who sent it to
me said it had been posted recently to comp.sys.sun.admin.
	-Eric
#!/bin/sh
# chkoverlap - check overlapping disk partitions on suns
#	* works only on suns (so far)
#	* written by Bob Arnold 9/22/92
# Use at your own risk.  No warranty or guarantee of any sort is implied.
# Hopefully, you will find it useful.

badnewsonly=false		# assume we report good news too
showhost=false			# assume we show hostname
overlap=false			# assume we don't find overlap
filter=/tmp/$pr.filter		# filter egrep-ified from $usedparts
rpt=/tmp/$pr.rpt		# final report
tmp=/tmp/$pr.tmp		# scratch file
usedparts=/tmp/$pr.used		# list of used partitions
splithead=/tmp/chko.		# for split of egrep RE if it's too long
arch=`arch`			# Sun architecture, we hope
host=`hostname`			# get hostname of this machine
rmlist="$filter $rpt $tmp $usedparts ${splithead}*"	# files to clean up
USAGE="usage: $pr [-b|badnewsonly] [-s|showhost]
       $pr [-h|help]"

case "$arch" in
sun*)	: do nothing since we are ok ;;
*)	echo "$pr: This script only works on Suns." ; exit 1 ;;
esac

for arg in $* ; do
	case $arg in
	-b*|b*)	badnewsonly=true ;;
	-h*|h*)	echo "$USAGE" ; exit ;;
	-s*|s*)	showhost=true ;;
	esac
done

## build list of used partitions
# first, make sure we haven't left anything around
rm -f $rmlist
# first, get filesystems and root swap partition from df of local filesystems
df -t 4.2 \
| awk '
	/^\/dev\// {
		print $1, $NF
		if ($NF == "/") {
			print $1, "root_swap"
		}
	}' \
| sed -e '/ root_swap$/s/. /b /' > $usedparts
# a brief diversion here to get the name of the used filesystem
rootdev=`sed -n -e 's,/dev/\([^ ]*\) /$,\1,p' $usedparts`
# next, get used partitions from fstab; this list will mostly overlap the
# df output.  But it would include any swap partitions and "ignored"
# partitions ("ignored" partitions are probably Ingres raw log partitions).
egrep '^/dev/' /etc/fstab \
| awk '{print $1, $2}' \
| sed -e 's/ swap$/ fstab_swap/' >> $usedparts
# third, get raw ingres log partitions from fstab comments
awk '
	/^\#/ {
		# if this line mentions an Ingres raw log partition
		if ( $0 ~ /[iI]ngres.*[lL]og|[rR]aw.*[lL]og/ ) {
			# try to get the device name from this line
			gotdev=0
			for (i=1;i<=NF;i++) {
				if ($i~/\/dev\//) {
					print $1, "ingres_raw_log"
					gotdev=1
				}
			}
			# if this line did not have the device name, try the next line
			if (gotdev==0) {
				trynext=1
			}
		} else if (trynext==1) {
			trynext=0
			for (i=1; i<=NF; i++) {
				if ($i~/\/dev\//) {
					print $1, "ingres_raw_log"
					gotdev=1
				}
			}
		}
	}
' /etc/fstab >> $usedparts
# finally, strip floppies, cdroms, and leading "/dev/" from $usedparts,
# and sort uniq lines too
sed -e '/^\/dev\/fd/d' -e '/^\/dev\/sr/d' -e 's,\#*/dev/,,' $usedparts \
| sort +0u -1 > $tmp
mv $tmp $usedparts

## build list of used disks
disklist=`sed -e 's/. .*//' $usedparts | sort -u`
echo $disklist

## build egrep command to grab *used* partitions from list
## of *available* partitions
# create egrep filter
awk '{print "^" $1 " "}' $usedparts > $filter
# If there are too many filesystems, egrep will barf on the filter, saying
# egrep: regular expression too long
# In that case we have to split the filter into pieces and then create
# an egrep command that can handle them all
# To test for that condition, we have to feed the filter something it is
# guaranteed to find, i.e. the root device (which we figured out earlier)
# followed by a <SPACE>
if echo "$rootdev " | egrep -f $filter > /dev/null 2>&1 ; then
	egrepcmd="egrep -f $filter"
else
	split -5 $filter $splithead
	for i in ${splithead}* ; do
		if test -z "$egrepcmd" ; then
			egrepcmd="egrep -f $i"
		else
			egrepcmd="$egrepcmd | egrep -f $i"
		fi
	done
fi

## put check of each disk into $rpt
# gnarly code gets info about partitioning of each disk,
# egreps for partitions we're really using,
# joins that info to $usedparts and sorts it by starting cylinder
# (which is *key* because the following awk algorithm depends on it),
# shoving that output into an awk script to do the actual overlap check
for disk in $disklist ; do
	dkinfo $disk 2>&1 \
	| sed -e '/^[a-z][a-z][0-9]:/d' \
	      -e '/No such device or address/d' \
	      -e '/cylinders.*heads.*track/d' \
	| awk '
		$1  ~ /^[a-h]:/ {printf("%s%s %s ", "'$disk'", $1, $4)}
		$1 !~ /^[a-h]:/ {print $NF}
	' \
	| sed -e 's/[:(]//g' \
	| awk '{print $1, $3, $2}' \
	| eval $egrepcmd \
	| join - $usedparts \
	| sort +1n -2 \
	| awk '
		BEGIN {n=0}
		# load arrays from each input line
		{ part[n]=$1; startcyl[n]=$2; ncyl[n]=$3; mtpt[n]=$4; line[n]=$0; n++ }
		# now check arrays to see if any partitions overlap
		END {
			for (i=0; i+1<n; i++) {
				if ((startcyl[i]+ncyl[i]-1) >= startcyl[i+1]) {
					print line[i], "OVERLAP", line[i+1]
				}
			}
		}
	' >> $rpt
done

## final results !!
test -s $rpt && overlap=true
case $badnewsonly in
false)	test ! -s $rpt && echo OK > $rpt ;;
esac

case $showhost$badnewsonly in
truetrue)	echo -n "$host	" ; test $overlap = true && cat $rpt ;;
falsetrue)	:		  ; test $overlap = true && cat $rpt ;;
truefalse)	echo -n "$host	" ; cat $rpt ;;
falsefalse)	:		  ; cat $rpt ;;
esac

## clean up and quit
rm -f $rmlist
if test $overlap = "true" ; then
	exit 1
else
	exit 0
fi