Behaviour of os.path.join

Roel Schroeven roel at roelschroeven.net
Thu May 28 14:18:01 EDT 2020


Eryk Sun schreef op 28/05/2020 om 15:51:
> On 5/27/20, Chris Angelico <rosuav at gmail.com> wrote:
>> On Thu, May 28, 2020 at 7:07 AM BlindAnagram <blindanagram at nowhere.com>
>> wrote:
>>> You can define a path however you want but it won't change the fact that
>>> on Windows a path that ends in '\\' is inherently a path to a directory.
>>
>> Citation needed.
> 
> See [MS-FSA] 2.1.5.1 Server Requests an Open of a File [1]. Here are
> the relevant statements:
> 
>      The operation MUST be failed with STATUS_OBJECT_NAME_INVALID under
>      any of the following conditions:
>      ....
>        * If PathName contains a trailing backslash and
>          CreateOptions.FILE_NON_DIRECTORY_FILE is TRUE.

i.e. trailing backslashes are not allowed for regular files

>      ....
>      If PathName contains a trailing backslash:
>        * If StreamTypeToOpen is DataStream or
>          CreateOptions.FILE_NON_DIRECTORY_FILE is TRUE, the operation MUST
>          be failed with STATUS_OBJECT_NAME_INVALID

i.e. again, trailing backslashes are not allowed for non-directory files.

There is no limitation listed that says something like "The operation 
must be failed if pathname doesn't contain a trailing backslash and 
CreateOptions.FILE_NON_DIRECTOR_FILE is FALSE". Path names referring to 
directories are allowed to have trailing backslashes, but no requirement 
to do so. Directory PathNames with and without trailing backslashes are 
handled exactly the same.

> Internally, WinAPI CreateFileW calls NTAPI NtCreateFile with the
> create option FILE_NON_DIRECTORY_FILE (i.e. only open or create a data
> file stream), unless backup semantics are requested in order to be
> able to open a directory (i.e. an index stream), in which case the
> call uses neither FILE_NON_DIRECTORY_FILE nor FILE_DIRECTORY_FILE and
> leaves it up to the path name.

No, that is not my understanding. It is up to the actual type of file 
specified by the path. CreateFileW using FILE_FLAG_BACKUP_SEMANTICS  can 
only open existing directories, so there is no need to look at the last 
character of the path.

> In other words, with backup semantics, if you need to ensure that
> only a directory is opened, add a trailing slash.
It's not like you have some random path, you think "hey, I only want to 
open this if it is a directory", and then do

CreateFileW(
   L"...\\...\\",
   ..,
   ...,
   ...,
   ...,
   FILE_FLAG_BACKUP_SEMANTICS,
   NULL);

What happens instead is that you have a path to a real existing object 
(CreateFileW on directories works only with both OPEN_EXISTING and 
FILE_FLAG_BACKUP_SEMANTICS specified: you can not create a directory 
using CreateFileW), and CreateFileW (via NtCreateFile) will open it as a 
directory if the object is a directory, and as a file it is a file. 
Exception is that it will refuse to open it as a file if there's a 
backslash in the end, while for directories backslashes are optional. 
But if you never add a backslash in the end, everything will work just 
fine for both files and directories.

-- 
"Honest criticism is hard to take, particularly from a relative, a
friend, an acquaintance, or a stranger."
         -- Franklin P. Jones

Roel Schroeven



More information about the Python-list mailing list