#!/usr/bin/env bash
#----
## @Synopsis	Redefine install command for Centreon Install
## @Copyright	Copyright 2008, Guillaume Watteeux
## @Copyright	Copyright 2008-2020, Centreon
## @License	GPL : http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
## This program is't a "fork" of install command. Specificly develop for
## Centreon Install Script. 
## <p>
## Examples:
## <p>
## If you want to copy a sources files in a directory where you allready have
## a files with specific right, you can use this script to define right ONLY 
## on files and directories, use this command:
## <pre>
## cinstall -u user -g group -d 755 -m 644 -p src/dirtocopy src/dirtocopy/* dst/dirtopaste
## </pre>
## Usage
## <pre>
## Usage: cinstall [OPTION]... SOURCE DEST
##    or: cinstall [OPTION]... DIRECTORY
## <br>
## In the first form, copy SOURCE to DEST or multiple SOURCE(s) to
## the existing DIRECTORY, while setting permission modes and owner/group.
## In the second form, create all components of the given DIRECTORY.
## <br>
## Options:
##  -u USER	set ownership (super-user only)
##  -g GROUP	set group ownership
##  -m NUM	set permission mode for file(s) (as in chmod)
##  -d NUM	set permission mode for directory(ies) (as in chmod)
##  -b BKPDIR	make a backup of each existing destination
##  -p BASEDIR	use SOURCE in BASEDIR to set a destination permissions
##  -f 		use force command to ecrase old file or directory
##  -h		display this help and exit
##  -v		verbose mode
## </pre>
#----
## Centreon is developed with GPL Licence 2.0
##
## GPL License: http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
##
## Developed by : Julien Mathis - Romain Le Merlus
## Contributors : Guillaume Watteeux - Maximilien Bersoult
##
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## as published by the Free Software Foundation; either version 2
## of the License, or (at your option) any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License for more details.
##
##    For information : infos@centreon.com

# Enable Shell debug ?
#set -x

#----
##	print message 
##	@param	message
#----
function log() {
	if [ $verbose -eq 1 ] ; then 
		local program=$program
		local message=$@
		echo -e "[$program]: $message"
	fi
	return 0
}

#----
##	change username and group in a specific directory
##	@param	directory
## 	@param	chown/chgrp option (-R)
##	@Globals	username, group
#----
function lchown() {
	local directory="$1"
	local option=$2
	log "lchown: directory: $directory, option: $option"
	if [ -n "$username" ] ; then
		${CHOWN} $option $username:$group $directory
		log "\tchown $option $username:$group $directory"
	elif [ -n "$group" ] ; then
		chgrp $option $group $directory
		log "\tchgrp $option $group $directory"
	else
		return 0
	fi
	return 0
}

#----
##	find and chmod file or directory
##	@param	directory
## 	@param	type of search:	f=file, d=directory
## 	@param	permission mode (ex: 775)
## 	@param	define mindepth in find command (default 0)
#----
function find_and_chmod() {
	local directory=$1
	local type=$2
	local mode=$3
	local depth=${4:-0}
	log "find_and_chmod: directory: $directory"
	log "\ttype: $type; mode: $mode; depth: $depth"
	find $directory -mindepth $depth -type $type -print | \
		xargs -I '{}' ${CHMOD} $mode '{}'
	
	log "\tfind $directory -mindepth $depth -type $type -print | \ "
	log "\t\txargs -I '{}' chmod $mode '{}'"
	return 0
}

#----
##	Usage for this script
##	@Stdout	Usage information
#----
function usage() {
	local program=cinstall
	${CAT} << __EOT__

Usage: $program [OPTION]... SOURCE DEST
   or: $program [OPTION]... DIRECTORY

In the first form, copy SOURCE to DEST or multiple SOURCE(s) to
the existing DIRECTORY, while setting permission modes and owner/group.
In the second form, create all components of the given DIRECTORY.

Options:
  -u USER	set ownership (super-user only)
  -g GROUP	set group ownership
  -m NUM	set permission mode for file(s) (as in chmod)
  -d NUM	set permission mode for directory(ies) (as in chmod)
  -b BKPDIR	make a backup of each existing destination
  -p BASEDIR	use SOURCE in BASEDIR to set a destination permissions
  -f 		use force command to ecrase old file or directory
  -h		display this help and exit
  -v		verbose mode


__EOT__
return 0
}

[ -z ${GREP} ] && GREP=grep
[ -z ${CAT} ] && CAT=cat
[ -z ${SED} ] && SED=sed
[ -z ${CHMOD} ] && CHMOD=chmod
[ -z ${CHOWN} ] && CHOWN=chown

## Init default variables
program=`basename $0`
username=""
group=""
mode=""
dirmode=""
backupdir=""
backup=0
verbose=0
force=0

while getopts ":u:g:m:d:b:p:fhv" Option ; do
	#log "Option: $Option, arg: $OPTARG"
	case $Option in
		u )	username="$OPTARG" ;;
		g )	group="$OPTARG" ;;
		m )	mode="$OPTARG" ;;
		d )	dirmode="$OPTARG" ;;
		p )	basedir="$OPTARG" ;;
		b )	backupdir="$OPTARG" ; backup=1 ;;
		f )	force=1 ;;
		v )	verbose=1 ;;
		\?|h )	usage ; exit 0 ;;
		* )	usage ; exit 0 ;;
	esac 
done
shift $(($OPTIND - 1))

[ $# -eq 0 ] && usage && exit 0
## Check if backupdir exists when backup enabled
if [ $backup -eq 1 ] ; then
	log "Backup enabled in $backupdir"
	if [ ! -d $backupdir ] ; then
		log "$backupdir not found"
		mkdir -p $backupdir
		log "$backupdir create"
	fi
fi

### Main

if [ $# -eq 1 ] ; then
	dst=$1
	if [ ! -d $dst ] ; then 
		mkdir -p $dst
		log "Create directory: $dst"
	fi

	## Apply chown on DEST
	lchown $dst

	if [ -n "$dirmode" ] ; then 
		if [ -n "$basedir" ] ; then 
			find_and_chmod $basedir "d" "$dirmode" "1"
		else 
			${CHMOD} $dirmode $dst
		fi
	fi
fi
if [ $# -ge 2 ] ; then
	src=$1
	dst=""
	count=1
	shift
	## Count number of arguments
	while [ $# -gt 1 ] ; do
		src="$src $1"
		(( count++ ))
		shift
	done
	dst=$1
	
	## Test if I want exit program...
	## SRC=file and DEST=directory
	## DEST=directory without backup...
	if [ $count -eq 1 -a -d $dst ] ; then
		if [ -f "$src" ] ; then
			log "ERR: count:$count, $src is a file and $dst exists"
			exit 1
		elif [ -d "$src" -a $backup -ne 1 -a "$force" -eq 0 ] ; then
			log "ERR: count:$count, $src is a directory and backup disabled"
			exit 1
		fi
	fi
	
	## Backup DEST if necessary
	if [ $backup -eq 1 -a -e $dst ] ; then
		bdate=`date +%Y%m%d-%H%M%S`
		mv $dst $backupdir/`basename $dst`.$bdate 
		log "Backup $dst in $backupdir/`basename $dst`.$bdate"
	fi

	[ ! -d `dirname $dst` ] && mkdir -p `dirname $dst`
	[ $count -gt 1 -a ! -d $dst ] && mkdir -p $dst
	
	## Test howto copy SRC into DEST
	if [ $count -eq 1 -a -f "$src" ] ; then
		cp -f $src $dst
		log "count: $count, src: $src, src = file"
		log "cp -f $src $dst"
	elif [ $count -gt 1 ] ; then 
		log "count: $count, src: $src"
		if [ "$force" -eq 1 ] ; then 
			cp -Rf $src $dst
			log "force=on; cp -Rf $src $dst "
		else 
			cp -R $src $dst
			log "force=off; cp -R $src $dst "
		fi
	elif [ $count -eq 1 -a -d "$src" ] ; then
		log "count: $count, src: $src"
		if [ "$force" -eq 1 ] ; then 
			cp -Rf $src "$(dirname $dst)"
			log "force=on; cp -Rf $src $(dirname $dst) "
		else 
			cp -R $src $dst
			log "force=off; cp -R $src $dst "
		fi
	else 
		log "No copy"
		log "count: $count, src: $src"
		exit 1
	fi

	
	if [ -n "$basedir" ] ; then 
		## find all file for post set permissions
		cd $basedir
		files=`mktemp -t cinstall_files.XXXXXX`
		directory=`mktemp -t cinstall_dirs.XXXXXX`
		find . -type f -print > $files
		find . -mindepth 1 -type d -print  > $directory
		
		cd $dst
		## Apply permissions
		if [ -n "$username" ] ; then
			${CAT} $files $directory | \
				xargs -I '{}' ${CHOWN} $username:$group '{}' 
		elif [ -n "$group" ] ; then
			${CAT}  $files $directory | \
				xargs -I '{}' chgrp $group '{}'
		fi
		[ -n "$mode" ] && ${CAT} $files | \
			xargs -I '{}' ${CHMOD} $mode '{}' 
		[ -n "$dirmode" ] && ${CAT} $directory | \
			xargs -I '{}' ${CHMOD} $dirmode '{}' 

		rm -f $files $directory
	else 
		if [ $count -eq 1 -a -f "$src" ] ; then
			lchown $dst
			[ -n "mode" ] && ${CHMOD} $mode $dst
		elif [ $count -eq 1 -a -d "$src" ] ; then
			lchown $dst "-R"
			[ -n "$mode" ] && find_and_chmod $dst "f" "$mode"
			[ -n "$dirmode" ] && find_and_chmod $dst "d" "$dirmode"
		elif [ $count -gt 1 ] ; then
			lchown "$dst/*" "-R"
			[ -n "$mode" ] && find_and_chmod $dst "f" "$mode" "1"
			[ -n "$dirmode" ] && find_and_chmod $dst "d" "$dirmode" "1"

		fi

	fi
fi
exit 0


