linuxbashfilesystemsfile-permissionsext4

How to detect if a filesystem supports permissions?


Recently I ran into an issue when my script extracts temporary files via tar to a folder choosen by the user.

The problem was that if that folder was on a USB stick with exfat filesystem, the extracted files loose the permission information that ext4 and btrfs filesystems store with each file.

To solve this I created the following fix:

#!/usr/bin/env bash

FOLDER="/example"
FS=$(stat -f -c %T "$FOLDER")

if [[ "$FS" == "fat"* || "$FS" == "vfat"* || "$FS" == "exfat"* || "$FS" == "ntfs"* || "$FS" == "fuse"* || "$FS" == "msdos"* ]]; then
  echo "Unsupported filesystem!"
  exit
fi

While this works, it requires me to keep a list of which filesystems are incompatible with ext4 permissions, and I'm sure my list is far from complete. Because there exist dozens of exotic filesystems that may have the same issue.

So is there a better way to test if a folder supports permissions without actually having to write a file first? And if not, what filesystems should I add to this list to make it more complete?


Solution

  • Might be ok to check if one can change write permission and make it a function:

    #!/usr/bin/env sh
    
    # Checks path support changing write permissions
    # @args
    #     $1: The path to check (mandatory)
    # @return
    #     0: Allow changing write permission
    #     1: Does not allow changing write permission
    #     2: Cannot perform the check
    canChangeWritePermission() {
        [ -d "${1:?}" ] || return 2
        __cCWP_tmpFile=$(TMPDIR=$1 mktemp) || return 2
    
        if
            chmod -w "$__cCWP_tmpFile" && ! [ -w "$__cCWP_tmpFile" ] &&
            chmod +w "$__cCWP_tmpFile" && [ -w "$__cCWP_tmpFile" ]
            then rc=0
            else rc=1
        fi
        rm -f -- "$__cCWP_tmpFile"
        return $rc
    }
    
    if canChangeWritePermission "${1:?}" 2>/dev/null
    then printf '%s has support for changing write permission.\n' "$1"
    elif [ $? -eq 1 ]
        then printf '%s does not allow changing write permission.\n' "$1"
        else printf 'Cannot check %s\n' "$1" >&2
    fi