mkdir not setting permissions correctly

Viewed 149

I am trying to make a directory that has the "set group ID on execution" set in Python

In the shell:

$ mkdir --mode 2775 mail
$ ls -ld mail
drwxrwsr-x 1 john john 0 May  3 08:34 mail
      ^

In Python I am using pathlib.Path.mkdir, and it seems there some bits for mode are not taken into account, even when the umask is cleared:

from pathlib import Path
import os

os.umask(0)
md = Path('mail')
md.mkdir(mode=0o2775)    

drwxrwxr-x 1 john john 0 May  3 08:35 mail
       ^

Is there some cut-off at nine bits that is not documented

2 Answers

Ultimately, on non-Windows systems, Path.mkdir calls os.mkdir which in turn invokes the C system call mkdirat. That call's behavior is defined in terms of mkdir, which, on Linux, documents the mode with:

The argument mode specifies the permissions to use. It is modified by the process's umask in the usual way: the permissions of the created directory are (mode & ~umask & 0777)

Note that the permissions explicitly mask off all bits above 0777; this is just how mkdir system calls behave on some OSes. You'll just have to chmod it after the fact.

pathlib's mkdir essentially just calls os.mkdir(). The documentation there includes the section:

On some systems, mode is ignored. Where it is used, the current umask value is first masked out. If bits other than the last 9 (i.e. the last 3 digits of the octal representation of the mode) are set, their meaning is platform-dependent. On some platforms, they are ignored and you should call chmod() explicitly to set them.

So only the last 9 bits are guaranteed to be used. You'll have to do (no need to set umask):

md.mkdir()
md.chmod(0o2775)

It would be better if pathlib would not silently ignore extra bits, but actually threw a ValueError.

Related