228 lines
6.6 KiB
Bash
228 lines
6.6 KiB
Bash
# ------------------------------------------------------------------------------
|
|
# File manipulation function
|
|
# This file is part of the init.sh project
|
|
# Copyright (c) 2019-2021 Geoffray Levasseur <fatalerrors@geoffray-levasseur.org>
|
|
# ------------------------------------------------------------------------------
|
|
# This file is distributed under 3-clause BSD license.
|
|
# The complete license agreement can be obtained at:
|
|
# https://opensource.org/licenses/BSD-3-Clause
|
|
# ------------------------------------------------------------------------------
|
|
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# Backup original installation files
|
|
# (or any old files if runned several time on same file)
|
|
backupdist()
|
|
{
|
|
if [[ $# -lt 1 ]]; then
|
|
prnt E "backupdist(): At least one argument is required."
|
|
exit 11
|
|
fi
|
|
|
|
local file=
|
|
for file in $@; do
|
|
local tmstmp=$(stdtime)
|
|
if [[ -L ${file} ]]; then
|
|
# With symbolik links we call again backupdist to treat target
|
|
prnt I "Following the symbolic link $file to do a proper backup..."
|
|
backupdist $(readlink -f ${file})
|
|
elif [[ -f ${file} ]]; then
|
|
prnt I "Creating a backup of ${file} on $tmstmp..."
|
|
cp -av $file ${file}.dist.${tmstmp}
|
|
if [[ $? -ne 0 ]]; then
|
|
prnt E "backupdist(): Failed copying file."
|
|
die 12
|
|
fi
|
|
elif [[ -d ${file} ]]; then
|
|
prnt I "Creation a backup of the directory ${file} on $tmstmp..."
|
|
cp -av $file ${file}.dist.${tmstmp}
|
|
if [[ $? -ne 0 ]]; then
|
|
prnt E "backupdist(): Failed copyind directory recursively."
|
|
die 12
|
|
fi
|
|
else
|
|
prnt W "backupdist(): $file don't exists, nothing to do."
|
|
fi
|
|
unset tmstmp
|
|
done
|
|
unset file
|
|
}
|
|
export -f backupdist
|
|
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# Select source file according to our priority mechanisme
|
|
select_file()
|
|
{
|
|
local infile=$1
|
|
if [[ -f $MYPATH/repo/hosts/$HOSTNAME/$infile ]]; then
|
|
local source="$MYPATH/repo/hosts/$HOSTNAME/$infile"
|
|
elif [[ -f $MYPATH/repo/common/$infile ]]; then
|
|
local source="$MYPATH/repo/common/$infile"
|
|
else
|
|
# Not found in repository, we expect full name
|
|
local source="$infile"
|
|
fi
|
|
unset infile
|
|
echo $source
|
|
unset source
|
|
}
|
|
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# Install file to the host (specific first then general)
|
|
# Todo: implement wildcard support
|
|
installfile()
|
|
{
|
|
local filelist=""
|
|
local i=0
|
|
|
|
if [[ $# -lt 2 ]]; then
|
|
prnt E "installfile(): At least two arguments are required."
|
|
die 11
|
|
fi
|
|
if [[ $(echo $@ | grep "\*\|\?") ]]; then
|
|
prnt E "installfile(): Wildcards are not authorized."
|
|
die 7
|
|
fi
|
|
|
|
local arg=
|
|
for arg in $@; do
|
|
filelist="$filelist $(select_file $arg)"
|
|
done
|
|
unset arg
|
|
|
|
# Empty to just obtain the target which is the last element of the list
|
|
local file=
|
|
for file in $filelist; do
|
|
:
|
|
done
|
|
if [[ ! $file == /* ]]; then
|
|
prnt E "installfile(): Target must be on the root filesystem and full path must be provided."
|
|
die 13
|
|
fi
|
|
unset file
|
|
|
|
if [[ -d $(dirname $i) ]]; then
|
|
prnt I "Creating required target directory $(dirname $i)..."
|
|
mkdir -pv $(dirname $i)
|
|
if [[ $? -ne 0 ]]; then
|
|
prnt E "installfile(): Can't create target directory!"
|
|
die 12
|
|
fi
|
|
fi
|
|
prnt I "Copying files ${filelist} to target directory $(dirname $i)..."
|
|
cp -av $filelist
|
|
if [[ $? -ne 0 ]]; then
|
|
prnt E "installfile(): Couldn't copy some required files!"
|
|
die 12
|
|
fi
|
|
}
|
|
export -f installfile
|
|
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# Add the content of a file at the end of an other
|
|
appendfile()
|
|
{
|
|
local srcfile=$(select_file $1)
|
|
local dstfile=$2
|
|
if [[ -e $dstfile ]]; then
|
|
prnt E "appendfile(): Target must be on the root filesystem and full path must be provided."
|
|
die 13
|
|
fi
|
|
if [[ ! $dstfile == /* ]]; then
|
|
prnt E "appendfile(): Target file must exist."
|
|
die 13
|
|
fi
|
|
|
|
prnt I "Adding content to file $dstfile..."
|
|
cat $srcfile >> $dstfile
|
|
if [[ $? -ne 0 ]]; then
|
|
prnt E "appendfile(): Couldn't append a file!"
|
|
die 12
|
|
fi
|
|
}
|
|
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# determine if a directory is empty
|
|
isdirempty()
|
|
{
|
|
dir=$1
|
|
|
|
if [[ -f $dir ]]; then
|
|
prnt E "isdirempty():The given parameter is not a directory."
|
|
die 15
|
|
fi
|
|
if [[ ! -d $dir ]]; then
|
|
return 0
|
|
fi
|
|
|
|
nbfiles=$(ls -a1 $dir | egrep -v '^.$|^..$' | wc -l)
|
|
if [[ $nbfiles -eq 0 ]]; then
|
|
return 0
|
|
fi
|
|
return 1
|
|
}
|
|
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# copy and patch a file replacing all @var@ by the corresponding value in
|
|
# environment or the variable list given in parameter
|
|
patchfile()
|
|
{
|
|
local srcfile=$(select_file $1) && shift
|
|
local dstfile=$1 && shift
|
|
local workfile=${dstfile}.work
|
|
|
|
if [[ ! -s $srcfile ]]; then
|
|
prnt E "The source file is empty, is not a file or don't exists!"
|
|
die 10
|
|
fi
|
|
|
|
# Create a sub-process, to avoid bash environment pollution
|
|
(
|
|
local varlist= pattern=
|
|
if [[ $# -eq 0 ]] ; then
|
|
pattern="-e s/<\(.*\)>/\$\1\$\1/g"
|
|
else
|
|
local var=
|
|
for var in $* ; do
|
|
if ! declare -p $var >/dev/null 2>&1 ; then
|
|
local $var=$(eval echo \$$var)
|
|
fi
|
|
export $var
|
|
pattern="$pattern -e s/@$var@/\$$var/g"
|
|
varlist=$varlist\$$var
|
|
done
|
|
fi
|
|
|
|
# sed replace <VAR> with \$$VAR and envsubst do the replace by value
|
|
sed $pattern $srcfile | envsubst ${varlist:+"$varlist"} > "$workfile"
|
|
)
|
|
|
|
local -a rights=( $(stat --printf="%a %u %g" "$srcfile") )
|
|
unset srcfile
|
|
mv "$workfile" "$dstfile"
|
|
chmod ${rights[0]} "$dstfile"
|
|
chown ${rights[1]}:${rights[2]} "$dstfile"
|
|
|
|
unset rights dstfile
|
|
}
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# check a file exists and return error if not
|
|
file_exists()
|
|
{
|
|
prnt I "Checking $@ files existance..."
|
|
for f in $@; do
|
|
if [[ ! -f $(select_file $f) ]]; then
|
|
prnt E "The $f file is missing, cannot continue."
|
|
die 10
|
|
fi
|
|
done
|
|
}
|
|
|
|
# EOF
|