#!/bin/bash
#
# make-gvs-patches.sh v1.0 2006/03
#
# This script generates sets of 3 patches from 4 Kernel source trees
# optionally zipped and with optional diffstats, with an incremental
# version suffix to prevent overwrite.
#
# Copyright (C) 2006 < pjvenda (at) pjvenda org >
#
# Distributed under the terms of the GNU Public License Agreement (GPLv2)
# http://www.fsf.org/licensing/licenses/gpm.html or
# http://www.fsf.org/licensing/licenses/gpl.txt
#
# Long Description
# ================
#
# Suppose you have 4 kernel source trees:
# - linux-2.6.4
# - linux-2.6.4-p2
# - linux-2.6.4-p4
# - linux-2.6.4-p24
# and you want to have the following patches on a given directory - 
# say patches
# - patch-2.6.4-to-2.6.4--p24
# - patch-2.6.4-p1-to-2.6.4-p24
# - patch-2.6.4-p2-to-2.6.4-p24
# also, you want your patches in a given directory - say patches - 
# and since you're eventually clumsy as I am, you want to prevent 
# yourself from overwriting patches, by adding an incremental version 
# suffix:
# - patches/patch-2.6.4-to-2.6.4--p24-v01
# - patches/patch-2.6.4-p1-to-2.6.4-p24-v01
# - patches/patch-2.6.4-p2-to-2.6.4-p24-v01
# everytime you want to write a new patch, just increment the version
# number and generate new patches, eventually compressed.
# 
# uff, this script does just this tedious set of tasks and even more.
# - generates a new version (v01-vXX) for the patches according to
#   the existing versions
# - creates the 3 patches
# - optionally compresses the 3 patches (gzip or bzip2)
# - optionally generates diffstats of the 3 patches
# 
# Usage
# =====
#
# no big deal. just CONFIGURE some variables (below) and then
# run it on the parent directory of the Kernel source trees.
#
# Take a look at the code: It is very simple. Much simpler than this
# small help text. Trust me.
#
# Changelog
# =========
#
# v1.0 - 2006/03
# - initial version
#

# program locations for basic functions
DIFF=/usr/bin/diff
MKDIR=/usr/bin/mkdir
MV=/usr/bin/mv

# destination of patch files
PATCH_DIR=/usr/src/gvs

# base kernel version
KERNEL_VERSION=2.6.14.6
GRSEC_VERSION=2.1.8
VS_VERSION=2.1.0

# grsecurity kernel source tree location
GRSEC_DIR=linux-${KERNEL_VERSION}-grsec
# vserver kernel source tree location
VS_DIR=linux-${KERNEL_VERSION}-vs
# vanilla kernel source tree location
VANILLA_DIR=linux-${KERNEL_VERSION}
# grsecurity-vserver kernel source tree location
GRSEC_VS_DIR=linux-${KERNEL_VERSION}-grsec-vs

# final part of patch file names
GRSECVS=grsec${GRSEC_VERSION}-vs${VS_VERSION}

# initial step of incremental versioning
SERIAL=01

# compress patches: none, gz, bz2
COMPRESS=gz
GZIP=/bin/gzip
BZIP=/usr/bin/bzip2

# generate/show diffstat reports 0 or 
STATS=1
DIFFSTAT=/usr/bin/diffstat


check_patch_dir()
{
	if [ ! -d ${PATCH_DIR} ]; then
		echo "creating patch directory ${PATCH_DIR}."
		${MKDIR} -p ${PATCH_DIR}
	fi
}

set_patch_names()
{
	VERSION=v${SERIAL}
	GRSEC_PATCH=patch-${KERNEL_VERSION}-grsec${GRSEC_VERSION}-to-${GRSECVS}-${VERSION}
	VS_PATCH=patch-${KERNEL_VERSION}-vs${VS_VERSION}-to-${GRSECVS}-${VERSION}
	VANILLA_PATCH=patch-${KERNEL_VERSION}-to-${GRSECVS}-${VERSION}
}	

check_patch_files()
{
	if [ ${COMPRESS} == "gz" ]; then
		if [ -e ${PATCH_DIR}/${GRSEC_PATCH}.gz ] || [ -e ${PATCH_DIR}/${VS_PATCH}.gz ] || [ -e ${PATCH_DIR}/${VANILLA_PATCH}.gz ]; then
			# patch files exist! don't overwrite them
			return 1;
		else
			# patch files don't exist; these names are safe
			return 0;
		fi
	elif [ ${COMPRESS} == "bz2" ]; then
		if [ -e ${PATCH_DIR}/${GRSEC_PATCH}.bz2 ] || [ -e ${PATCH_DIR}/${VS_PATCH}.bz2 ] || [ -e ${PATCH_DIR}/${VANILLA_PATCH}.bz2 ]; then
			# patch files exist! don't overwrite them
			return 1;
		else
			# patch files don't exist; these names are safe
			return 0;
		fi
	else
		if [ -e ${PATCH_DIR}/${GRSEC_PATCH}.diff ] || [ -e ${PATCH_DIR}/${VS_PATCH}.diff ] || [ -e ${PATCH_DIR}/${VANILLA_PATCH}.diff ]; then
			# patch files exist! don't overwrite them
			return 1;
		else
			# patch files don't exist; these names are safe
			return 0;
		fi
	fi
}

check_patches()
{
	# set patch names with default values (SERIAL=01)
	set_patch_names
	while ! check_patch_files; do
		# patch files exist; increment serial
		SERIAL=$(printf %02d $((SERIAL+1)))
		# and generate new patch names
		set_patch_names
	done
}

create_patches ()
{
	# patching grsec to grsec-vs
	echo -n "patching grsec to grsec-vs... "
	${DIFF} -rNu ${GRSEC_DIR} ${GRSEC_VS_DIR} > ${PATCH_DIR}/${GRSEC_PATCH}
	echo "done"

	# patching vs to grsec-vs
	echo -n "patching vs to grsec-vs... "
	${DIFF} -rNu ${VS_DIR} ${GRSEC_VS_DIR} > ${PATCH_DIR}/${VS_PATCH}
	echo "done"

	# patching vanilla to grsec-vs
	echo -n "patching vanilla to grsec-vs... "
	${DIFF} -rNu ${VANILLA_DIR} ${GRSEC_VS_DIR} > ${PATCH_DIR}/${VANILLA_PATCH}
	echo "done"
}

compress_patches()
{
	if [ ${COMPRESS} == "gz" ]; then
		echo -n "gzipping patches... "
		${GZIP} ${PATCH_DIR}/${GRSEC_PATCH}
		echo -n "*"
		${GZIP} ${PATCH_DIR}/${VS_PATCH}
		echo -n "*"
		${GZIP} ${PATCH_DIR}/${VANILLA_PATCH}
		echo "* done"
	elif [ ${COMPRESS} == "bz2" ]; then
		echo -n "bzipping patches... "
		${BZIP} ${PATCH_DIR}/${GRSEC_PATCH}
		echo -n "*"
		${BZIP} ${PATCH_DIR}/${VS_PATCH}
		echo -n "*"
		${BZIP} ${PATCH_DIR}/${VANILLA_PATCH}
		echo "* done"
	else
		echo -n "adding .diff extensions... "
		${MV} ${PATCH_DIR}/${GRSEC_PATCH} ${PATCH_DIR}/${GRSEC_PATCH}.diff
		echo -n "*"
		${MV} ${PATCH_DIR}/${VS_PATCH} ${PATCH_DIR}/${VS_PATCH}.diff
		echo -n "*"
		${MV} ${PATCH_DIR}/${VANILLA_PATCH} ${PATCH_DIR}/${VANILLA_PATCH}.diff
		echo "* done"
	fi
}

create_stats()
{
	if [ ${STATS} -eq 1 ]; then
		# write diffstats
		echo -n "writing diffstats... "
		${DIFFSTAT} ${PATCH_DIR}/${GRSEC_PATCH} > ${PATCH_DIR}/${GRSEC_PATCH}.stat
		echo -n "*"
		${DIFFSTAT} ${PATCH_DIR}/${VS_PATCH} > ${PATCH_DIR}/${VS_PATCH}.stat
		echo -n "*"
		${DIFFSTAT} ${PATCH_DIR}/${VANILLA_PATCH} > ${PATCH_DIR}/${VANILLA_PATCH}.stat
		echo "* done"
	fi
}

# check for ${PATCH_DIR} existence and create it if necessary
check_patch_dir
# check for patch existence and generate new patch names if
# necessary to prevent overwriting
check_patches
# show chosen version
echo "version: ${SERIAL}"
# create patches into text files (to be compressed or renamed to .diff)
create_patches
# generate diffstats
create_stats
# compress patches
compress_patches
