rlm@1: #!/bin/bash rlm@1: # Copyright (c) 2004 Matthias S. Benkmann
rlm@1: # You may do everything with this code except misrepresent its origin. rlm@1: # PROVIDED `AS IS' WITH ABSOLUTELY NO WARRANTY OF ANY KIND! rlm@1: rlm@1: #The following list should contain the mount points of all filesystems rlm@1: #that are to be scanned as a space-separated list within parentheses. rlm@1: #/ will usually be in this list and if you have /usr rlm@1: #on a separate partition, it will also be in this list. Other non-special rlm@1: #filesystems where package users could own files should also be put in this rlm@1: #list. rlm@1: #Mount points whose filesystems are special, such as procfs or sysfs must rlm@1: #not be in this list. While a simple find on those special filesystems should rlm@1: #be harmless, operations such as "-exec grep something" are NOT SAFE and may rlm@1: #have HARMFUL SIDE-EFFECTS, especially when performed as root. rlm@1: fs_to_scan=(/) rlm@1: rlm@1: #Files with a path prefix found in the following list are ignored. rlm@1: #This list will usually contain the parent directory of your package users' rlm@1: #home directories, because normally you don't want to scan those. You can rlm@1: #also add other directories that will never contain package user files, such rlm@1: #as /home. This reduces scan time. rlm@1: #NOTE: The LFS-6.0 book uses a ramfs mounted on /dev and with that setup rlm@1: #/dev does not need to be in the prune list. But since there is no requirement rlm@1: #that /dev have its on filesystem it's better to prune it explicitly. rlm@1: prune_prefixes=(/home /usr/src /dev /tools) #NO TRAILING SLASHES!!!! rlm@1: rlm@1: if [ $# -lt 1 -o "$1" = "--help" ]; then rlm@1: echo 1>&2 rlm@1: echo 1>&2 'USAGE: '"${0##*/}"' []' rlm@1: echo 1>&2 rlm@1: echo 1>&2 ' If contains no action other than -prune, -print will be' rlm@1: echo 1>&2 ' executed for all matching files.' rlm@1: echo 1>&2 ' Entries will be matched if group and/or user equals ' rlm@1: echo 1>&2 ' (numeric UID/GID allowed).' rlm@1: echo 1>&2 ' All matching entries will be acted on, including device special files, so' rlm@1: echo 1>&2 ' you should be extra careful with the you provide!' rlm@1: echo 1>&2 rlm@1: exit 1 rlm@1: fi rlm@1: rlm@1: #suppress ugly debug output from shell rlm@1: trap ':' SIGPIPE rlm@1: rlm@1: ugname="$1" rlm@1: shift 1 #remove user_or_group_name from argument list rlm@1: rlm@1: # Recent versions of find issue a warning if "-depth" is listed after a rlm@1: # non-option argument. To prevent this warning if -depth is passed to rlm@1: # this script, we pick up the "-depth" argument here to move it to the rlm@1: # front later on. rlm@1: depth="" rlm@1: if [ "_$1" = "_-depth" ]; then rlm@1: depth=-depth rlm@1: shift 1 rlm@1: fi rlm@1: rlm@1: ugmatcher=(-false) rlm@1: #test if find accepts ugname as a user, and append to ugmatcher if it does rlm@1: if find / -maxdepth 0 -user "$ugname" >/dev/null 2>&1 ; then rlm@1: ugmatcher[${#ugmatcher[@]}]="-or" rlm@1: ugmatcher[${#ugmatcher[@]}]="-user" rlm@1: ugmatcher[${#ugmatcher[@]}]="$ugname" rlm@1: fi rlm@1: #test if find accepts ugname as a group, and append to ugmatcher if it does rlm@1: if find / -maxdepth 0 -group "$ugname" >/dev/null 2>&1 ; then rlm@1: ugmatcher[${#ugmatcher[@]}]="-or" rlm@1: ugmatcher[${#ugmatcher[@]}]="-group" rlm@1: ugmatcher[${#ugmatcher[@]}]="$ugname" rlm@1: fi rlm@1: rlm@1: #if find accepted ugname as neither user nor group, then exit rlm@1: if [ "${#ugmatcher[@]}" = 1 ]; then rlm@1: echo 1>&2 'find does not accept `'"$ugname'"' as group or user name' rlm@1: exit 1 rlm@1: fi rlm@1: rlm@1: #construct find commands that match the prune_prefixes. Each prefix will be rlm@1: #matched as -path -or -path /* rlm@1: #so that the directory itself and all subdirectories are matched. rlm@1: y=(\( -false) rlm@1: for ((i=0; $i<${#prune_prefixes[@]}; i=$i+1)) rlm@1: do rlm@1: y[${#y[@]}]='-or' rlm@1: y[${#y[@]}]=-path rlm@1: y[${#y[@]}]="${prune_prefixes[$i]}" rlm@1: y[${#y[@]}]='-or' rlm@1: y[${#y[@]}]=-path rlm@1: y[${#y[@]}]="${prune_prefixes[$i]}/*" rlm@1: done rlm@1: y[${#y[@]}]=')' rlm@1: rlm@1: #In the following find command, the part rlm@1: # -not ( ( "${y[@]}" -prune ) -or "${y[@]}" ) rlm@1: #is responsible for preventing the files that match prune_prefixes from rlm@1: #being processed. The 2nd "${y[@]}" may seem redundant, but it isn't, because rlm@1: #-prune has no effect and is always false when -depth is used. rlm@1: #The -true before "$@" ensures that -depth can be passed as only parameter. rlm@1: find "${fs_to_scan[@]}" $depth -xdev -noleaf \ rlm@1: -not \( \( "${y[@]}" -prune \) -or "${y[@]}" \) \ rlm@1: -and \( "${ugmatcher[@]}" \) -and \( -true "$@" \)