integ/devtools/update-motd/files/customize-banner
Dean Troyer 3cd12006bb StarlingX open source release updates
Signed-off-by: Dean Troyer <dtroyer@gmail.com>
2018-05-31 07:36:35 -07:00

287 lines
7.0 KiB
Bash

#!/bin/bash
#
# Copyright (c) 2016 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
. /usr/bin/tsconfig
OPT_BANNER_BACKUP="/opt/banner.bk"
PLATFORM_BANNER_DIR="${CONFIG_PATH}/banner"
#
# set BANNER_VERBOSE to enable info logs
#
export BANNER_VERBOSE
info_log ()
{
if [ -n "${BANNER_VERBOSE}" ]; then
echo "INFO: customize-banner: $@" >&2
fi
}
warn_log ()
{
echo "WARNING: customize-banner: $@" >&2
}
error_log ()
{
echo "ERROR: customize-banner: $@" >&2
}
# some checks to see if the user does something odd
# Return: 1 if the file is not sane
# 0 if the file is normal looking
#
# Symbolic links are followed to their ultimate destination before
# further checks are made
file_is_sane ()
{
local fname=$1
if [ -z "${fname}" ]; then
error_log "no file specified"
return 1
fi
# resolve symlinks
if [ -h "${fname}" ]; then
local resolved=$(readlink -f "${fname}")
if [ -z "${resolved}" ]; then
error_log "file does not exist; did not resolve symbolic link"
return 1
fi
file_is_sane_no_link "${resolved}"
return $?
fi
file_is_sane_no_link "${fname}"
return $?
}
file_is_sane_no_link ()
{
local fname=$1
# a sanity check, the banner file has to be a regular file
# symbolic links are handled in file_is_sane()
if [ ! -f "${fname}" -o -h "${fname}" ]; then
error_log "file is not a regular file: ${fname}"
return 1
fi
# root usually has access to write readonly files...
if [ ! -w "${fname}" ]; then
error_log "file is readonly: ${fname}"
return 1
fi
# Warn only
if [ -x "${fname}" ]; then
warn_log "file is executable: ${fname}"
fi
}
#
# Prints list of files to stdout
#
get_banner_files ()
{
local flist=" \
/etc/issue \
/etc/issue.net \
/etc/motd.head \
/etc/motd.tail \
"
echo ${flist}
}
#
# This is to be executed either by config_controller or by the user
# through apply_banner_customization
#
# For each customizable file, if a customization is present do a bit of
# sanity and copy the file to the platform config for banner
# customization.
#
# Return 0 on success
# Return 1 for error conditions, if any customization file failed sanity
#
customize_banner ()
{
if [ ! -d "${CONFIG_PATH}" ]; then
error_log "config path does not exist"
return 1
fi
banner_dir="$1"
if [ -z "${banner_dir}" ]; then
error_log "path containing customization files is required"
return 1
fi
if [ ! -d "${banner_dir}" ]; then
warn_log "directory does not exist: ${banner_dir}"
return 0
fi
local inputok=0
local count=0
local fname=""
for fname in $(get_banner_files); do {
local bname="$(basename $fname)"
# confname includes 'etc'; newfname does not. This seems easier
# for the user; at least until a file with a duplicate name is
# customizable
local confname="${PLATFORM_BANNER_DIR}/${fname}"
local newfname="${banner_dir}/${bname}"
if [ -e "${newfname}" ]; then
count=$(expr $count + 1)
if ! file_is_sane ${newfname}; then
inputok=1
continue
fi
if [ -f "${confname}" ]; then
info_log "updating customization of ${fname}"
rm ${confname}
else
info_log "adding customization of ${fname}"
fi
mkdir -p $(dirname ${confname})
cp ${newfname} ${confname}
elif [ -f "${confname}" ]; then
info_log "maintaining previous customization of ${fname}"
fi
}; done
if [ "$count" -eq 0 ]; then
warn_log "no customization files were found in $banner_dir"
fi
return $inputok
}
#
# Compare two banner files
#
# Return 0 if they are the same
# 1 if they are different
#
compare_file ()
{
diff -q "$1" "$2" 2>&1 > /dev/null
return $?
}
#
# copy the file with a bkx extension, but only if it is not identical to
# another; look for an unused filename
#
# put a hard limit on the number of iterations
#
backup_file ()
{
local fname=$1
local dname=$(dirname $fname)
local bname=$(basename $fname)
local bkdir=${OPT_BANNER_BACKUP}/${dname}
local count=0
local newname=""
if [ ! -f "${fname}" ]; then
warn_log "file does not exist: $fname"
return 0
fi
for count in $(seq 0 9); do {
newname=${bkdir}/${bname}.bk${count}
if [ -e "${newname}" ]; then
if compare_file "${newname}" "${fname}"; then
info_log "file is previously backed up ${fname} as ${newname}"
touch ${newname}
return 0
fi
info_log "skipping name ${newname}"
else
if [ "$count" -gt 7 ]; then
warn_log "consider cleaning up $(dirname ${newname})"
fi
info_log "backing up ${fname} as ${newname}"
mkdir -p ${bkdir}
cp ${fname} ${newname}
return 0
fi
}; done
# find the oldest file and delete it.
newname=$(find ${bkdir} -maxdepth 1 -type f -name "${bname}.bk[0-9]" \
| xargs -r ls -1t | tail -n 1)
if [ -z "${newname}" -o ! -f "${newname}" ]; then
error_log "did not find backup files for ${fname}"
return 1
fi
warn_log "deleting oldest backed up file ${newname}"
rm ${newname}
cp ${fname} ${newname}
return $?
}
#
# For each customizable file, if the file exists under
# PLATFORM_BANNER_DIR, and it passes some sanity checks, then install
# the file onto the root fs
#
install_banner_files ()
{
# quietly stop if the PLATFORM_BANNER_DIR is not setup
if [ ! -d ${PLATFORM_BANNER_DIR} ]; then
return 0
fi
local banner_files=$(get_banner_files)
local bfile=""
for bfile in ${banner_files}; do {
# do not attempt to install files if the directory on the root
# fs is absent; this is an unexpected condition
if [ ! -d "$(dirname ${bfile})" ]; then
error_log "directory does not exist for ${bfile}"
continue
fi
# proceed only if the user provided a customization for the file
if [ ! -f "${PLATFORM_BANNER_DIR}/${bfile}" ]; then
info_log "file is not customized: ${bfile}"
continue
fi
if [ -e "${bfile}" ]; then
if ! file_is_sane ${bfile}; then
continue
fi
if compare_file "${PLATFORM_BANNER_DIR}/${bfile}" "${bfile}"; then
info_log "file already installed: ${bfile}"
continue
fi
info_log "installing over existing file: ${bfile}"
backup_file ${bfile} \
|| continue
else
info_log "installing: ${bfile}"
fi
cp ${PLATFORM_BANNER_DIR}/${bfile} ${bfile}
}; done;
}