jina verze
This commit is contained in:
@@ -0,0 +1,827 @@
|
||||
# Searches for entries (files and directories) in the specified local directory.
|
||||
#
|
||||
# $1 (path): The path to the directory on the local machine where the search for entries will be performed.
|
||||
# $2 (type): Type entry (f: files, d: directories, ...).
|
||||
function fileList() {
|
||||
local path="${1-}"
|
||||
local type="${2-}"
|
||||
local args=(-mindepth 1 -maxdepth 1)
|
||||
|
||||
[[ -n "$path" ]] || { appError "Path not specified"; return 1; }
|
||||
[[ -d "$path" ]] || { appError "Directory not found: $path"; return 1; }
|
||||
|
||||
if [[ -n "$type" ]]; then
|
||||
case "$type" in
|
||||
f|d|l|p|s|b|c) args+=(-type "$type") ;;
|
||||
*) appError "Unsupported file type: $type"; return 1 ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
find "$path" "${args[@]}" -printf '%f\n'
|
||||
}
|
||||
|
||||
# Searches for entries (files or directories) in the specified directory on an FTP server.
|
||||
#
|
||||
# $1 (path): The path to the directory on the FTP server where the search for entries will be performed.
|
||||
# $2 (type): Type entry (f: files, d: directories, ...).
|
||||
function ftpFileList() {
|
||||
local path="$1"
|
||||
local type="$2"
|
||||
local output error
|
||||
|
||||
run output error curl -sS -u "$ftpUser:$ftpPass" "ftp://$ftpHost:$ftpPort$ftpPath$path/" --connect-timeout 10 \
|
||||
|| { appError "$error"; return 1; }
|
||||
|
||||
case "$type" in
|
||||
f) printf '%s\n' "$output" | grep -v '^d' | awk '{print $NF}' ;;
|
||||
d) printf '%s\n' "$output" | grep '^d' | awk '{print $NF}' ;;
|
||||
*) printf '%s\n' "$output" | awk '{print $NF}' ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Searches for entries (files or directories) in the specified directory on a remote server via SSH.
|
||||
#
|
||||
# $1 (path): The path to the directory on the remote server where the search for entries will be performed.
|
||||
# $2 (type): Type entry (f: files, d: directories, ...).
|
||||
function sshFileList() {
|
||||
local path="$1"
|
||||
local type="$2"
|
||||
local typeArg="${type:+-type $type}"
|
||||
local output error
|
||||
|
||||
run output error ssh -i "$sshKeyFile" "$sshUser@$sshHost" \
|
||||
"find '${sshPath}${path}' -maxdepth 1 -mindepth 1 ${typeArg} -exec basename {} \\;" \
|
||||
|| { appError "$error"; return 1; }
|
||||
|
||||
printf '%s\n' "$output"
|
||||
}
|
||||
|
||||
# Searches for entries (files or directories) in the specified directory on external storage.
|
||||
function storageFileList() {
|
||||
local -A storageFunc=(
|
||||
[ftp]=ftpFileList
|
||||
[rsync]=ftpFileList
|
||||
[ssh]=sshFileList
|
||||
)
|
||||
[[ -n "${storageFunc[$storageType]:-}" ]] || { appError "Unknown value storageType: $storageType"; return 1; }
|
||||
|
||||
"${storageFunc[$storageType]}" "$@"
|
||||
}
|
||||
|
||||
# Cleans a specified directory on a remote server using rsync.
|
||||
#
|
||||
# $1 (path): The path to the directory to be cleaned on the remote server.
|
||||
#
|
||||
# The function creates a temporary empty directory on the local machine and syncs it with the remote directory
|
||||
# using rsync with the `--delete` option, which removes any files on the remote side that are not present in
|
||||
# the local directory. After completion, the temporary directory is deleted. An error message is displayed in case of failure.
|
||||
function rsyncDirectoryClean() {
|
||||
local path="$1"
|
||||
[[ -n "$path" ]] || { appError "Path not specified"; return 1; }
|
||||
|
||||
local emptyPath="$appDataPath/$(uuidgen)"
|
||||
local error
|
||||
runError error mkdir -p "$emptyPath" || { appError "Failed to create temp directory: $error"; return 1; }
|
||||
|
||||
runError error rsync -r --delete --password-file="$rsyncPassFile" "$emptyPath/" rsync://"$rsyncUri$path/" \
|
||||
|| { rm -rf "$emptyPath"; appError "Failed to clean remote directory: $error"; return 1; }
|
||||
rm -rf "$emptyPath"
|
||||
}
|
||||
|
||||
# Deletes a directory on an FTP server.
|
||||
#
|
||||
# $1 (path): The path to the directory on the FTP server to be deleted (in ftpPath).
|
||||
function ftpDirectoryDelete() {
|
||||
local path="$1"
|
||||
[[ -n "$path" ]] || { appError "Path not specified"; return 1; }
|
||||
|
||||
local error
|
||||
runError error curl -u "$ftpUser:$ftpPass" -Q "-RMD $ftpPath$path" "ftp://$ftpHost:$ftpPort" --connect-timeout 10 \
|
||||
|| { appError "$error"; return 1; }
|
||||
}
|
||||
|
||||
# Deletes a directory on a remote server via SSH (in sshPath).
|
||||
#
|
||||
# $1 (path): The path to the directory to be deleted.
|
||||
function sshDirectoryDelete() {
|
||||
local path="$1"
|
||||
[[ -n "$path" ]] || { appError "Path not specified"; return 1; }
|
||||
|
||||
local error
|
||||
runError error ssh -i "$sshKeyFile" "$sshUser@$sshHost" "rm -rf '${sshPath}${path}'" \
|
||||
|| { appError "$error"; return 1; }
|
||||
}
|
||||
|
||||
# Create a timestamped backup copy of a file if it exists.
|
||||
# $1 (file): path to the file to back up.
|
||||
# [$2] (suffix): custom suffix for the backup file (defaults to a timestamp .bak suffix).
|
||||
function fileBackup() {
|
||||
local file="$1"
|
||||
if [[ -z "$file" ]]; then
|
||||
appError "File not specified"
|
||||
return 1
|
||||
fi
|
||||
if [[ ! -f "$file" ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
local suffix="${2:-.$(date +%F_%H-%M-%S).bak}"
|
||||
|
||||
cp -p -- "$file" "$file$suffix" || {
|
||||
appError "Failed to backup file: $file"
|
||||
return 1
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# Download remote file to a local path.
|
||||
function fileDownload() {
|
||||
local remoteFile="$1"
|
||||
local localFile="$2"
|
||||
local retries="${3:-5}"
|
||||
local delay="${4:-3}"
|
||||
|
||||
[[ -n "$remoteFile" ]] || { appError "Remote file not specified"; return 1; }
|
||||
[[ -n "$localFile" ]] || { appError "Local file not specified"; return 1; }
|
||||
|
||||
mkdir -p "$(dirname "$localFile")" || { appError "Failed to create folder"; return 1; }
|
||||
|
||||
local tmpFile="${localFile}.part"
|
||||
local i rc curlError lastError
|
||||
for ((i = 1; i <= retries; i++)); do
|
||||
curlError=$(curl -kfsSL --http1.1 --max-redirs 10 --connect-timeout 30 --speed-time 60 --speed-limit 1024 -C - -o "$tmpFile" "$remoteFile" 2>&1)
|
||||
rc=$?
|
||||
if [[ $rc -eq 0 ]]; then
|
||||
mv -f "$tmpFile" "$localFile" || { appError "Failed to move downloaded file"; return 1; }
|
||||
return 0
|
||||
fi
|
||||
|
||||
lastError="$curlError"
|
||||
[[ $rc -ne 33 ]] || rm -f "$tmpFile" # rc=33: server doesn't support resume, restart from scratch
|
||||
|
||||
sleep "$delay"
|
||||
done
|
||||
|
||||
lastError="${lastError//$'\r'/ }"
|
||||
lastError="${lastError//$'\n'/ }"
|
||||
|
||||
appError "Failed to download file after $retries attempts | $lastError"
|
||||
return 1
|
||||
}
|
||||
|
||||
# Creates an archive from a source file or directory.
|
||||
#
|
||||
# Supported archive formats are selected by the target file extension:
|
||||
# .zip, .tar.gz, or .tgz.
|
||||
#
|
||||
# $1 (source): Source file or directory to archive.
|
||||
# $2 (target): Target archive file path.
|
||||
#
|
||||
# Returns:
|
||||
# 0 on success, 1 on validation or archive creation failure.
|
||||
function archiveCreate() {
|
||||
local source="$1"
|
||||
if [[ -z "$source" ]]; then
|
||||
appError "Source path not specified"
|
||||
return 1
|
||||
fi
|
||||
if [[ ! -e "$source" ]]; then
|
||||
appError "Source path not found: $source"
|
||||
return 1
|
||||
fi
|
||||
|
||||
local target="$2"
|
||||
if [[ -z "$target" ]]; then
|
||||
appError "Target file not specified"
|
||||
return 1
|
||||
fi
|
||||
|
||||
local compressProgram="${3:-}"
|
||||
|
||||
local sourcePath sourceBase targetPath targetBase output rc
|
||||
sourcePath=$(dirname -- "$source")
|
||||
sourceBase=$(basename -- "$source")
|
||||
targetPath=$(dirname -- "$target")
|
||||
targetBase=$(basename -- "$target")
|
||||
|
||||
case "$targetBase" in
|
||||
*.zip|*.tar.gz|*.tgz)
|
||||
;;
|
||||
*)
|
||||
appError "Unknown type archive: $targetBase"
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
|
||||
mkdir -p -- "$targetPath" || {
|
||||
appError "Failed to create directory: $targetPath"
|
||||
return 1
|
||||
}
|
||||
|
||||
case "$targetBase" in
|
||||
*.zip)
|
||||
if [[ -d "$source" ]]; then
|
||||
output=$(cd "$source" && zip -qr "$target" . 2>&1)
|
||||
else
|
||||
output=$(cd "$sourcePath" && zip -qr "$target" "$sourceBase" 2>&1)
|
||||
fi
|
||||
rc=$?
|
||||
[[ $rc -le 1 ]] || { appError "Error creating ZIP (rc=$rc)${output:+: $output}"; return 1; }
|
||||
[[ $rc -ne 1 ]] || [[ -z "$output" ]] || appError "Warning creating ZIP${output:+: $output}"
|
||||
;;
|
||||
*.tar.gz|*.tgz)
|
||||
local -a tarCompressFlags
|
||||
if [[ -n "$compressProgram" ]]; then
|
||||
tarCompressFlags=("--use-compress-program=$compressProgram")
|
||||
else
|
||||
tarCompressFlags=("-z")
|
||||
fi
|
||||
if [[ -d "$source" ]]; then
|
||||
output=$(tar --warning=no-file-changed -c "${tarCompressFlags[@]}" -f "$target" -C "$source" . 2>&1)
|
||||
else
|
||||
output=$(tar --warning=no-file-changed -c "${tarCompressFlags[@]}" -f "$target" -C "$sourcePath" "$sourceBase" 2>&1)
|
||||
fi
|
||||
rc=$?
|
||||
[[ $rc -le 1 ]] || { appError "Error creating TAR (rc=$rc)${output:+: $output}"; return 1; }
|
||||
[[ $rc -ne 1 ]] || [[ -z "$output" ]] || appError "Warning creating TAR${output:+: $output}"
|
||||
;;
|
||||
esac
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# Extracts an archive into a target directory.
|
||||
#
|
||||
# Supported archive formats are selected by the source file extension:
|
||||
# .zip, .tar.gz, or .tgz.
|
||||
#
|
||||
# $1 (source): Source archive file path.
|
||||
# $2 (target): Target directory where archive contents should be extracted.
|
||||
#
|
||||
# Returns:
|
||||
# 0 on success, 1 on validation or extraction failure.
|
||||
function archiveExtract() {
|
||||
local source="$1"
|
||||
if [[ -z "$source" ]]; then
|
||||
appError "Source archive not specified"
|
||||
return 1
|
||||
fi
|
||||
if [[ ! -f "$source" ]]; then
|
||||
appError "Source archive not found: $source"
|
||||
return 1
|
||||
fi
|
||||
|
||||
local target="$2"
|
||||
if [[ -z "$target" ]]; then
|
||||
appError "Target directory not specified"
|
||||
return 1
|
||||
fi
|
||||
|
||||
local sourceBase output rc
|
||||
sourceBase=$(basename -- "$source")
|
||||
|
||||
case "$sourceBase" in
|
||||
*.zip|*.tar.gz|*.tgz)
|
||||
;;
|
||||
*)
|
||||
appError "Unknown type archive: $sourceBase"
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
|
||||
mkdir -p -- "$target" || {
|
||||
appError "Failed to create directory: $target"
|
||||
return 1
|
||||
}
|
||||
|
||||
case "$sourceBase" in
|
||||
*.zip)
|
||||
output=$(unzip -oq "$source" -d "$target" 2>&1)
|
||||
rc=$?
|
||||
if [[ $rc -ne 0 ]]; then
|
||||
appError "Error extracting ZIP: $output"
|
||||
return 1
|
||||
fi
|
||||
;;
|
||||
*.tar.gz|*.tgz)
|
||||
output=$(tar -xzf "$source" -C "$target" 2>&1)
|
||||
rc=$?
|
||||
if [[ $rc -ne 0 ]]; then
|
||||
appError "Error extracting TAR: $output"
|
||||
return 1
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# Retrieves the size of the specified path (file or directory) in b/kb/mb/gb.
|
||||
#
|
||||
# $1 (path): The path to the file or directory whose size is to be retrieved.
|
||||
# $2 (unit): Unit.
|
||||
# $3 (precision): Precision.
|
||||
function pathSize() {
|
||||
local path="$1"
|
||||
[[ -n "$path" ]] || { appError "Path not specified"; return 1; }
|
||||
|
||||
local unit="${2:-}"
|
||||
local precision="${3:-0}"
|
||||
local divisor="1"
|
||||
case "${unit,,}" in
|
||||
kb) divisor="1024" ;;
|
||||
mb) divisor="1048576" ;;
|
||||
gb) divisor="1073741824" ;;
|
||||
esac
|
||||
|
||||
local output error bytes
|
||||
if [[ -d "$path" ]]; then
|
||||
run output error du -sb "$path" || { appError "$error"; return 1; }
|
||||
bytes=$(printf '%s\n' "$output" | cut -f1)
|
||||
elif [[ -f "$path" ]]; then
|
||||
run output error stat -c %s "$path" || { appError "$error"; return 1; }
|
||||
bytes="$output"
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
|
||||
LC_NUMERIC=C awk -v bytes="$bytes" -v divisor="$divisor" -v precision="$precision" 'BEGIN { printf "%.*f\n", precision, bytes / divisor }'
|
||||
}
|
||||
|
||||
# Return the contents of a file if it exists and is non-empty, otherwise write the given value to it and return it.
|
||||
# $1 (file): path to the file.
|
||||
# $2 (value): value to write when the file is missing or empty.
|
||||
function fileValueGetOrCreate() {
|
||||
local file="${1-}"
|
||||
local value="${2-}"
|
||||
|
||||
if [[ -z "$file" ]]; then
|
||||
appError "File not specified"
|
||||
return 1
|
||||
fi
|
||||
if [[ -s "$file" ]]; then
|
||||
cat "$file"
|
||||
return $?
|
||||
fi
|
||||
|
||||
if [[ -z "$value" ]]; then
|
||||
appError "Value not specified"
|
||||
return 1
|
||||
fi
|
||||
|
||||
mkdir -p -- "$(dirname -- "$file")" || {
|
||||
appError "Failed to create folder for: $file"
|
||||
return 1
|
||||
}
|
||||
|
||||
install -o root -g root -m 600 /dev/null "$file" || {
|
||||
appError "Failed to create file: $file"
|
||||
return 1
|
||||
}
|
||||
|
||||
printf '%s\n' "$value" > "$file" || {
|
||||
appError "Failed to save value: $file"
|
||||
return 1
|
||||
}
|
||||
|
||||
printf '%s\n' "$value"
|
||||
}
|
||||
|
||||
# Retrieves or generates a password and stores it in the specified file.
|
||||
#
|
||||
# $1: path to the file where the password should be stored.
|
||||
# [$2+]: additional parameters are passed to the stringRandom function for generating the password (optional).
|
||||
function filePasswordGetOrCreate() {
|
||||
local file="${1-}"
|
||||
if [[ -z "$file" ]]; then
|
||||
appError "File not specified"
|
||||
return 1
|
||||
fi
|
||||
shift || true
|
||||
|
||||
local value
|
||||
if [[ -s "$file" ]]; then
|
||||
cat "$file"
|
||||
return $?
|
||||
fi
|
||||
value="$(strRandom "$@")" || {
|
||||
appError "Failed to generate password"
|
||||
return 1
|
||||
}
|
||||
|
||||
fileValueGetOrCreate "$file" "$value"
|
||||
}
|
||||
|
||||
# Get value by key from "KEY=VALUE" content or file (returns first match)
|
||||
function configGet() {
|
||||
local file="${1-}"
|
||||
local key="${2-}"
|
||||
local line value
|
||||
|
||||
if [[ -z "$file" ]]; then
|
||||
appError "Config file not specified"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [[ -z "$key" ]]; then
|
||||
appError "Config key not specified"
|
||||
return 1
|
||||
fi
|
||||
|
||||
[[ -f "$file" ]] || {
|
||||
printf '\n'
|
||||
return 0
|
||||
}
|
||||
|
||||
line="$(awk -F= -v key="$key" '$1 == key { print; exit }' "$file")" || {
|
||||
printf '\n';
|
||||
return 0;
|
||||
}
|
||||
[[ "$line" == "$key="* ]] || {
|
||||
printf '\n'
|
||||
return 0
|
||||
}
|
||||
|
||||
value="${line#*=}"
|
||||
value="$(sed -E 's/[[:space:]]+$//' <<<"$value")"
|
||||
|
||||
printf '%s\n' "$value"
|
||||
}
|
||||
|
||||
# Ensure key=value is present in file (remove previous key lines, then append).
|
||||
function configSet() {
|
||||
local file="${1-}"
|
||||
local key="${2-}"
|
||||
local value="${3-}"
|
||||
local tmp
|
||||
|
||||
if [[ -z "$file" ]]; then
|
||||
appError "Config file not specified"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [[ -z "$key" ]]; then
|
||||
appError "Config key not specified"
|
||||
return 1
|
||||
fi
|
||||
|
||||
value="${value//$'\r'/ }"
|
||||
value="${value//$'\n'/ }"
|
||||
|
||||
mkdir -p -- "$(dirname -- "$file")" || {
|
||||
appError "Failed to create folder for: $file"
|
||||
return 1
|
||||
}
|
||||
|
||||
[[ -f "$file" ]] || install -o root -g root -m 600 /dev/null "$file" || {
|
||||
appError "Failed to create file: $file"
|
||||
return 1
|
||||
}
|
||||
|
||||
tmp="$(mktemp)" || return 1
|
||||
|
||||
awk -F= -v key="$key" '$1 != key' "$file" > "$tmp" || true
|
||||
|
||||
if [[ -n "$value" ]]; then
|
||||
printf '%s=%s\n' "$key" "$value" >> "$tmp" || {
|
||||
rm -f -- "$tmp"
|
||||
appError "Failed to write config value: $key"
|
||||
return 1
|
||||
}
|
||||
fi
|
||||
|
||||
cat "$tmp" > "$file" || {
|
||||
rm -f -- "$tmp"
|
||||
appError "Failed to update config file: $file"
|
||||
return 1
|
||||
}
|
||||
|
||||
rm -f -- "$tmp"
|
||||
}
|
||||
|
||||
# Get param from config or set via configSet if missing
|
||||
function configGetOrSet() {
|
||||
local file="${1-}"
|
||||
local key="${2-}"
|
||||
local value="${3-}"
|
||||
local current
|
||||
|
||||
current="$(configGet "$file" "$key")" || return 1
|
||||
if [[ -n "$current" ]]; then
|
||||
printf '%s\n' "$current"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ -z "$value" ]]; then
|
||||
appError "Config value not specified: $key"
|
||||
return 1
|
||||
fi
|
||||
|
||||
configSet "$file" "$key" "$value" || return 1
|
||||
printf '%s\n' "$value"
|
||||
}
|
||||
|
||||
# Get param from config or create via configSet (+gen stringRandom if missing value) if missing
|
||||
function configGetOrCreate() {
|
||||
local file="${1-}"
|
||||
local key="${2-}"
|
||||
shift 2 || true
|
||||
|
||||
local value current
|
||||
|
||||
current="$(configGet "$file" "$key")" || return 1
|
||||
if [[ -n "$current" ]]; then
|
||||
printf '%s\n' "$current"
|
||||
return 0
|
||||
fi
|
||||
|
||||
value="$(strRandom "$@")" || {
|
||||
appError "Failed to generate config value: $key"
|
||||
return 1
|
||||
}
|
||||
|
||||
configSet "$file" "$key" "$value" || return 1
|
||||
printf '%s\n' "$value"
|
||||
}
|
||||
|
||||
# Check that no line in a file exceeds the specified maximum length, printing offending lines to stderr.
|
||||
# $1 (file): path to the file to check.
|
||||
# $2 (max): maximum allowed line length in characters.
|
||||
function fileCheckLineLength() {
|
||||
local file="$1"
|
||||
local max="$2"
|
||||
local line len num=0 found=0
|
||||
|
||||
[[ -f "$file" ]] || { appError "File not found: $file"; return 1; }
|
||||
[[ "$max" =~ ^[0-9]+$ ]] || { appError "Invalid max line length: $max"; return 1; }
|
||||
|
||||
while IFS= read -r line || [[ -n $line ]]; do
|
||||
((num++))
|
||||
len=${#line}
|
||||
|
||||
if (( len > max )); then
|
||||
printf 'Line %d exceeds %d characters (%d)\n' "$num" "$max" "$len" >&2
|
||||
found=1
|
||||
fi
|
||||
done < "$file"
|
||||
|
||||
return "$found"
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# ===============================================================================================================
|
||||
# ===============================================================================================================
|
||||
# ===============================================================================================================
|
||||
|
||||
|
||||
# Checking the availability of a file (URL) for download.
|
||||
# Check if a URL is accessible and print the final effective URL on success.
|
||||
# $1 (url): the URL to check.
|
||||
function urlAccessible() {
|
||||
local url="$1" code final
|
||||
if [[ -z "$url" ]]; then
|
||||
appError "URL not specified"
|
||||
return 1
|
||||
fi
|
||||
|
||||
final=$(curl -ksSL --max-redirs 10 --range 0-0 -o /dev/null -w "%{url_effective} %{http_code}" "$url") || return 1
|
||||
code="${final##* }" # http code
|
||||
final="${final% *}" # final URL
|
||||
if [[ "$code" =~ ^[23][0-9]{2}$ ]]; then
|
||||
printf "%s" "$final"
|
||||
return 0
|
||||
fi
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
# Fetch and print the HTTP status code for the given URL.
|
||||
# $1 (url): the URL to request.
|
||||
function urlCode() {
|
||||
local url="$1" code
|
||||
if [[ -z "$url" ]]; then
|
||||
appError "URL not specified"
|
||||
return 1
|
||||
fi
|
||||
|
||||
code=$(curl -ksSL --max-redirs 10 -o /dev/null -w "%{http_code}" "$url") || return 1
|
||||
printf "%s" "$code"
|
||||
return 0
|
||||
}
|
||||
|
||||
|
||||
|
||||
# Derive a local filename from a URL, optionally using a custom base name.
|
||||
# $1 (url): the source URL to extract the filename from.
|
||||
# [$2] (localFileName): custom base name; if given, the URL extension is appended to it.
|
||||
function urlLocalFileGen() {
|
||||
local url="$1" code
|
||||
if [[ -z "$url" ]]; then
|
||||
appError "URL not specified"
|
||||
return 1
|
||||
fi
|
||||
|
||||
local localFileName="$2"
|
||||
|
||||
name="${url##*/}"
|
||||
name="${name%%\?*}"
|
||||
base="${name%%.*}"
|
||||
ext="${name#*.}"
|
||||
|
||||
if [[ -z "$localFileName" ]]; then
|
||||
printf '%s' "$name"
|
||||
else
|
||||
printf '%s' "$localFileName.$ext"
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# DEPRECATED
|
||||
# Retrieves a list of files in an FTP directory along with their sizes (in ftpPath).
|
||||
#
|
||||
# $1 (assoc): An associative array where file names and their sizes will be saved.
|
||||
# $2 (path): The path to the directory on the FTP server.
|
||||
#
|
||||
# If a file is a directory, its size is set to "-1". If it's a regular file, its size is saved.
|
||||
function ftpEntrySizeList() {
|
||||
local -n assoc=$1
|
||||
local path="$2"
|
||||
|
||||
if ! run output error curl -sS -u "$ftpUser:$ftpPass" "ftp://$ftpHost:$ftpPort$ftpPath$path/" --connect-timeout 10; then
|
||||
appError "$error"
|
||||
return 1
|
||||
fi
|
||||
|
||||
local line file size
|
||||
while IFS= read -r line; do
|
||||
file=$(echo "$line" | awk '{print $NF}')
|
||||
size=$(echo "$line" | awk '{print $5}')
|
||||
if [[ -n "$file" ]] && [[ "$line" =~ ^d.* ]]; then
|
||||
assoc["$file"]="-1"
|
||||
elif [[ -n "$file" ]] && [[ -n "$size" ]]; then
|
||||
assoc["$file"]="$size"
|
||||
fi
|
||||
done <<< "$output"
|
||||
}
|
||||
|
||||
# DEPRECATED
|
||||
# Retrieves a list of files and their sizes from a remote directory via SSH (in sshPath).
|
||||
#
|
||||
# $1 (assoc): An associative array where file names and their sizes will be saved.
|
||||
# $2 (path): The path to the remote directory where file sizes need to be retrieved.
|
||||
function sshEntrySizeList() {
|
||||
local -n assoc=$1
|
||||
local path="$2"
|
||||
|
||||
if ! run output error ssh -i "$sshKeyFile" "$sshUser@$sshHost" "du -ab --max-depth=1 $sshPath$path"; then
|
||||
appError "$error"
|
||||
return 1
|
||||
fi
|
||||
output=$(echo "$output" | grep -v "[[:space:]]\+$sshPath$path$")
|
||||
|
||||
local size file
|
||||
while IFS=$'\t' read -r size file; do
|
||||
file=$(basename "$file")
|
||||
if [[ -n "$file" && -n "$size" ]]; then
|
||||
assoc["$file"]="$size"
|
||||
fi
|
||||
done <<< "$output"
|
||||
}
|
||||
|
||||
# DEPRECATED
|
||||
# Retrieves a list of files and their sizes in a specified directory on extended storage.
|
||||
#
|
||||
# $1 (assoc): An associative array where file names and their sizes will be saved.
|
||||
# $2 (path): The path to the local directory where file sizes need to be retrieved.
|
||||
function storageEntrySizeList() {
|
||||
local -A storageFunc=(
|
||||
["ftp"]=ftpEntrySizeList
|
||||
["rsync"]=ftpEntrySizeList
|
||||
["ssh"]=sshEntrySizeList
|
||||
)
|
||||
if [[ -z "${storageFunc[$storageType]}" ]]; then
|
||||
appError "Unknown value storageType: $storageType"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! run output error "${storageFunc[$storageType]}" "$@"; then
|
||||
appError "$error"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# DEPRECATED
|
||||
# Retrieves a list of files and their sizes in a specified local directory (in backupPath).
|
||||
#
|
||||
# $1 (assoc): An associative array where file names and their sizes will be saved.
|
||||
# $2 (path): The path to the local directory where file sizes need to be retrieved.
|
||||
function backupEntrySizeList() {
|
||||
local -n assoc=$1
|
||||
local path="$2"
|
||||
|
||||
if ! run output error du -ab --max-depth=1 "$backupDailyPath$path"; then
|
||||
appError "$error"
|
||||
return 1
|
||||
fi
|
||||
local entryList
|
||||
entryList=$(echo "$output" | grep -v "[[:space:]]\+$backupDailyPath$path$")
|
||||
|
||||
local file size
|
||||
while IFS=$'\t' read -r size file; do
|
||||
file=$(basename "$file")
|
||||
if [[ -n "$file" && -n "$size" ]]; then
|
||||
assoc["$file"]="$size"
|
||||
fi
|
||||
done <<< "$entryList"
|
||||
}
|
||||
|
||||
|
||||
# DEPRECATED
|
||||
# List entries in a backup daily directory path.
|
||||
# $1 (path): sub-path within backupDailyPath to list.
|
||||
# [$2] (type): entry type filter (f: files, d: directories).
|
||||
function backupEntryList() {
|
||||
if ! run output error fileList "$backupDailyPath$1" "$2"; then
|
||||
appError "$error"
|
||||
return 1
|
||||
fi
|
||||
|
||||
printf '%s\n' "$output"
|
||||
}
|
||||
|
||||
function fileSignatureDiffList() {
|
||||
local path="$1" type="$2" mask="$3"
|
||||
if [[ -z "$path" || -z "$type" || -z "$mask" ]]; then
|
||||
printDanger "fileSignatureDiffList: missing argument(s)"
|
||||
return 1
|
||||
fi
|
||||
if [[ ! -d "$path" ]]; then
|
||||
printDanger "fileSignatureDiffList: path not found: $path"
|
||||
return 1
|
||||
fi
|
||||
|
||||
find "$path" -type "$type" -printf '%m:%u:%g:%p\n' 2>/dev/null | grep -vE "$mask:"
|
||||
return 0
|
||||
}
|
||||
|
||||
function fileSignatureDiff() {
|
||||
local path="$1" mask="$2" sign
|
||||
[[ -n "$path" && -n "$mask" ]] || { printDanger "Missing argument(s)"; return 1; }
|
||||
[[ -d "$path" ]] || { printDanger "Path not found: $path"; return 1; }
|
||||
|
||||
sign="$(stat -c '%a:%U:%G' "$path")"
|
||||
[[ "$sign" == "$mask" ]] || printf "%s\n" "$sign:$path";
|
||||
}
|
||||
|
||||
function fileSignatureAclDiff() {
|
||||
local path="$1" mask="$2"
|
||||
[[ -n "$path" && -n "$mask" ]] || { printDanger "Missing argument(s)"; return 1; }
|
||||
[[ -d "$path" ]] || { printDanger "Path not found: $path"; return 1; }
|
||||
|
||||
local acl unexpected
|
||||
acl=$(getfacl -p "$path" 2>/dev/null)
|
||||
unexpected=$(grep -vE "^(#|\$|(default:)?((user|group|mask)::|other::---|$mask\$))" <<< "$acl" | paste -sd '|')
|
||||
|
||||
grep -qxF "$mask" <<< "$acl" || unexpected+="${unexpected:+|}missing:$mask"
|
||||
grep -qxF "default:$mask" <<< "$acl" || unexpected+="${unexpected:+|}missing:default:$mask"
|
||||
|
||||
[[ -z "$unexpected" ]] || printf "%s\n" "$unexpected:$path"
|
||||
}
|
||||
|
||||
function fileSignatureCheck() {
|
||||
local output error
|
||||
run output error fileSignatureDiff "$@" || return 1
|
||||
[[ -z "$output" ]]
|
||||
}
|
||||
|
||||
function fileSignatureAclCheck() {
|
||||
local output error
|
||||
run output error fileSignatureAclDiff "$@" || return 1
|
||||
[[ -z "$output" ]]
|
||||
}
|
||||
Reference in New Issue
Block a user