Use getopts for helpers in filesystem

This commit is contained in:
Maniack Crudelis 2018-10-16 23:41:11 +02:00 committed by GitHub
parent f354c4b833
commit d59401f08e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -10,13 +10,12 @@ CAN_BIND=${CAN_BIND:-1}
# #
# If DEST is ended by a slash it complete this path with the basename of SRC. # If DEST is ended by a slash it complete this path with the basename of SRC.
# #
# usage: ynh_backup src [dest [is_big [arg]]] # usage: ynh_backup --src_path=src_path [--dest_path=dest_path] [--is_big]
# | arg: src - file or directory to bind or symlink or copy. it shouldn't be in # | arg: -s, --src_path - file or directory to bind or symlink or copy. it shouldn't be in
# the backup dir. # the backup dir.
# | arg: dest - destination file or directory inside the # | arg: -d, --dest_path - destination file or directory inside the
# backup dir # backup dir
# | arg: is_big - 1 to indicate data are big (mail, video, image ...) # | arg: -b, --is_big - Indicate data are big (mail, video, image ...)
# | arg: arg - Deprecated arg
# #
# example: # example:
# # Wordpress app context # # Wordpress app context
@ -43,15 +42,23 @@ CAN_BIND=${CAN_BIND:-1}
# #
ynh_backup() { ynh_backup() {
# TODO find a way to avoid injection by file strange naming ! # TODO find a way to avoid injection by file strange naming !
local SRC_PATH="$1"
local DEST_PATH="${2:-}" # Declare an array to define the options of this helper.
local IS_BIG="${3:-0}" declare -Ar args_array=( [s]=src_path= [d]=dest_path [b]=is_big )
local src_path
local dest_path
local is_big
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
local dest_path="${dest_path:-}"
local is_big="${is_big:-0}"
BACKUP_CORE_ONLY=${BACKUP_CORE_ONLY:-0} BACKUP_CORE_ONLY=${BACKUP_CORE_ONLY:-0}
# If backing up core only (used by ynh_backup_before_upgrade), # If backing up core only (used by ynh_backup_before_upgrade),
# don't backup big data items # don't backup big data items
if [ "$IS_BIG" == "1" ] && [ "$BACKUP_CORE_ONLY" == "1" ] ; then if [ "$is_big" == "1" ] && [ "$BACKUP_CORE_ONLY" == "1" ] ; then
echo "$SRC_PATH will not be saved, because backup_core_only is set." >&2 echo "$src_path will not be saved, because backup_core_only is set." >&2
return 0 return 0
fi fi
@ -59,24 +66,24 @@ ynh_backup() {
# Format correctly source and destination paths # Format correctly source and destination paths
# ============================================================================== # ==============================================================================
# Be sure the source path is not empty # Be sure the source path is not empty
[[ -e "${SRC_PATH}" ]] || { [[ -e "${src_path}" ]] || {
echo "Source path '${SRC_PATH}' does not exist" >&2 echo "Source path '${src_path}' does not exist" >&2
return 1 return 1
} }
# Transform the source path as an absolute path # Transform the source path as an absolute path
# If it's a dir remove the ending / # If it's a dir remove the ending /
SRC_PATH=$(realpath "$SRC_PATH") src_path=$(realpath "$src_path")
# If there is no destination path, initialize it with the source path # If there is no destination path, initialize it with the source path
# relative to "/". # relative to "/".
# eg: SRC_PATH=/etc/yunohost -> DEST_PATH=etc/yunohost # eg: src_path=/etc/yunohost -> dest_path=etc/yunohost
if [[ -z "$DEST_PATH" ]]; then if [[ -z "$dest_path" ]]; then
DEST_PATH="${SRC_PATH#/}" dest_path="${src_path#/}"
else else
if [[ "${DEST_PATH:0:1}" == "/" ]]; then if [[ "${dest_path:0:1}" == "/" ]]; then
# If the destination path is an absolute path, transform it as a path # If the destination path is an absolute path, transform it as a path
# relative to the current working directory ($YNH_CWD) # relative to the current working directory ($YNH_CWD)
@ -85,43 +92,43 @@ ynh_backup() {
# $YNH_BACKUP_DIR/apps/APP_INSTANCE_NAME/backup/ # $YNH_BACKUP_DIR/apps/APP_INSTANCE_NAME/backup/
# #
# If it's a system part backup script, YNH_CWD is equal to $YNH_BACKUP_DIR # If it's a system part backup script, YNH_CWD is equal to $YNH_BACKUP_DIR
DEST_PATH="${DEST_PATH#$YNH_CWD/}" dest_path="${dest_path#$YNH_CWD/}"
# Case where $2 is an absolute dir but doesn't begin with $YNH_CWD # Case where $2 is an absolute dir but doesn't begin with $YNH_CWD
[[ "${DEST_PATH:0:1}" == "/" ]] \ [[ "${dest_path:0:1}" == "/" ]] \
&& DEST_PATH="${DEST_PATH#/}" && dest_path="${dest_path#/}"
fi fi
# Complete DEST_PATH if ended by a / # Complete dest_path if ended by a /
[[ "${DEST_PATH: -1}" == "/" ]] \ [[ "${dest_path: -1}" == "/" ]] \
&& DEST_PATH="${DEST_PATH}/$(basename $SRC_PATH)" && dest_path="${dest_path}/$(basename $src_path)"
fi fi
# Check if DEST_PATH already exists in tmp archive # Check if dest_path already exists in tmp archive
[[ ! -e "${DEST_PATH}" ]] || { [[ ! -e "${dest_path}" ]] || {
echo "Destination path '${DEST_PATH}' already exist" >&2 echo "Destination path '${dest_path}' already exist" >&2
return 1 return 1
} }
# Add the relative current working directory to the destination path # Add the relative current working directory to the destination path
local REL_DIR="${YNH_CWD#$YNH_BACKUP_DIR}" local rel_dir="${YNH_CWD#$YNH_BACKUP_DIR}"
REL_DIR="${REL_DIR%/}/" rel_dir="${rel_dir%/}/"
DEST_PATH="${REL_DIR}${DEST_PATH}" dest_path="${rel_dir}${dest_path}"
DEST_PATH="${DEST_PATH#/}" dest_path="${dest_path#/}"
# ============================================================================== # ==============================================================================
# ============================================================================== # ==============================================================================
# Write file to backup into backup_list # Write file to backup into backup_list
# ============================================================================== # ==============================================================================
local SRC=$(echo "${SRC_PATH}" | sed -r 's/"/\"\"/g') local src=$(echo "${src_path}" | sed -r 's/"/\"\"/g')
local DEST=$(echo "${DEST_PATH}" | sed -r 's/"/\"\"/g') local dest=$(echo "${dest_path}" | sed -r 's/"/\"\"/g')
echo "\"${SRC}\",\"${DEST}\"" >> "${YNH_BACKUP_CSV}" echo "\"${src}\",\"${dest}\"" >> "${YNH_BACKUP_CSV}"
# ============================================================================== # ==============================================================================
# Create the parent dir of the destination path # Create the parent dir of the destination path
# It's for retro compatibility, some script consider ynh_backup creates this dir # It's for retro compatibility, some script consider ynh_backup creates this dir
mkdir -p $(dirname "$YNH_BACKUP_DIR/${DEST_PATH}") mkdir -p $(dirname "$YNH_BACKUP_DIR/${dest_path}")
} }
# Restore all files linked to the restore hook or to the restore app script # Restore all files linked to the restore hook or to the restore app script
@ -168,10 +175,10 @@ with open(sys.argv[1], 'r') as backup_file:
# Use the registered path in backup_list by ynh_backup to restore the file at # Use the registered path in backup_list by ynh_backup to restore the file at
# the good place. # the good place.
# #
# usage: ynh_restore_file ORIGIN_PATH [ DEST_PATH ] # usage: ynh_restore_file --origin_path=origin_path [--dest_path=dest_path]
# | arg: ORIGIN_PATH - Path where was located the file or the directory before # | arg: -o, --origin_path - Path where was located the file or the directory before
# to be backuped or relative path to $YNH_CWD where it is located in the backup archive # to be backuped or relative path to $YNH_CWD where it is located in the backup archive
# | arg: DEST_PATH - Path where restore the file or the dir, if unspecified, # | arg: -d, --dest_path - Path where restore the file or the dir, if unspecified,
# the destination will be ORIGIN_PATH or if the ORIGIN_PATH doesn't exist in # the destination will be ORIGIN_PATH or if the ORIGIN_PATH doesn't exist in
# the archive, the destination will be searched into backup.csv # the archive, the destination will be searched into backup.csv
# #
@ -189,43 +196,50 @@ with open(sys.argv[1], 'r') as backup_file:
# ynh_restore_file "conf/nginx.conf" # ynh_restore_file "conf/nginx.conf"
# #
ynh_restore_file () { ynh_restore_file () {
local ORIGIN_PATH="/${1#/}" # Declare an array to define the options of this helper.
local ARCHIVE_PATH="$YNH_CWD${ORIGIN_PATH}" declare -Ar args_array=( [o]=origin_path= [d]=dest_path= )
# Default value for DEST_PATH = /$ORIGIN_PATH local origin_path
local DEST_PATH="${2:-$ORIGIN_PATH}" local archive_path
local dest_path
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
local origin_path="/${origin_path#/}"
local archive_path="$YNH_CWD${origin_path}"
# Default value for dest_path = /$origin_path
local dest_path="${dest_path:-$origin_path}"
# If ARCHIVE_PATH doesn't exist, search for a corresponding path in CSV # If archive_path doesn't exist, search for a corresponding path in CSV
if [ ! -d "$ARCHIVE_PATH" ] && [ ! -f "$ARCHIVE_PATH" ] && [ ! -L "$ARCHIVE_PATH" ]; then if [ ! -d "$archive_path" ] && [ ! -f "$archive_path" ] && [ ! -L "$archive_path" ]; then
ARCHIVE_PATH="$YNH_BACKUP_DIR/$(_get_archive_path \"$ORIGIN_PATH\")" archive_path="$YNH_BACKUP_DIR/$(_get_archive_path \"$origin_path\")"
fi fi
# Move the old directory if it already exists # Move the old directory if it already exists
if [[ -e "${DEST_PATH}" ]] if [[ -e "${dest_path}" ]]
then then
# Check if the file/dir size is less than 500 Mo # Check if the file/dir size is less than 500 Mo
if [[ $(du -sb ${DEST_PATH} | cut -d"/" -f1) -le "500000000" ]] if [[ $(du -sb ${dest_path} | cut -d"/" -f1) -le "500000000" ]]
then then
local backup_file="/home/yunohost.conf/backup/${DEST_PATH}.backup.$(date '+%Y%m%d.%H%M%S')" local backup_file="/home/yunohost.conf/backup/${dest_path}.backup.$(date '+%Y%m%d.%H%M%S')"
mkdir -p "$(dirname "$backup_file")" mkdir -p "$(dirname "$backup_file")"
mv "${DEST_PATH}" "$backup_file" # Move the current file or directory mv "${dest_path}" "$backup_file" # Move the current file or directory
else else
ynh_secure_remove ${DEST_PATH} ynh_secure_remove ${dest_path}
fi fi
fi fi
# Restore ORIGIN_PATH into DEST_PATH # Restore origin_path into dest_path
mkdir -p $(dirname "$DEST_PATH") mkdir -p $(dirname "$dest_path")
# Do a copy if it's just a mounting point # Do a copy if it's just a mounting point
if mountpoint -q $YNH_BACKUP_DIR; then if mountpoint -q $YNH_BACKUP_DIR; then
if [[ -d "${ARCHIVE_PATH}" ]]; then if [[ -d "${archive_path}" ]]; then
ARCHIVE_PATH="${ARCHIVE_PATH}/." archive_path="${archive_path}/."
mkdir -p "$DEST_PATH" mkdir -p "$dest_path"
fi fi
cp -a "$ARCHIVE_PATH" "${DEST_PATH}" cp -a "$archive_path" "${dest_path}"
# Do a move if YNH_BACKUP_DIR is already a copy # Do a move if YNH_BACKUP_DIR is already a copy
else else
mv "$ARCHIVE_PATH" "${DEST_PATH}" mv "$archive_path" "${dest_path}"
fi fi
} }
@ -265,11 +279,17 @@ properly with chmod/chown." >&2
# #
# $app should be defined when calling this helper # $app should be defined when calling this helper
# #
# usage: ynh_store_file_checksum file # usage: ynh_store_file_checksum --file=file
# | arg: file - The file on which the checksum will performed, then stored. # | arg: -f, --file - The file on which the checksum will performed, then stored.
ynh_store_file_checksum () { ynh_store_file_checksum () {
local checksum_setting_name=checksum_${1//[\/ ]/_} # Replace all '/' and ' ' by '_' # Declare an array to define the options of this helper.
ynh_app_setting_set $app $checksum_setting_name $(sudo md5sum "$1" | cut -d' ' -f1) declare -Ar args_array=( [f]=file= )
local file
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
local checksum_setting_name=checksum_${file//[\/ ]/_} # Replace all '/' and ' ' by '_'
ynh_app_setting_set $app $checksum_setting_name $(sudo md5sum "$file" | cut -d' ' -f1)
} }
# Verify the checksum and backup the file if it's different # Verify the checksum and backup the file if it's different
@ -278,12 +298,17 @@ ynh_store_file_checksum () {
# #
# $app should be defined when calling this helper # $app should be defined when calling this helper
# #
# usage: ynh_backup_if_checksum_is_different file # usage: ynh_backup_if_checksum_is_different --file=file
# | arg: file - The file on which the checksum test will be perfomed. # | arg: -f, --file - The file on which the checksum test will be perfomed.
# #
# | ret: Return the name a the backup file, or nothing # | ret: Return the name a the backup file, or nothing
ynh_backup_if_checksum_is_different () { ynh_backup_if_checksum_is_different () {
local file=$1 # Declare an array to define the options of this helper.
declare -Ar args_array=( [f]=file= )
local file
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
local checksum_setting_name=checksum_${file//[\/ ]/_} # Replace all '/' and ' ' by '_' local checksum_setting_name=checksum_${file//[\/ ]/_} # Replace all '/' and ' ' by '_'
local checksum_value=$(ynh_app_setting_get $app $checksum_setting_name) local checksum_value=$(ynh_app_setting_get $app $checksum_setting_name)
if [ -n "$checksum_value" ] if [ -n "$checksum_value" ]
@ -318,28 +343,33 @@ ynh_delete_file_checksum () {
# Remove a file or a directory securely # Remove a file or a directory securely
# #
# usage: ynh_secure_remove path_to_remove # usage: ynh_secure_remove file=path_to_remove
# | arg: path_to_remove - File or directory to remove # | arg: -f, --file - File or directory to remove
ynh_secure_remove () { ynh_secure_remove () {
local path_to_remove=$1 # Declare an array to define the options of this helper.
declare -Ar args_array=( [f]=file= )
local file
# Manage arguments with getopts
ynh_handle_getopts_args "$@"
local forbidden_path=" \ local forbidden_path=" \
/var/www \ /var/www \
/home/yunohost.app" /home/yunohost.app"
if [[ "$forbidden_path" =~ "$path_to_remove" \ if [[ "$forbidden_path" =~ "$file" \
# Match all paths or subpaths in $forbidden_path # Match all paths or subpaths in $forbidden_path
|| "$path_to_remove" =~ ^/[[:alnum:]]+$ \ || "$file" =~ ^/[[:alnum:]]+$ \
# Match all first level paths from / (Like /var, /root, etc...) # Match all first level paths from / (Like /var, /root, etc...)
|| "${path_to_remove:${#path_to_remove}-1}" = "/" ]] || "${file:${#file}-1}" = "/" ]]
# Match if the path finishes by /. Because it seems there is an empty variable # Match if the path finishes by /. Because it seems there is an empty variable
then then
echo "Avoid deleting $path_to_remove." >&2 echo "Avoid deleting $file." >&2
else else
if [ -e "$path_to_remove" ] if [ -e "$file" ]
then then
sudo rm -R "$path_to_remove" sudo rm -R "$file"
else else
echo "$path_to_remove wasn't deleted because it doesn't exist." >&2 echo "$file wasn't deleted because it doesn't exist." >&2
fi fi
fi fi
} }