0

When creating a file or directory, the OS uses a default permission mode based on different sources (OS-default, inherited ACLs, ...?). I want to get the default permissions for a specific directory.

For example, if I create a file /tmp/test.txt, the file has mode 0o644. AFAIK this comes from the default 0o666 permissions of the OS and from the umask 0o22.

A directory /tmp/testdir would start with 0o755 as the default mode is 0o777 and the umask is 0o22.

But is there a way to programmatically get the defaults, all inheritance and the umask to calculate the mode in effect?

I thought about creating a temporary file and a folder in this directory, read the permission flags and delete them. But is there a better way?

# Default file mask = 0o666, no ACL or other, umask = 0o22
get_default_file_mode("/tmp") # should return 0o644
# Default direcoty mask = 0o777
get_default_directory_mode("/tmp") # should return 0o755

Is there a way to achieve this without creating the file and folder explicitly?

(The programming language to be used is not that important)

Michael
  • 2,528
  • 3
  • 21
  • 54

2 Answers2

1

Here is some sample code to obtain the default umask, and from it derive the default mode. This Stack Overflow question was helpful in explaining the meaning of umask (TL;DR: it's the permissions a newly created file or directory should not have).

import os

# Create a temporary umask to apply, which neither grants permissions 
# to others, nor takes away permissions from the user
temp_umask = 0o077

# Obtain the existing default umask by applying the temporary umask.
default_umask = os.umask(temp_umask)

# Immediately reapply the existing default umask
os.umask(default_umask)

print(f'default_umask: {oct(default_umask)}')

# The default mode is the bitwise XOR of 0o777 (full permissions) and
# the default umask.
default_mode = 0o777^default_umask

print(f'default_mode: {oct(default_mode)}')
Josh
  • 126
  • 2
  • 6
0

Using os.stat you can get the file/dir permissions, and then you can calculate the mask from them and the default.

import os
# st_mode give decimal, so we need to get its octal
# the last 3 chars will give the permission
print(oct(os.stat(".").st_mode & 0o777))
# then we can match against default 0o777
print(oct(0o777 - (os.stat(".").st_mode & 0o777)))

This bash version is simpler, run it in the directory of interest, set BASE var to 777 for directory permissions or 666 for file permissions.

BASE="777" MASK="$(umask)" ; printf "base:\t$BASE\numask:\t$MASK\nperms:\t$(($BASE - $MASK))\n"
ljmc
  • 4,830
  • 2
  • 7
  • 26
  • I don't understand how this helps with my problem. Could you explain? – Michael Jan 17 '22 at 11:38
  • Ok, so the defaults you listed are correct, 777 for dir and 666 for file, after that, to get the umask, and if language does not matter which I just read, you can just use `umask` from bash. So by now we have two of the three things you asked, just need to calculate the permissions (base - umask). Let me add a bash version which is simpler. – ljmc Jan 17 '22 at 11:57
  • Also check this for umask questions. https://askubuntu.com/a/44548 – ljmc Jan 17 '22 at 12:00
  • Sorry, that wasn't the point of my question. I don't want to read the mode of a file or folder. I want to get the default mode, when a file or folder will be created. The "777" or "666" is defined somewhere. I'm not sure if this is the same on all systems or if this can change. And AFAIK ACLs can affect the default mode too. – Michael Jan 17 '22 at 12:23