ensure filesystem permissions with configuration files

a configuration file format and evaluator implementation for specifying and setting filesystem permissions. a bit like css for filesystem permissions


programs, copied files and remote users working on a system sometimes create new files with incorrect permissions and modify the permissions of existing files. if there are no regular automatic checks and fixes to keep desired filesystem permissions, the security of the system is at risk and processes that need specific permissions might stop working. for the purpose of ensuring filesystem permissions, writing shell scripts that use the chown, chmod, setfacl, find and similar utilities is much more cumbersome, unclear, error prone and harder to maintain than necessary


  • nested paths
  • user/group/other and acl permissions
  • file-type specific permissions
  • setting owner and group
  • automatic executable bit for directories if the read permission is set
  • globbing with a child selector "", recursive/descendants selector "", and "." ".**" for including the starting path
  • path production
  • dry-run option that displays shell commands
  • permission specifiers can be shortened, like just "r" or "rw,r::groupname"
  • list and string support for acl specifiers
  • no support for octal notation


permission configuration file with almost all features mixed:

  (file-type regular default-user (nonroot rw) user (testuser rw http r) group (http rw) other r)
  ("temp/documents/*" (acl file-type directory "d:u:1000:rwx"))
  (("modules" "tests") "rwx,rw::git"))

same with comments

  ;restriction on directories. sets permissions, user and group
  ;acl as a key/value list
  (file-type regular default-user (nonroot rw) user (testuser rw http r) group (http rw) other r)
    ;an alternative acl notation as a key/value list and string as would be used with "setfacl"
    (acl file-type directory "d:u:1000:rwx"))
  ;matches any of the listed file names
  (("modules" "tests") "rwx,rw::git"))

more practical example

; matches all ".git" directories under "/home/testuser"
("/home/testuser/**/.git" "rw:nonroot:git")

command-line program

$ fs-perm-set --help

  options ... specifier path paths ...
  --help | -h

usage examples

$ cat my-fs-config | fs-perm-set --dry-run
$ fs-perm-set --config-file=my-fs-config
$ fs-perm-set rw,r:testuser testpath testpath/**
$ fs-perm-set --acl u:testuser:rw testpath-1 testpath-2
$ fs-perm-set rwx,rw:nonroot /usr/share/guile/site/2.2/ice-9/* --dry-run
chown 1000:-1 "/usr/share/guile/site/2.2/ice-9/match-phd-lookup.scm"
chmod 760 "/usr/share/guile/site/2.2/ice-9/match-phd-lookup.scm"
chown 1000:-1 "/usr/share/guile/site/2.2/ice-9/match-phd.scm"
chmod 760 "/usr/share/guile/site/2.2/ice-9/match-phd.scm"
chown 1000:-1 "/usr/share/guile/site/2.2/ice-9/set"
chmod 770 "/usr/share/guile/site/2.2/ice-9/set"
chown 1000:-1 "/usr/share/guile/site/2.2/ice-9/vset.scm"
chmod 760 "/usr/share/guile/site/2.2/ice-9/vset.scm"

configuration file syntax

  • file-name: {valid filesystem file name character} ...
  • path: ["/"] file-name///./.** ["/" path] ...
  • perm-name: "r"/"w"/"x"
  • perm: perm-name [perm-name [perm-name]]
  • ugo-perm: perm ["," perm ["," perm]]
  • acl-specifier: ([symbol:key symbol/string:value])/(acl [symbol:key any:value] ... string [symbol:key any:value] ...)
  • rule: (string:path/(string:path ...) string:ugo-specifier/acl-specifier ... rule ...)



why no support for octal notation?

if both octal and rwx notation would be supported, it would occur mixed and make usage inconsistent and the configuration slightly more complicated because you need to know/learn the semantics of both. is any one of those notations better? octal notation is shorter (i usually prefer it on the command-line), but specific to only three permission types where it has to be known which octal value stands for which permission. rwx is more generic and the characters hint at the name of the permission. in this program not all three (user, group, other) parts have to be specified, in short the benefits should be consistency and clearer notation (write-once read-often) through the use of characters instead of integers


  • download fs-perm from releases or clone from git://git.sph.mn/fs-perm
  • extract the downloaded archive
  • link or copy the files exe/fs-perm-set into a directory which is in the environment variable $PATH
  • link or copy the files modules/* into a directory which is in the environment variable $GUILE_LOAD_PATH or any other guile load path
  • adjust file system permissions eventually

module name

(sph fs-perm config)