#!/bin/bash ################################################################################ # Global variables ################################################################################ MODE="find" ATIME_SEARCH=0 ################################################################################ # Functions ################################################################################ die() { printf '%s\n' "$1" >&2 exit 1 } show_help() { cat << HELP Helper script to search and manage atime and retention settings. Script must be executed on a Special Delete Mount, to bypass the WORM xlator. Usage: $1 [OPTION] Mandatory: -d|--directory DIRECTORY search this directory, can also be a single file Optional: -m|--mode MODE show, find or set (default: ${MODE}) Options for search mode: -a|--atime ATIME search for files with an atime (seconds since epoch) higher than this value -r|--retention RETENTION which retention time to search for. Only works with special delete mounts Options for set mode -n|--new-retention set the new retention/atime. atime will be calculated: trusted.archive_time+new-retention HELP } get_atime_of_file() { stat --format=%X "${1}" 2> /dev/null } get_xattr_of_file() { getfattr --absolute-names --only-values -m "${2}" "${1}" | tr -d '\0' } find_files_with_atime() { while read -r FILE; do ATIME_FILE=$(get_atime_of_file "${FILE}") if [ "${ATIME_FILE}" == "" ]; then continue fi if [ ${ATIME_FILE} -ge ${ATIME_SEARCH} ]; then echo "${FILE}" fi done <<< $(find "${DIRECTORY}" -type f) } find_files_with_retention() { while read -r FILE; do RETENTION_FILE=$(get_xattr_of_file "${FILE}" "trusted.worm.attr" | grep -o '[0-9]\+$') if [ "${RETENTION_FILE}" == "" ]; then continue fi if [ ${RETENTION_FILE} -eq ${RETENTION_SEARCH} ]; then echo "${FILE}" fi done <<< $(find "${DIRECTORY}" -type f) } set_atime() { for FILE in $(find_files_with_retention "${DIRECTORY}" "${RETENTION_SEARCH}"); do if [ -f "${FILE}" ]; then ARCHIVE_TIME=$(get_xattr_of_file "${FILE}" "trusted.archive_time") NEW_ATIME=$((ARCHIVE_TIME+NEW_RETENTION)) #echo touch -a --date=@${NEW_ATIME} "${FILE}" touch -a --date=@${NEW_ATIME} "${FILE}" fi done } show_atime_retention() { while read -r FILE; do ATIME=$(get_atime_of_file "${FILE}") if [ "${ATIME}" == "" ]; then continue fi TRUSTED_WORM_ATTR=$(get_xattr_of_file "${FILE}" "trusted.worm.attr" | grep -o '[0-9]\+$') echo "${FILE}" echo " atime: $(date --date=@${ATIME}) || ${ATIME}" echo " trusted.worm.attr: ${TRUSTED_WORM_ATTR}" done <<< $(find "${DIRECTORY}" -type f) } ################################################################################ # Argument parser ################################################################################ while :; do case $1 in -h|-\?|--help) show_help # Display a usage synopsis. exit ;; -a|--atime) # Takes an option argument; ensure it has been specified. if [ "$2" ]; then ATIME_SEARCH=$2 shift else die 'ERROR: "-a|--atime" requires a non-empty option argument.' fi ;; -d|--directory) # Takes an option argument; ensure it has been specified. if [ "$2" ]; then DIRECTORY=$2 shift else die 'ERROR: "-d|--directory" requires a non-empty option argument.' fi ;; -r|--retention) # Takes an option argument; ensure it has been specified. if [ "$2" ]; then RETENTION_SEARCH=$2 shift else die 'ERROR: "-r|--retention" requires a non-empty option argument.' fi ;; -m|--mode) # Takes an option argument; ensure it has been specified. if [ "$2" ]; then MODE=$2 shift else die 'ERROR: "-m|--mode" requires a non-empty option argument.' fi ;; -n|--new-retention) # Takes an option argument; ensure it has been specified. if [ "$2" ]; then NEW_RETENTION=$2 shift else die 'ERROR: "-n|--new-retention" requires a non-empty option argument.' fi ;; --) # End of all options. shift break ;; *) # Default case: No more options, so break out of the loop. break esac shift done ################################################################################ # Main, main, main ################################################################################ if [ "${DIRECTORY}" == "" ]; then show_help exit 0 fi OPER_MODE="${MODE}" if [ "${OPER_MODE}" == "show" ]; then show_atime_retention "${DIRECTORY}" elif [ "${OPER_MODE}" == "find" ]; then if [ "${RETENTION_SEARCH}" != "" ]; then find_files_with_retention else find_files_with_atime fi elif [ "${OPER_MODE}" == "set" ]; then # Some panic checks.. if [ ! -e "${DIRECTORY}" ]; then echo "${DIRECTORY} is not existent. Will exit now..." exit 1 fi if [ "${RETENTION_SEARCH}" == "" ]; then echo "RETENTION_SEARCH is not set. Cowardly refusing to continue..." exit 1 fi if [ "${NEW_RETENTION}" == "" ]; then echo "NEW_RETENTION is not set. Cowardly refusing to continue..." exit 1 fi # Finally set the new atime set_atime "${DIRECTORY}" "${RETENTION_SEARCH}" fi