如何通过具有 DELETE 访问权限的 ID 打开文件?

How to open a file by id with DELETE access?

使用 NT 本机函数 NtCreateFile 可以使用 FILE_OPEN_BY_FILE_ID 创建选项按 ID 打开文件。但是,这样做时 DELETE 访问标志似乎被忽略了。如果我设置它,文件将正常打开,但任何删除或重命名文件的尝试都将失败(例如,通过设置 FILE_DELETE_ON_CLOSE 或使用 FILE_RENAME_INFORMATION class 和 NtSetInformationFile)。

用这种方式打开的文件不能删除吗?有没有其他方法可以通过 ID 而不是名称删除文件?

我寻找 ntfs-4 源代码并查看 NtfsSetRenameInfo

中的下一个 code
//
//  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 )) {

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

除了 RbMm 的回答之外,我还找到了 Alex Carp Some Limitations Using Files Opened By ID 的博客 post,其中解释了这样做的基本原理。

Unfortunately the semantics for files opened by ID are a bit different from the semantics of the same files if they would have been opened by name. The file name namespace for example allows multiple names for a file (hardlinks) while the ID namespace does not. The different semantics of the different namespaces can make it so that some operations don't make sense.

For example because NTFS allows multiple names for a file if the file is opened by ID and an operation that changes the namespace is attempted, which name should be affected? To make this very clear, if file \Foo\f.txt and file \Bar\b.txt are hardlinks to the same file and I open the file by ID and I try to rename it, which name should change? How about if I try a delete?

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

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