PetrZ
Dabbler
- Joined
- Feb 23, 2018
- Messages
- 20
I didn't found simple way to set ACLs using provided tools, so I wrote basic script.
Feel free to use it, but there is no guarantee. :)
It is using bash and I run it with redirected stderr:
./acl_set.sh 2>error.log
Feel free to use it, but there is no guarantee. :)
It is using bash and I run it with redirected stderr:
./acl_set.sh 2>error.log
Code:
#!/usr/bin/env bash
export ROOT_DIR="/mnt/DATA"
ACL_RW_FILE='rw-p-daARWc---:-------:allow';
ACL_RW_DIR='rwxp-daARWc---:fd-----:allow';
ACL_RO_FILE='r-----a-R-c---:-------:allow';
ACL_RO_DIR='r-x---a-R-c---:fd-----:allow';
# ACLs set by winacl as default will be deleted
read -r -d '' ACL_DEL_FILE <<'ACL'
group@:rwxpDdaARWcCos:------I:allow
everyone@:r-x---a-R-c---:------I:allow
ACL
read -r -d '' ACL_DEL_DIR <<'ACL'
group@:rwxpDdaARWcCos:fd----I:allow
everyone@:r-x---a-R-c---:fd----I:allow
ACL
CUR_DIR=`pwd`
# In case of harld links, setfacl fails as already
# removed ACLs can not be removed again. Therefore
# it is needed to check if we can skip this error.
function acl_check {
TYPE="${1}"
OBJ="${2}"
# check if delete was done already
if [[ ! -z "$(getfacl "${OBJ}" | grep -E $(cut -d':' -f1 "/tmp/acl_delete_${TYPE}.def" | sed -e 's/^\(.*\)$/(\1)|/' | tr -d "\n" | sed -e 's/\(.*\)|/\1/'))" ]]; then
return 1;
fi
# check if add was done already
if [[ -z "$(getfacl "${OBJ}" | grep -Eoz $(sed -e 's/$/\\s*/g' /tmp/acl_add.def | tr -d "\n" | sed -e 's/\(.*\)\\s\*/\1/'))" ]]; then
return 1;
fi
return 0
}
# Set ACL for single file / dir
function acl_set {
TYPE="${1}"
DIR="${2}"
FILE="${3}"
set +e
{ ERR=$(setfacl -h -M "/tmp/acl_add.def" -X "/tmp/acl_delete_${TYPE}.def" "${DIR}/${FILE}" 2>&1 1>&$out); } {out}>&1;
STATUS=$?;
set -e
# Check if error is "skippable", log to stderr
if [ $STATUS -ne 0 ]; then
printf "Set ACL for %s failed, check ACL" "${FILE}" >&2
if acl_check "${TYPE}" "${DIR}/${FILE}"; then
echo ... passed >&2
else
echo ... failed >&2
echo Command: setfacl -h -M "/tmp/acl_add.def" -X "/tmp/acl_delete_${TYPE}.def" "${FILE}" >&2
echo Result: "${ERR}" >&2
ERR_COUNT=$(( ERR_COUNT + 1))
return 1
fi
fi
}
# Set ACLs recursively. When single is not empty, apply without recursive.
# type d|f, acl rule, dir, single
function acl_walk {
TYPE="${1}"
ACL="${2}"
DIR="${3}"
SINGLE="${4}"
# Write ACLs to be added
printf "${ACL}" >/tmp/acl_add.def
cd "${DIR}"
if [[ "${TYPE}" == "d" ]]; then
acl_set "${TYPE}" "${DIR}" ""
fi
if [[ ! -z "${SINGLE}" ]]; then
return 0;
fi
TOTAL=$(find . -type "${TYPE}" ! -name . ! -name .windows | wc -l)
COUNT=0
find . -type "${TYPE}" ! -name . ! -name .windows -print0 | while IFS= read -r -d '' FILE; do
COUNT=$(( COUNT + 1))
printf '\r%9d / %d, Errors %d' "${COUNT}" "${TOTAL}" "${ERR_COUNT}"
acl_set "${TYPE}" "${DIR}" "${FILE}"
done
echo
}
# Print count of detected errors on exit
function errors {
printf '\nDetected %d errors\n' "${ERR_COUNT}"
}
set -e
ERR_COUNT=0
trap errors EXIT
echo "${ACL_DEL_FILE}" >/tmp/acl_delete_f.def
echo "${ACL_DEL_DIR}" >/tmp/acl_delete_d.def
# I use it this way
echo "Set owner and default for whole share"
winacl -O root -G wheel -a reset -r -p "${ROOT_DIR}/your_share"
echo "Set RO for Employer for your_share top level"
acl_walk d "group:Employer:${ACL_RO_DIR}" "${ROOT_DIR}/your_share" single
echo "Set RW for Employer for following subfolders"
for sub in Public General Misc; do
echo " /${sub} - directories"
acl_walk d "group:Employer:${ACL_RW_DIR}" "${ROOT_DIR}/your_share/${sub}"
echo " /${sub} - files"
acl_walk f "group:Employer:${ACL_RW_FILE}" "${ROOT_DIR}/your_share/${sub}"
done
echo "Set RW for Finances for Accounts"
echo " - directories"
acl_walk d "group:Finances:${ACL_RW_DIR}" "${ROOT_DIR}/your_share/Accounts"
echo " - files"
acl_walk f "group:Finances:${ACL_RW_FILE}" "${ROOT_DIR}/your_share/Accounts"
# Other share will have RO and RW for different groups
echo "Set owner and default for whole other_share"
winacl -O root -G wheel -a reset -r -p "${ROOT_DIR}/other_share"
echo "Set RO for Media and Mediamanagement for other_share top level"
acl_walk d "group:Media:${ACL_RO_DIR}\ngroup:Mediamanagement:${ACL_RO_DIR}" "${ROOT_DIR}/other_share" single
echo "Set RO for Media, RW for Mediamanagement for following subfolders"
for sub in Documents Video Photos; do
echo " /${sub} - directories"
acl_walk d "group:Media:${ACL_RO_DIR}\ngroup:Mediamanagement:${ACL_RW_DIR}" "${ROOT_DIR}/other_share/${sub}"
echo " /${sub} - files"
acl_walk f "group:Media:${ACL_RO_FILE}\ngroup:Mediamanagement:${ACL_RW_FILE}" "${ROOT_DIR}/other_share/${sub}"
done
echo "Set RW for Media and Mediamanagement for UPLOAD"
echo " - directories"
acl_walk d "group:Media:${ACL_RW_DIR}\ngroup:Mediamanagement:${ACL_RW_DIR}" "${ROOT_DIR}/other_share/UPLOAD"
echo " - files"
acl_walk f "group:Media:${ACL_RW_FILE}\ngroup:Mediamanagement:${ACL_RW_FILE}" "${ROOT_DIR}/other_share/UPLOAD"
cd "${CUR_DIR}"
Last edited: