#!/usr/bin/env bash # Variables declared in dreport, expected to be set before sourcing this file declare -x name_dir declare -x dump_size declare -x dreport_log declare -x summary_log declare -x quiet declare -x verbose # Source dreport configuration (generated at build time) if [ -f /usr/share/dreport.d/dreport.conf ]; then # shellcheck source=/dev/null source /usr/share/dreport.d/dreport.conf fi # Set compression flags based on algorithm case "${DUMP_COMPRESSION:-xz}" in xz) TAR_COMPRESS_FLAG="-J" ARCHIVE_EXT="tar.xz" ;; gzip) TAR_COMPRESS_FLAG="-z" ARCHIVE_EXT="tar.gz" ;; zstd) TAR_COMPRESS_FLAG="" ARCHIVE_EXT="tar.zst" ;; *) TAR_COMPRESS_FLAG="-J" ARCHIVE_EXT="tar.xz" ;; esac # @brief Create a compressed tar archive # @param $1 Output file path (without extension) # @param $2 Source directory (parent dir for -C) # @param $3 Base name to archive # @return Sets ARCHIVE_PATH to the created archive path function create_archive() { local output_base="$1" local src_dir="$2" local base_name="$3" local archive_file="${output_base}.${ARCHIVE_EXT}" case "${DUMP_COMPRESSION:-xz}" in zstd) tar -cf - -C "$src_dir" "$base_name" | zstd > "$archive_file" ;; *) tar ${TAR_COMPRESS_FLAG} -cf "$archive_file" -C "$src_dir" "$base_name" ;; esac ARCHIVE_PATH="$archive_file" } # @brief Execute the command and save the output into the dreport # packaging, if it is in the user allowed dump size limit. # @param $1 Command to be executed. # @param $2 Save file name. # @param $3 Plugin description used for logging. function add_cmd_output() { command="$1" file_name="$2" desc="$3" if ! eval "$command" >> "$name_dir/$file_name"; then log_error "Failed to collect $desc" rm -f "$name_dir/$file_name" return 1 fi if check_size "$name_dir/$file_name"; then log_info "Collected $desc" else log_warning "Skipping $desc" fi } # @brief Copy the file or directory into the dreport packaging, # if it is in the user allowed dump size limit. # @param $1 Copy file or directory name. # @param $2 Plugin description used for logging. function add_copy_file() { file_name="$1" desc="$2" if ! cp -Lr "$file_name" "$name_dir"; then log_error "Failed to copy $desc $file_name" # file_name is not empty, otherwise cp would have failed rm -fr "${name_dir:?}/$file_name" return "$RESOURCE_UNAVAILABLE" fi if check_size "$name_dir/$(basename "$file_name")"; then log_info "Copied $desc $file_name" return "$SUCCESS" else log_warning "Skipping copy $desc $file_name" return "$RESOURCE_UNAVAILABLE" fi } # @brief Copy the symbolic link file to the dreport packaging, # if it is in the user allowed dump size limit. # @param $1 symbolic link file name # @param $2 Plugin description used for logging. function add_copy_sym_link_file() { file_name="$1" desc="$2" if ! cp "$file_name" "$name_dir"; then log_error "Failed to copy $desc $file_name" # file_name is not empty, otherwise cp would have failed rm -fr "${name_dir:?}/$file_name" return "$RESOURCE_UNAVAILABLE" fi if check_size "$name_dir/$(basename "$file_name")"; then log_info "Copied $desc $file_name" return "$SUCCESS" else log_warning "Skipping copy $desc $file_name" return "$RESOURCE_UNAVAILABLE" fi } # @brief Calculate file or directory compressed size based on input # and check whether the size in the allowed size limit. # Remove the file or directory from the name_dir # if the check fails. # @param $1 Source file or directory # @return 0 on success, error code if size exceeds the limit. # Limitation: compress and tar will have few bytes size difference function check_size() { source=$1 #No size check required in case dump_size is set to unlimited if [ "$dump_size" = "$UNLIMITED" ]; then return 0 fi #get the file or directory size if [[ -d $source ]] && [[ -n $source ]]; then tar -cf "$source.tar" -C \ "$(dirname "$source")" "$(basename "$source")" size=$(stat -c%s "$source.tar") rm "$source.tar" else size=$(stat -c%s "$source") fi if [ $((size + cur_dump_size)) -gt "$dump_size" ]; then #Exceed the allowed limit, #tar and compress the files and check the size create_archive "$name_dir" "$(dirname "$name_dir")" "$(basename "$name_dir")" size=$(stat -c%s "$ARCHIVE_PATH") if [ "$size" -gt "$dump_size" ]; then #Remove the the specific data from the name_dir and continue rm "$source" "$ARCHIVE_PATH" return "$RESOURCE_UNAVAILABLE" else rm "$ARCHIVE_PATH" fi fi cur_dump_size=$((size + cur_dump_size)) return "$SUCCESS" } # @brief log the error message # @param error message function log_error() { echo "$($TIME_STAMP)" "ERROR: $*" >> "$dreport_log" if ((quiet != TRUE)); then echo "$($TIME_STAMP)" "ERROR: $*" >&2 fi } # @brief log warning message # @param warning message function log_warning() { if ((verbose == TRUE)); then echo "$($TIME_STAMP)" "WARNING: $*" >> "$dreport_log" if ((quiet != TRUE)); then echo "$($TIME_STAMP)" "WARNING: $*" >&2 fi fi } # @brief log info message # @param info message function log_info() { if ((verbose == TRUE)); then echo "$($TIME_STAMP)" "INFO: $*" >> "$dreport_log" if ((quiet != TRUE)); then echo "$($TIME_STAMP)" "INFO: $*" >&1 fi fi } # @brief log summary message # @param message function log_summary() { echo "$($TIME_STAMP)" "$*" >> "$summary_log" if ((quiet != TRUE)); then echo "$($TIME_STAMP)" "$*" >&1 fi }