Open a directory on Windows: 'Permission denied'

python, windows

Solution

Edit:

This is not a permission issue, it will never work with Python 2. Python 2 is using the Win 32 API call `_wopen` when doing `os.open()` (code: https://github.com/python/cpython/blob/2.7/Modules/posixmodule.c#L6554). According to the docs, it throws an error when opening a directory:

EACCES Tried to open read-only file for writing, file's sharing mode does not allow specified operations, or given path is directory.

So:

The docs does not indicate you can't nor any platform difference. Is this expected behavior?

It is expected behavior. I would say in this case it is fine that this detail is not clarified in the Python docs.

Is it not possible to get file descriptors for directories on Windows?

On Python 2 you can use the ctypes module for calling arbitrary Win 32 API methods yourself. Python 3 uses `CreateFile` instead of `_wopen`, a more modern API call, which might enable you to do what you want, see below.

Old answer:

The most important resource for this question is the documentation for the CreateFile Win 32 API function, documented here:

http://msdn.microsoft.com/en-us/library/windows/desktop/aa363858%28v=vs.85%29.aspx

You might want to read the relevant parts of it, e.g.

To open a directory using CreateFile, specify the FILE_FLAG_BACKUP_SEMANTICS flag as part of dwFlagsAndAttributes.

Also, there is a comment below the docs, saying

In order to open a handle to a directory you appear to need SYNCHRONIZE access, even if you aren't requesting any access rights. (Note: this doesn't apply if you have backup/restore privilege.)

Python 3 uses this function in several places, you may want to search for yourself

https://github.com/python/cpython/search?q=CreateFile&type=Code

or via git clone and using `grep -HR "CreateFile(" .`. In Python 3, there is the _winapi.c module which is most likely used when doing `os.open()` on Windows.

On Python 2, there is a call to _wopen in https://github.com/python/cpython/blob/2.7/Modules/posixmodule.c#L6554, but I am not sure where this is defined. When you follow this path, you will find the actual implementation. Then you can see how exactly Python is calling that function -- this, together with the docs, will most likely explain your observations.

Problem

I'm trying to get a file descriptor for a directory but calling `os.open` on on directories always result in a "permission denied" error. I do not believe it's a permission issue because it happens on all directories, while there's no issue on files (See REPL session below). Running as administrator makes no difference. ``` Python 2.7.6 (default, Nov 10 2013, 19:24:18) [MSC v.1500 32 bit (Intel)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> import os >>> os.mkdir('mydir') >>> os.access('mydir', os.F_OK) True >>> os.access('mydir', os.R_OK) True >>> os.access('.', os.R_OK) True >>> os.access('.', os.F_OK) True >>> os.open('myfile', os.O_RDWR) 3 >>> os.open('mydir', os.O_RDONLY) Traceback (most recent call last): File "<stdin>", line 1, in <module> OSError: [Errno 13] Permission denied: 'mydir' >>> os.open('mydir', os.O_RDWR) Traceback (most recent call last): File "<stdin>", line 1, in <module> OSError: [Errno 13] Permission denied: 'mydir' >>> open('mydir') Traceback (most recent call last): File "<stdin>", line 1, in <module> IOError: [Errno 13] Permission denied: 'mydir' ``` On linux it works as expected: ``` >>> os.open('mydir', os.O_RDONLY) 3 ``` The docs does not indicate you can't nor any platform difference. Is this expected behavior? Is it not possible to get file descriptors for directories on Windows?

Original source