2

使用 NT 原生函数,可以使用create 选项NtCreateFile按 id 打开文件。FILE_OPEN_BY_FILE_ID但是,这样做DELETE似乎会忽略访问标志。如果我设置它,文件将正常打开,但任何删除或重命名文件的尝试都会失败(例如,通过设置FILE_DELETE_ON_CLOSE或使用FILE_RENAME_INFORMATION带有 的类NtSetInformationFile)。

以这种方式打开的文件无法删除吗?有没有其他方法可以通过 id 而不是 name 删除文件?

4

2 回答 2

3

除了 RbMm 的回答之外,我还发现了 Alex Carp 的博客文章,使用 ID 打开的文件的一些限制,解释了这样做的理由。

不幸的是,由 ID 打开的文件的语义与相同文件的语义略有不同,如果它们是按名称打开的。例如,文件名命名空间允许文件有多个名称(硬链接),而 ID 命名空间则不允许。不同命名空间的不同语义可以使某些操作没有意义。

例如,因为 NTFS 允许文件使用多个名称,如果文件是按 ID 打开的,并且尝试更改名称空间的操作,应该影响哪个名称?为了明确这一点,如果文件 \Foo\f.txt 和文件 \Bar\b.txt 是同一个文件的硬链接,并且我通过 ID 打开文件并尝试重命名它,应该更改哪个名称?如果我尝试删除呢?

简而言之,在 NTFS 模型中删除文件实际上意味着删除对文件的引用(也称为名称)。只有在删除所有对它的引用后,作为副作用,文件本身才能被删除。很像许多编程语言中的引用计数。

假设有一个操作需要一个文件 ID 并删除所有引用以及文件,但这将是一个非常不同的操作并且可能很棘手(例如,它需要对所有受影响的文件名执行权限检查,等待所有相关的句柄关闭,防止新文件名引用被删除的文件等)。因此,在这方面,它不存在也就不足为奇了。

于 2019-10-13T16:06:37.417 回答
2

我寻找 ntfs-4 源代码并查看说下一个代码NtfsSetRenameInfo

//
//  Do a quick check that the caller is allowed to do the rename.
//  The opener must have opened the main data stream by name and this can't be
//  a system file.
//

if (!FlagOn( Ccb->Flags, CCB_FLAG_OPEN_AS_FILE ) ||
    (Lcb == NULL) ||
    (NtfsSegmentNumber( &Fcb->FileReference ) < FIRST_USER_FILE_NUMBER)) {

    DebugTrace( -1, Dbg, ("NtfsSetRenameInfo:  Exit -> %08lx\n", STATUS_INVALID_PARAMETER) );
    return STATUS_INVALID_PARAMETER;
}

FileDispositionInformationFILE_DELETE_ON_CLOSE选项(1)的情况相同

    if (FlagOn( Ccb->Flags, CCB_FLAG_DELETE_ON_CLOSE )) {

        if (FlagOn( Ccb->Flags, CCB_FLAG_OPEN_AS_FILE )) {

因此,如果未在文件中设置,由于某种原因 ntfs 不允许重命名或删除CCB_FLAG_OPEN_AS_FILE文件。(id打开文件时不设置)

于 2019-10-13T14:54:32.427 回答