3

This is not a duplicate question.

Assume I have

  1. the full path
  2. to a regular file named target
  3. that might be owned by some other user.
  4. and the environment may be stripped down (busybox with very little enabled)

In a shell script, how can I test whether this file is executable by its owner when I might not be its owner? Imagine that my program's purpose is to check if everything is set up nicely for other things to run (since the environment may have been ruined by other users) and it's looking in a particular directory to make sure the owners of every file have permission to execute their file.

This is a professional context, not homework.

Any solution I will use needs to cover all kinds of old Linux environments that I had no hand in setting up (so they could be missing things you'd normally expect like which or some options on find etc).

However, this question might be useful for others who don't face that limitation so I do appreciate other solutions that require more complete or modern environments.

[ -x "$path" ] only tells me if I can execute it.

ls -l "$path" and checking if the fourth character is x seems too fragile: -rwxrw-rw- 1 otheruser group 26 Jun 13 10:57 target

ls -F "$path" and checking if it ends in * seems a little better: target* The one environment I tested does take into account who the actual owner is... But this does not feel like the best way...

mrflash818
  • 930
  • 13
  • 24
user1011471
  • 1,090
  • 2
  • 14
  • 34
  • What if the fs is mounted noexec? This will prevent a user from executing a file regardless of its permissions. – that other guy Jun 13 '18 at 20:02
  • Possible duplicate of [How to check if a program exists from a Bash script?](https://stackoverflow.com/q/592620/608639), [How to check if command exists in a shell script?](https://stackoverflow.com/q/7522712/608639), [Check if a file is executable](https://stackoverflow.com/q/10319652/608639), [How to check if a file is executable in Bash](https://stackoverflow.com/q/42633413/608639), [How to check if command is available or existant?](https://stackoverflow.com/q/7222674/608639), etc. – jww Jun 14 '18 at 00:29
  • I've edited to make it clear this is not a duplicate of any of those. (My reason for ruling out `[ -x "$path" ]` was technically enough to distinguish, I think) My program is a validator and it wants to make sure the owner of each file in a directory is executable by that specific owner. I don't think groups count because I dropped user permissions on something I owned that had (my) group and other x set and I couldn't execute it. Not homework. Needs to be robust and handle all kinds of strange/old Linux environments. – user1011471 Jun 14 '18 at 17:28

3 Answers3

4
permissions=$(stat -c "%a" target)
permissions=$(( ${permissions: -3: 1} % 2 ))

stat gives you file permissions in octal. Then we need just the character for the owner's permissions (technically third from the right, not the first character), and then need to check if it's odd (executable in octal is the 1 bit).

If permissions is 1, it's executable by the owner. If it's 0, it's not.

Older environments might require arithmetic expressions instead:

permissions=$(stat -c "%a" $target)
if [ $((0$permissions & 0100)) -ne 0 ]; then
    # executable by owner
else
    # not executable by owner
fi
jeremysprofile
  • 10,028
  • 4
  • 33
  • 53
  • @thatotherguy, Is that taking a sub-string of val starting at `3` characters from the right end? If so, isn't the next argument the length and should that be a `1` instead of a `-2`? Or ... what am I mistaken about when it comes to that `-2`? – user1011471 Jun 14 '18 at 18:55
  • @user1011471, you could try testing the code yourself and verifying that it works. – jeremysprofile Jun 14 '18 at 19:20
  • @user1011471 http://wiki.bash-hackers.org/syntax/pe#negative_length_value – jeremysprofile Jun 14 '18 at 21:20
  • Oh. "This works since Bash 4.2-alpha" In one my later edits to the OP, I mention needing to support some crazy old environments, in which case `1` would be better, right? – user1011471 Jun 14 '18 at 21:21
  • @user1011471, yes. I believe that the negative offset might not even work in sufficiently old versions of bash (but I could be wrong on that, I couldn't find a source to back up that feeling) – jeremysprofile Jun 14 '18 at 21:35
  • If you add `1` as an alternative that works on older machines, I'll accept this answer. It's what I ended up using. – user1011471 Jun 14 '18 at 22:54
  • @user1011471, changed. 1 is correct either way so it doesn't really need to be an alternative. – jeremysprofile Jun 14 '18 at 22:57
  • Another alternative would be `if (( 0$val & 0100)); then echo "executable by owner"; fi` – that other guy Jun 15 '18 at 01:45
2

You could use find, if you don't want to parse the output of something:

if find ${path} -prune -perm -u+x | grep -q ''; then
  echo "Executable by owner"
else
  echo "Not executable by owner"
fi

The -perm option let's you check if it's executable by the user (owner) and the -prune option prevents descending in to a directory if ${path} is a directory so we can just check the given path by itself.

Brandon Miller
  • 4,695
  • 1
  • 20
  • 27
0

ls -l "$path" and check the first group of permissions (owner permissions). If there is an x in it then the file is executable by its owner.

Athanasios Emmanouilidis
  • 2,084
  • 3
  • 18
  • 30