Python's os.chmod behaves differently on Linux vs Windows

Issue

I do have a question for the community, from which I will either learn something new about Windows and Linux, or it will result in a Python bug.

I am trying to set the permissions of a file to be readable by the user only. I am using the os and stat standard libraries in order to avoid operating system dependency.

Now, when I run the command

os.chmod("foo", stat.S_IRUSR)

and check the permissions afterwards, I expect it to end with 0400. In Linux, that is the case:

In [4]: os.chmod('foo', stat.S_IRUSR)

In [5]: oct(os.stat('foo').st_mode)
Out[5]: '0o100400'

But on Windows, I am getting

In [5]: os.chmod("foo", stat.S_IRUSR)

In [6]: oct(os.stat("foo").st_mode)
Out[6]: '0o100444'

I.e. read permissions for the group and public as well.

Now, either this is a but in Python, or I am hitting some edge case scenario between Windows and Linux. However, there are ways in Windows to set a file to be readable only by the owner, so that seems to be odd. I will include the full ipython sessions below for completeness. Help on this one is appreciated.

Windows

Python 3.10.5 (tags/v3.10.5:f377153, Jun  6 2022, 16:14:13) [MSC v.1929 64 bit (AMD64)]
Type 'copyright', 'credits' or 'license' for more information
IPython 8.4.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]: import os

In [2]: import stat

In [3]: os.stat("foo")
Out[3]: os.stat_result(st_mode=33206, st_ino=2533274790432494, st_dev=1682859993, st_nlink=1, st_uid=0, st_gid=0, st_size=2, st_atime=1657572476, st_mtime=1657572476, st_ctime=1657572476)

In [4]: oct(os.stat("foo").st_mode)
Out[4]: '0o100666'

In [5]: os.chmod("foo", stat.S_IRUSR)

In [6]: oct(os.stat("foo").st_mode)
Out[6]: '0o100444'

In [7]: stat.S_IRUSR
Out[7]: 256

In [8]: oct(_)
Out[8]: '0o400'

Linux/Mac

Python 3.10.5 (main, Jun  6 2022, 18:49:26) [GCC 12.1.0]
Type 'copyright', 'credits' or 'license' for more information
IPython 8.4.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]: import stat

In [2]: import os

In [3]: oct(os.stat('foo').st_mode)
Out[3]: '0o100644'

In [4]: os.chmod('foo', stat.S_IRUSR)

In [5]: oct(os.stat('foo').st_mode)
Out[5]: '0o100400'

In [6]: oct(stat.S_IRUSR)
Out[6]: '0o400'

Solution

Please look at the documentation for os.chmod.

Note Although Windows supports chmod(), you can only set the file’s
read-only flag with it (via the stat.S_IWRITE and stat.S_IREAD
constants or a corresponding integer value). All other bits are
ignored.

Answered By – Frank Yellin

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published