On 4/5/21, Rami Khaldi <khaldi.r...@gmail.com> wrote: > > It seems that the os.open API cannot distinguish between a permission error > and the fact that a directory cannot be opened like files. > The following script reproduces the scenario (tested on Python 3.8.2 > (tags/v3.8.2:7b3ab59, Feb 25 2020, 22:45:29) [MSC v.1916 32 bit (Intel)] on > win32) :
In Windows, C open() calls WinAPI CreateFileW(), which defaults to opening regular files by default, i.e. it calls the NTAPI NtCreateFile() system function with the option FILE_NON_DIRECTORY_FILE. If the filesystem supports file streams (NTFS, ReFS), then the primary stream in a directory is an index stream of type $INDEX_ALLOCATION. (A directory can also have $DATA streams, but I digress.) An open can override the FILE_NON_DIRECTORY_FILE option by explicitly opening the index stream in the directory. For example: fd = os.open('someDirectory::$INDEX_ALLOCATION', 0) Alternatively, if CreateFileW() is called with the flag FILE_FLAG_BACKUP_SEMANTICS, then it does not use the NtCreateFile() option FILE_NON_DIRECTORY_FILE to limit the open type. This means directories can be opened. If you want to limit this case to just opening directories, add a trailing slash to the name. The Universal C Runtime has an undocumented flag for C open() -- _O_OBTAIN_DIR (0x2000) -- which makes it use the CreateFileW() flag FILE_FLAG_BACKUP_SEMANTICS. So you can also open "someDirectory" in Windows in Python 3.5 and later as follows: fd = os.open('someDirectory', 0x2000) or fd = os.open('someDirectory/', 0x2000) > *Traceback (most recent call last): File "<stdin>", line 1, in > <module>PermissionError: [Errno 13] Permission denied: 'someDirectory'* Unfortunately, there are 4 layers of errors when traversing the APIs involved here: Python <-> C <-> WinAPI <-> NTAPI. Important and helpful details are often lost. When an NtCreateFile() system call fails because an attempt was made to open a directory as a file, the status code explains itself: STATUS_FILE_IS_A_DIRECTORY (0xC00000BA). WinAPI CreateFileW() unhelpfully translates this status code to ERROR_ACCESS_DENIED (5). Finally, C open() translates the Windows error code as EACCES (13). Unfortunately the interpreter doesn't have enough information to know that it should raise IsADirectoryError instead of PermissionError. -- https://mail.python.org/mailman/listinfo/python-list