Keeping your Home file permissions correct

I have been a UNIX user for a long time, and in that time I have been looking for a program to set/reset all the file permissions of a complex directory hierarchy (my home) according to a configuration file of rules.

That is not the simple find-xargs-chmod rule but a program (shell/perl/c) that reads a configuration file that defines the file permissions over my whole home, and keeps them in order.

For example the top level directory of my home is accessable and readable.
This allows other users to grab and used scripts i have written (and they do), the web server to access my public_html directory. But it also means most of my other files must be kept 'closed' to others. Especially 'dot' files.

More importantly it only changes a file permissions if those permissions are wrong, so that the file does not get incrementally backed up all the time.

I have a 'kludge' script solution I have used for years, and it works well, but the exceptions to the script is a pain, and I am sure others have also had this problem. As such I want to see what is out there!

Googling only ever seems to find 'novice' reset individual file, or whole directory type solutions. Never 'set by config' solutions.

Does anyone out there know such solutions?

Can you post an example of configuration file you are using ?

Regards
Peasant.

I fear you have a lot of work coming your way - with the upside being that it is real *interesting* work. :wink:

As you want to use a configuration file you will have to write a generic script. You need:

  • A function "SetFileMode( filename, filemode )" to set the permission for a single file/directory. It will get a single file name, set the file mode and return a success/failure flag.
  • A function "GetFileMode( filename, rulefilename )" which gets a single file/directory name and figures out which permission to apply. It will do so by reading and interpreting some rule (=configuration) file. This function will call the SetPermission() routine then (or not at all if no rules apply).

    (Because these two functions get the same "filename" parameter it looks like they could be combined into one. In principle this is possible but i wouldn't do so - different tasks should be in different routines.)

    There has to be some error handling for syntax errors in the configuration file and a return value which reflects that.
  • A function to traverse the (part of the) file system. It will call GetFileMode() and SetFileMode() then to find out and set the permissions. This function will also have to process return values of SetFileMode() and GetFileMode().

    It should stop if GetFileMode() returns non-TRUE, which will mean an error in the config file and you don't want to repeat this error for every single file over and over.
  • A main() function to do the rest - parse the command line arguments, etc.

Let us have a look at the configuration syntax. This is basically the logic you put into GetFileMode(), which will be a little parser. You want it rule-based, so basically a "rule" would be some file glob and a (part of the) permission set which should be set. For example:

*abc        rwx------
*def*       ???rw----

This should mean: every file/directory ending in "abc" will get filemode 700 set. Every file/dir with a "def" in it will have the group and world permissions set to 60 and the owner permissions left as they are.

We also need to clarify what should happen in case of contradictory rules. Should the first overrule the last or vice versa or should the "more open" overrule the more restrictive one or should it be the other way round? You will simply have to decide about it and then put either logic into GetFileMode().

You might also want some logic to restrict a rule to either files or directories. You will need some syntax for this in your rule file. For instance:

[f]*abc        rwx------
[d]*def*       ???rw----
*ghi*          ??????r-x

The first rule applies only to files, the second only to directories. You will have to decide how you want the third rule to be processed: for both files and directories? Neither? Only for files (or directories) as default? Consider it an syntax error in the configuration file?

You might also want a way to restrict rules based on the depth. If you start in "/some/dir" you might want to apply a certain rule to "/some/dir/*" but not any further, like "/some/dir/below/that". You need some syntax for this, like:

[d1]*abc*       rwx------
[d3]*def*       ???r-x---

The first rule will apply only to directories in your starting directory. The second rule will apply to these and their sub- and sub-sub-directories.

Things ommitted: You will definitely want to use comments in your config file syntax, because you will want to document your rules - you said they are "complex" and therefore you will want some notes to remind you what you thought when you wrote them. You will also have to take care of the sticky bits (which i left out for clarity). Further, you might want to think over the allowed file globs themselves: i have only used "*" in my examples but the shell allows a lot more.

I hope this helps.

bakunin

</br></br>
I am basically looking to see what software is out there.</br></br>

As such any configuration is suitable. Just something that can set file permissions of everything in a directory (and sub-directories), with exceptions. </br></br>

My current method uses a configuration file with two types of lines (non-comment) only...

# Configuration Lines are of the form...
#   Directory/         dir_perms  exec_perms  files_perms  [R]
#   Filename                      permission
#
# Permissions are specified in octal for example '700', '755', '644'
# The special permission '---' means to ignore (don't change) permissions
#
# A directory entry sets not only the directory but the default permissions
# for that directories contents, it will not progress further downward into
# sub-directories unless a 'R' recurse flag is also given.
#
# If you want to make the directory itself different its its contents, you
# need to specify a specific  'Filename' which always overrides a directory
# entry.  As such to open your home directory, but close permissions of
# all files and sub-directories by default, you need to use two lines..
#
#        ./           700   700   600
#        .            755
#

The problems I have with my current method is that while I can set exceptions, for specific files (such as for the home directory itself as above). I can't do it generally.

That is I can make an exception for say "bin/file.dat" (a data file in a directly predominantly executables) I can't make it general "bin/.dat" or recursivally general "bin/**/.dat"

I am simply looking for a better solution!

---------- Post updated at 05:23 PM ---------- Previous update was at 05:08 PM ----------

Something like you describe is exactly right, and it is very interesting.

I have even made something like this (see config summery above), but it does not work well, especially for various types of exceptions. Like a specific suffix in a sub-directory.

I searched for solutions to this but it does not really have any good search keys for find such solutions. So I finally decided to ask if anyone has seen something like this.

Some similar problems exist for things like rsync and unison, but they only look at whether to include or exclude a specific file based on patterns, and from my experience of using them, I found them to have serious problems. In any case file permissions need more than just a boolean selection.

This type of problem must have been looked at many times, either with file permissions, or with just file selection (for backup/replication) and I'd like to fine something that actually works!

This is basically a matter of correct parsing of the configuration file. I suppose you can probably solve most problems by applying the following algorithm:

First sort all entries in the configuration by "length" - that is: by the number of subdirectory levels they contain. Then, within the levels, sort the entries simply alphabetically. Apply now the rules to every file from top down.

This way you will automatically apply all the exceptions correctly, because the "shorter" rules for a specific path will be applied before the longer ones. You can have every number of exceptions this way.

I hope this helps.

bakunin