summarylogtreecommitdiffstats
path: root/pacman-ps.sh
blob: 41d28d5c73a53a453a31071d89ff2fe9607b002d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#!/usr/bin/env bash
#
# Copyright (C) 2016  Samantha McVey <samantham@posteo.net>
# This file and project are licensed under the GPLv2 or greater at your choice.
# For more information view the license included or visit:
# https://www.gnu.org/licenses/gpl-2.0.html
#
# This script processes the output from ps-lsof which is a two column list, where
# the 1st and 2nd columns must be delimited by spaces. The first column of the
# input is the process name.  The second column is the file. It then compares
# the filename with the file at $DB_FILE which is a two column file delimited
# by spaces, the first column is the name of the package and the second is the
# filename which belongs to the package.

# Help
if [[ "${1}" = "-h" || "${1}" = "--help" ]]; then
	printf "pacman-ps: Shows running process names and the files they still have\n "
	printf "  open that have been changed or removed on disk and the packages which"
	printf " own those packages.\n"
	printf "command line options:\n  -q  quiet: don't print header\n  -s only print"
	printf " out packages and files changed on disk but not process names\n  -h or"
	printf " --help: shows this help\n"
	exit 0
elif [[ ! "${1}" = "-s" &&  ! "${1}" = "-q" && ! "${1}" = "" ]]; then
	printf "Unknown option! Try %s -h or --help to see help!\n" "${0}"
	exit 1
fi
# Function to check if we are using a temp database and if so remove it.
cleanuptemp() {
	if [ "${DB_TEMP_FILE}" = "1" ]; then
		rm "${LIST}"
	fi
}
sortdb() {
	DB_DIR="/var/cache/pacman-ps"
	if [ ! -f "${DB_DIR}/files.db.sorted" ]; then
		if (( "$EUID" != 0 )); then
    	echo "Please run as root or sudo, to process the database."
    	exit 1
		fi
		sort -u -k 2,2 "${DB_DIR}/files.db" > "${DB_DIR}/files.db-"
		rm "${DB_DIR}/files.db"
		mv "${DB_DIR}/files.db-" "${DB_DIR}/files.db"
	  touch "${DB_DIR}/files.db.sorted"
	fi
}
sortdb
DB_FILE="/var/cache/pacman-ps/files.db"
# Get the resolved filename of the currently running script
RUN=$(readlink -f "$0")
# Get the directory name that file is in
RUNDIR=$(dirname "${RUN}")
# If a file called ps-lsof is found in the same directory as pacman-ps use that
if [ -f "${RUNDIR}/ps-lsof" ]; then
	PS_LSOF_CMD="${RUNDIR}/ps-lsof -q"
	#printf "using ps-lsof -q\n"
elif [ -f "${RUNDIR}/ps-lsof.pl" ]; then
	PS_LSOF_CMD="${RUNDIR}/ps-lsof.pl"
	#printf "Using ps-lsof.pl\n"
# Otherwise, if we find a ps-lsof.sh file, use that to call ps-lsof
elif [ -f "${RUNDIR}/ps-lsof.sh" ]; then
	PS_LSOF_CMD="${RUNDIR}/ps-lsof.sh -q"
	#printf "Using ps-lsof.sh -q\n"
else
	echo "Could not find ps-lsof or ps-lsof.sh"
	echo "Make sure it is in the same folder as pacman-ps or pacman-ps.sh"
	exit 1
fi


# Get the output from ps-lsof and sort it so that 'join' will be happy
PS_LSOF_OUTPUT=$(${PS_LSOF_CMD} | sort -k 2,2)
# If ps-lsof doesn't output anything, our work here is done
if [ "${PS_LSOF_OUTPUT}" = "" ]; then
	exit 0
fi

# If we find the database file at $DB_FILE then use that
if [ -f "${DB_FILE}" ]; then
	LIST=${DB_FILE}
else
	# If we can't find it, print out that we are falling back to asking pacman
	# Unless we invoke -q (quiet)
	if [ ! "${1}" = "-q" ]; then
		echo "Could not find ${DB_FILE}"
		echo "Asking pacman for file listing using pacman -Ql"
	fi
	# Get a temp filename
	LIST=$(mktemp)
	trap "cleanuptemp"
	pacman -Ql | sort -u -k 2,2 > "${LIST}"
	DB_TEMP_FILE="1"
fi
# -s option will only print out packages and files but not processes
if [ "${1}" = "-s" ]; then
	$PS_LSOF_CMD | cut -d ' ' -f 2-99 | xargs -I '{}'  grep '{}' "${LIST}" | sort -u | (echo "PROCESS FILENAME"; cat) | column -t
	exit 0
fi

OUTPUT=$(join -j 2 <(printf "%s" "${PS_LSOF_OUTPUT}") <(cut -d ' ' -f 2-99 <(printf "%s" "${PS_LSOF_OUTPUT}") | xargs -P 8 -I '{}'  grep '{}' "${LIST}" | sort -u -k 2,2) )
# If there's no output just cleanup a temp file if there is one and exit
if [ "$OUTPUT" = "" ]; then
	cleanuptemp
	exit 0
fi

if [ "${1}" = "-q" ]; then
	printf "%s\n" "$OUTPUT" | column -t
else
	printf "FILENAME PROCESS PACKAGE\n%s\n" "$OUTPUT" | column -t
fi
cleanuptemp
exit 0