rlm@1
|
1 #!/bin/bash
|
rlm@1
|
2 # Copyright (c) 2004 Matthias S. Benkmann <article AT winterdrache DOT de>
|
rlm@1
|
3 # You may do everything with this code except misrepresent its origin.
|
rlm@1
|
4 # PROVIDED `AS IS' WITH ABSOLUTELY NO WARRANTY OF ANY KIND!
|
rlm@1
|
5
|
rlm@1
|
6 #The following list should contain the mount points of all filesystems
|
rlm@1
|
7 #that are to be scanned as a space-separated list within parentheses.
|
rlm@1
|
8 #/ will usually be in this list and if you have /usr
|
rlm@1
|
9 #on a separate partition, it will also be in this list. Other non-special
|
rlm@1
|
10 #filesystems where package users could own files should also be put in this
|
rlm@1
|
11 #list.
|
rlm@1
|
12 #Mount points whose filesystems are special, such as procfs or sysfs must
|
rlm@1
|
13 #not be in this list. While a simple find on those special filesystems should
|
rlm@1
|
14 #be harmless, operations such as "-exec grep something" are NOT SAFE and may
|
rlm@1
|
15 #have HARMFUL SIDE-EFFECTS, especially when performed as root.
|
rlm@1
|
16 fs_to_scan=(/)
|
rlm@1
|
17
|
rlm@1
|
18 #Files with a path prefix found in the following list are ignored.
|
rlm@1
|
19 #This list will usually contain the parent directory of your package users'
|
rlm@1
|
20 #home directories, because normally you don't want to scan those. You can
|
rlm@1
|
21 #also add other directories that will never contain package user files, such
|
rlm@1
|
22 #as /home. This reduces scan time.
|
rlm@1
|
23 #NOTE: The LFS-6.0 book uses a ramfs mounted on /dev and with that setup
|
rlm@1
|
24 #/dev does not need to be in the prune list. But since there is no requirement
|
rlm@1
|
25 #that /dev have its on filesystem it's better to prune it explicitly.
|
rlm@1
|
26 prune_prefixes=(/home /usr/src /dev /tools) #NO TRAILING SLASHES!!!!
|
rlm@1
|
27
|
rlm@1
|
28 if [ $# -lt 1 -o "$1" = "--help" ]; then
|
rlm@1
|
29 echo 1>&2
|
rlm@1
|
30 echo 1>&2 'USAGE: '"${0##*/}"' <user_or_group_name> [<find-commands>]'
|
rlm@1
|
31 echo 1>&2
|
rlm@1
|
32 echo 1>&2 ' If <find-commands> contains no action other than -prune, -print will be'
|
rlm@1
|
33 echo 1>&2 ' executed for all matching files.'
|
rlm@1
|
34 echo 1>&2 ' Entries will be matched if group and/or user equals <user_or_group_name>'
|
rlm@1
|
35 echo 1>&2 ' (numeric UID/GID allowed).'
|
rlm@1
|
36 echo 1>&2 ' All matching entries will be acted on, including device special files, so'
|
rlm@1
|
37 echo 1>&2 ' you should be extra careful with the <find-commands> you provide!'
|
rlm@1
|
38 echo 1>&2
|
rlm@1
|
39 exit 1
|
rlm@1
|
40 fi
|
rlm@1
|
41
|
rlm@1
|
42 #suppress ugly debug output from shell
|
rlm@1
|
43 trap ':' SIGPIPE
|
rlm@1
|
44
|
rlm@1
|
45 ugname="$1"
|
rlm@1
|
46 shift 1 #remove user_or_group_name from argument list
|
rlm@1
|
47
|
rlm@1
|
48 # Recent versions of find issue a warning if "-depth" is listed after a
|
rlm@1
|
49 # non-option argument. To prevent this warning if -depth is passed to
|
rlm@1
|
50 # this script, we pick up the "-depth" argument here to move it to the
|
rlm@1
|
51 # front later on.
|
rlm@1
|
52 depth=""
|
rlm@1
|
53 if [ "_$1" = "_-depth" ]; then
|
rlm@1
|
54 depth=-depth
|
rlm@1
|
55 shift 1
|
rlm@1
|
56 fi
|
rlm@1
|
57
|
rlm@1
|
58 ugmatcher=(-false)
|
rlm@1
|
59 #test if find accepts ugname as a user, and append to ugmatcher if it does
|
rlm@1
|
60 if find / -maxdepth 0 -user "$ugname" >/dev/null 2>&1 ; then
|
rlm@1
|
61 ugmatcher[${#ugmatcher[@]}]="-or"
|
rlm@1
|
62 ugmatcher[${#ugmatcher[@]}]="-user"
|
rlm@1
|
63 ugmatcher[${#ugmatcher[@]}]="$ugname"
|
rlm@1
|
64 fi
|
rlm@1
|
65 #test if find accepts ugname as a group, and append to ugmatcher if it does
|
rlm@1
|
66 if find / -maxdepth 0 -group "$ugname" >/dev/null 2>&1 ; then
|
rlm@1
|
67 ugmatcher[${#ugmatcher[@]}]="-or"
|
rlm@1
|
68 ugmatcher[${#ugmatcher[@]}]="-group"
|
rlm@1
|
69 ugmatcher[${#ugmatcher[@]}]="$ugname"
|
rlm@1
|
70 fi
|
rlm@1
|
71
|
rlm@1
|
72 #if find accepted ugname as neither user nor group, then exit
|
rlm@1
|
73 if [ "${#ugmatcher[@]}" = 1 ]; then
|
rlm@1
|
74 echo 1>&2 'find does not accept `'"$ugname'"' as group or user name'
|
rlm@1
|
75 exit 1
|
rlm@1
|
76 fi
|
rlm@1
|
77
|
rlm@1
|
78 #construct find commands that match the prune_prefixes. Each prefix will be
|
rlm@1
|
79 #matched as -path <prefix> -or -path <prefix>/*
|
rlm@1
|
80 #so that the directory itself and all subdirectories are matched.
|
rlm@1
|
81 y=(\( -false)
|
rlm@1
|
82 for ((i=0; $i<${#prune_prefixes[@]}; i=$i+1))
|
rlm@1
|
83 do
|
rlm@1
|
84 y[${#y[@]}]='-or'
|
rlm@1
|
85 y[${#y[@]}]=-path
|
rlm@1
|
86 y[${#y[@]}]="${prune_prefixes[$i]}"
|
rlm@1
|
87 y[${#y[@]}]='-or'
|
rlm@1
|
88 y[${#y[@]}]=-path
|
rlm@1
|
89 y[${#y[@]}]="${prune_prefixes[$i]}/*"
|
rlm@1
|
90 done
|
rlm@1
|
91 y[${#y[@]}]=')'
|
rlm@1
|
92
|
rlm@1
|
93 #In the following find command, the part
|
rlm@1
|
94 # -not ( ( "${y[@]}" -prune ) -or "${y[@]}" )
|
rlm@1
|
95 #is responsible for preventing the files that match prune_prefixes from
|
rlm@1
|
96 #being processed. The 2nd "${y[@]}" may seem redundant, but it isn't, because
|
rlm@1
|
97 #-prune has no effect and is always false when -depth is used.
|
rlm@1
|
98 #The -true before "$@" ensures that -depth can be passed as only parameter.
|
rlm@1
|
99 find "${fs_to_scan[@]}" $depth -xdev -noleaf \
|
rlm@1
|
100 -not \( \( "${y[@]}" -prune \) -or "${y[@]}" \) \
|
rlm@1
|
101 -and \( "${ugmatcher[@]}" \) -and \( -true "$@" \)
|