Skip to content

Instantly share code, notes, and snippets.

@azat
Last active August 27, 2018 16:33
Show Gist options
  • Select an option

  • Save azat/3bdddd02f5f3291d112068517ffe5dec to your computer and use it in GitHub Desktop.

Select an option

Save azat/3bdddd02f5f3291d112068517ffe5dec to your computer and use it in GitHub Desktop.
#1/usr/bin/env bash
declare -A opts
function print_usage()
{
cat <<EOL
NAME:
$0 -- restore files for existing process using procfs.
-p - pid
-P - pattern (bash regex)
-d - dry run
-n - no clobber
-h - print help
BUGS:
- Tested on linux 4.8 (for "deleted" keyword in proc symlink).
- It uses cat(1) for this, and yes it is very suboptimal.
EOL
}
function check_pattern() { [[ "$*" =~ (\"|\'\ ) ]] || return 0 && return 1; }
function configure_env()
{
if [[ "${opts[dry_run]}" = 1 ]]; then
function undel() { echo "# UNDEL $*"; }
elif [[ "${opts[no_clobber]}" = 1 ]]; then
function undel()
{
local src="$1" dst="$2"
shift 2 || return 1
[[ $# -gt 0 ]] && return 1
[[ -f "$dst" ]] && {
echo "EEXITS '$dst'" >&2
return 2
}
[[ -L "$src" ]] || return 3
cat "$src" > "$dst"
echo "UNDEL '$dst'"
}
else
function undel()
{
local src="$1" dst="$2"
shift 2 || return 1
cat "$src" > "$dst"
echo "UNDEL '$dst'"
}
fi
export -f undel
}
function parse_opts()
{
local OPTIND OPTARG o
while getopts "P:p:hdn" o; do
case "$o" in
p) opts[pid]="$OPTARG";;
P) opts[pattern]="$OPTARG";;
d) opts[dry_run]=1;;
n) opts[no_clobber]=1;;
h) print_usage; exit 0;;
*) print_usage >& 2; return 1;;
esac
done
check_pattern "${opts[pattern]}" || {
echo "'${opts[pattern]}' is unsafe" >&2
return 2
}
configure_env
}
function check()
{
local fd="$1" pattern="$2"
shift
[[ -n $pattern ]] || return 1
local path="$(readlink -f "$fd")"
[[ "$path" =~ \ \(deleted\)$ ]] || return 0
path="${path%% (deleted)}"
[[ "$path" =~ $pattern ]] || return 0
undel "$fd" "$path"
}
export -f check
function undelete()
{
local pid="$1" pattern="$2"
shift 2
# xargs here because bash is too slow
find "/proc/$pid/fd/" -type l | xargs -P40 -i -n1 bash -c "check {} $pattern"
}
function main()
{
parse_opts "$@" || return
undelete "${opts[pid]}" "${opts[pattern]}"
}
main "$@"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment