2
\$\begingroup\$

I wrote a simple script to set permissions for a file or folder for some embedded Linux devices as part of a larger setup script.

This method would be called on less than 20 files and folders. It seems to work correctly. For the Linux OS, the stat command is not available. Please let me know if anyone notices any issue or knows of a better way to set and check file and folder permissions.

Thanks.

# Runs 'chmod' command to set folder or file permissions.
# Uses 'find' command with permission parameter to verify
# the file or folder exists with the permissions that 
# were set.
#  Param1 = NumericPermission. Param2 = File/Folder path.
set_permissions()
{
local text
chmod $1 $2 
text="$(find $2 -maxdepth 0 -perm $1)"
if [ -e $2 ]; then    
    if [ -n "$( echo $text | grep $2)" ]; then
        PermissionResult=$PASSED
        echo "Permissions set."
    else
        PermissionResult=$FAILED        
        printf " Permissions for '$2' not correctly set.\n" >> $SETUP_LOG 
    fi
else
    printf " Path not found for '$2'.\n" >> $SETUP_LOG
fi
}

#Usage:
local file='/home/testfile'
printf "test file" > $file 
set_permissions 777 $file
\$\endgroup\$
2

2 Answers 2

3
\$\begingroup\$

It's worth a trip through Shellcheck, as there are some standard mistakes here, notably failing to quote strings such as "$1" or "$PASSED" - though the latter is probably a mistake, since PASSED is never assigned (I recommend set -u to catch use of undefined variables).

It seems silly to interpolate strings into the format string for printf (and it's risky, if those strings might contain % or \). The obvious solution is to use %s for the argument, though you could instead interpolate and use echo or printf '%s\n'.

Also, is "$2" expected to expand to a filename or to a regular expression? It's unlikely to be a good argument to both find and grep simultaneously.

Given that we actually only care whether find produced some output or not, then we could easily just grep for a non-empty line:

    if find "$2" -maxdepth 0 -perm "$1" 2>/dev/null | grep -q .
    then
        echo "Permissions set."
        return 0
    else
        printf " Permissions for '%s' not correctly set.\n" "$2" |
            tee -a "$SETUP_LOG" >&2
        return 1
    fi

It's not clear what this script aims to provide that's not provided by plain chmod, which will leave the file untouched if permissions are already as desired.

\$\endgroup\$
6
  • \$\begingroup\$ Thanks for the feedback. I added quotes around the param. strings and added the %s format for printf. I know about making recursive calls (chmod -R) but the files and folders are not all in the same location. \$\endgroup\$
    – netcat
    May 23, 2023 at 17:21
  • \$\begingroup\$ Also, this will only be used where the second string argument is always the file path, so no regular expressions are used. \$\endgroup\$
    – netcat
    May 23, 2023 at 17:24
  • 1
    \$\begingroup\$ Sorry, I missed the -maxdepth 0 - I think find is overkill for a simple stat test. And none of your path names will ever contain any of []\?*. or other regex characters? You're lucky - on my systems, . at least occurs quite frequently in filenames. Perhaps you wanted grep -F, but that still has chance of false positive. \$\endgroup\$ May 23, 2023 at 17:39
  • \$\begingroup\$ Yeah I wish I could use stat but this is on devices with embedded Linux with very limited versions of Linux; stat is not available. \$\endgroup\$
    – netcat
    May 23, 2023 at 18:09
  • \$\begingroup\$ No, none of the files will ever contain any invalid characters. This is part of a setup script for devices that my team configures and we control the entire process. \$\endgroup\$
    – netcat
    May 23, 2023 at 18:41
2
\$\begingroup\$

Steps:

  1. verify that the file indeed exists
  2. retrieve the current permissions and compare them to the expected value

The output of the Linux find command can be customized. Thus:

find /path/to/file -printf "%m\n"

will return the octal permissions for a given file eg 644 or 755 etc. The exit code will be != 0 if the file doesn't exist.

Likewise, you could return with an exit code > 0 if the check does not succeed. This will make it possible for any caller routine (or the rest of your installation script) to determine the outcome of the command and behave accordingly.

Also, to log the output of your script, you could run something like this at the start of your script:

exec &> >(tee -a "$SETUP_LOG")  # for stdout and stderr

so that there is no need to pipe or tee in every command. Source

Google Linux file redirection for more details.

\$\endgroup\$
6
  • \$\begingroup\$ Thanks for the info. Unfortunately our versions of LInux find do not support the -printf option for find. We are already using the &> operator to log all activity and errors, but we have another app. that reads and parses specific log entries after setup, so we need another log file that has less info with a specific format. \$\endgroup\$
    – netcat
    May 26, 2023 at 16:03
  • \$\begingroup\$ Can you mention the version of Linux you're using for your embedded device? Unless it's proprietary you can probably build your own customized image but I understand this may be a hassle. \$\endgroup\$
    – Kate
    May 26, 2023 at 17:02
  • \$\begingroup\$ ~ $>uname -a Linux [manufacturer redacted]_2070LX 2.6.39 #2 PREEMPT Mon Aug 1 15:51:52 CDT 2016 ppc GNU/Linux ~ $> \$\endgroup\$
    – netcat
    May 30, 2023 at 12:13
  • \$\begingroup\$ There are 4 different Linux versions depending on the manufacturer. The Linux distros are very lightweight. \$\endgroup\$
    – netcat
    May 30, 2023 at 12:15
  • \$\begingroup\$ Customized versions of Linux would likely void the warranties. We discussed this a while back and opted not to make our own. \$\endgroup\$
    – netcat
    May 30, 2023 at 12:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.