How to set default permissions for files moved or copied to a directory?

My question is similar to How to set the default file permissions on ALL newly created files in linux - but differs in important ways:

I want all files created in (or copied to or moved to) a certain directory to inherit a set of default permissions that is different from the system default.

Rationale: The directory in question is the "intake hopper" for an application. Users in a group place files in the directory, and the app (running under another user id in the same group) takes them and processes them. The problem is that the owner of each file placed in the directory is the user that placed it there, and the permissions are defaulting to "rw-r--r--"; I want to change that to "rw-rw----". The app doing the intake can't do that explicitly, because the user id the app is running under doesn't own the file in question, and the default permissions don't allow the app to chmod on the file! Obviously, the user could do a chmod after putting the file there - but I want to keep the "drop" by the user as simple as possible. (These folks are not linux-literate, they just drag and drop the files from their windows desktop to a (Samba) network share - i.e. they don't even know they are interacting with a linux system.)

umask seems too powerful: I don't want to set default permissions for every file created anywhere by these users - just those created in (or placed in) this directory.

Please advise... thanks!


Solution 1:

You can use an ACL (access control list) to set the default permissions for files in a directory.

From man 5 acl:

If a default ACL is associated with a directory, the mode parameter to the functions creating file objects and the default ACL of the directory are used to determine the ACL of the new object:

  1. The new object inherits the default ACL of the containing directory as its access ACL.

  2. The access ACL entries corresponding to the file permission bits are modified so that they contain no permissions that are not contained in the permissions specified by the mode parameter.

To set it up (change device, directories, etc., accordingly):

Edit your /etc/fstab file and add the acl mount option.

/dev/mapper/star-home /home ext3  defaults,acl 0 2

Remount (Samba mount.cifs man page) your filesystem by rebooting or use:

mount -o remount,acl /home

Make sure you have the setfacl and getfacl utilities.

Set the default ACL on the directory (you may also need to set the ACL on existing files):

$ setfacl -m d:user:george:rwx,d:group:sales-g:rwx,d:group:marketing-g:rwx projections

See the linked tutorial for more information.

Source: Tutorial Part 1 and Part 2

Reference: POSIX Access Control Lists on Linux

Solution 2:

I can offer a workaround: Make a separate "drop" directory, run a separate minijob there that fixes the permissions and then moves the files into the application's data directory. You can use incron for that so there would be virtually no noticeable time delay.

Solution 3:

I can think of four possible methods of doing this:

  • umask, which you do not wish to use
  • program wrapper, which sets that application's umask, not the user's
  • cron, as @Peter Eisentraut described; find $HOME/intake -type f -exec chmod 660 {} \;, different systems have performance improvements on this (like the -exec+ option)
  • directory based settings, which require a little bit of shell programming to do, but basically the shell, on setting the prompt or calling cd, would change the umask if there is a dot file present in that directory (or possibly an ancestor directory); for bash, PROMPT_COMMAND='test -s $PWD/.umask && umask $(cat $PWD/.umask)'";$PROMPT_COMMAND" would be the most simple.