#!/bin/bash
+# Original...
# Copyright (c) 2000,2004 Matthias S. Benkmann <article AT winterdrache DOT de>
# You may do everything with this code except misrepresent its origin.
# PROVIDED `AS IS' WITH ABSOLUTELY NO WARRANTY OF ANY KIND!
+# Copyright (C) 2014 Steve Youngs <steve@steveyoungs.com>
+# Rewrite, make it a lot more robost and handle most (all?)
+# possibilities of chown'ing. --SY.
+
DAISY_CHAIN=""
for p in $(type -ap chown) ; do
done
if [ ! -n "$DAISY_CHAIN" ]; then
- echo Cannot find real ${0##*/} command
+ echo 1>&2 '***' Cannot find real ${0##*/} command
+ exit 1
+fi
+
+if [ $(id -u) == 0 ]; then
+ echo 1>&2 '***' $(dirname $0) should not be in root\'s \$PATH
+ echo 1>&2 '***' call '"'$DAISY_CHAIN $@'"' directly.
exit 1
fi
-if [ $UID == 0 ]; then
- exec $DAISY_CHAIN "$@"
+# An ordinary user cannot change the UID of a file if that UID is
+# not their own, but chown can also be used to change the GID of a
+# file as well so it is feasible that an ordinary user could use
+# chown successfully.
+
+# preseve the command line as we're gonna mess with it.
+cmdline="$@"
+# strip off the options so that $1 becomes the UID:GID arg
+while [ -n "$1" ]; do
+ case "$1" in
+ (-*) shift ;;
+ (*) break ;;
+ esac
+done
+
+# Split USER:GROUP or USER.GROUP into USER and GROUP
+usrgrp="$1"
+usr=${usrgrp/[.:]*/}
+grp=${usrgrp/*[.:]/}
+
+report=0
+
+# Catch the case where USER is somebody else.
+if [ -n "$usr" ]; then
+ printf '%d' "$usr" &>/dev/null
+ if [ $? -eq 0 ]; then
+ if [ $usr -ne $(id -u) ]; then
+ report=1
+ fi
+ else
+ if [ "$usr" != "$(id -un)" ]; then
+ report=1
+ fi
+ fi
+fi
+
+# Catch the case where GROUP isn't in our groups.
+if [ -n "$grp" -a $report -eq 0 ]; then
+ GRP_CHAIN=""
+ printf '%d' "$grp" &>/dev/null
+ if [ $? -eq 0 ]; then
+ GRP_LIST=$(id -G)
+ else
+ GRP_LIST=$(id -Gn)
+ fi
+ for g in ${GRP_LIST}; do
+ if [ "$grp" == "$g" ]; then
+ GRP_CHAIN=$g
+ break
+ fi
+ done
+
+ if [ -z "$GRP_CHAIN" ]; then
+ report=1
+ fi
fi
-if [ "$1" == "root.root" ]; then
- echo 1>&2 '***' chown "$@"
+if [ $report -eq 1 ]; then
+ echo 1>&2 '***' chown ${cmdline}
else
- $DAISY_CHAIN "$@" || exit $?
+ $DAISY_CHAIN ${cmdline} || exit $?
fi
exit 0
+
+# Local variables:
+# sh-basic-offset: 4
+# End: