Filesystems 如何使用“删除”访问权限按id打开文件?

Filesystems 如何使用“删除”访问权限按id打开文件?,filesystems,nt-native-api,Filesystems,Nt Native Api,使用NT本机函数NtCreateFile可以使用file\u open\u by\u file\u idcreate选项按id打开文件。但是,在执行此操作时,DELETEaccess标志似乎被忽略。如果我设置它,文件将正常打开,但任何删除或重命名文件的尝试都将失败(例如,通过设置file\u delete\u ON\u CLOSE或使用file\u rename\u INFORMATION类和NtSetInformationFile) 是否无法删除以这种方式打开的文件?是否有其他方法可以通过id

使用NT本机函数
NtCreateFile
可以使用
file\u open\u by\u file\u id
create选项按id打开文件。但是,在执行此操作时,
DELETE
access标志似乎被忽略。如果我设置它,文件将正常打开,但任何删除或重命名文件的尝试都将失败(例如,通过设置
file\u delete\u ON\u CLOSE
或使用
file\u rename\u INFORMATION
类和
NtSetInformationFile


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

我查找ntfs-4源代码,并在
ntfstrenameinfo中查看say next

//
//  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;
}

因此,如果未在文件上设置
CCB\u FLAG\u OPEN\u AS\u file
,ntfs出于某种原因不允许重命名或删除文件。(当文件由id打开时未设置)

除了RbMm的答案之外,我还找到了Alex Carp的一篇博文,这篇博文解释了这一点的基本原理

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

例如,如果文件是按ID打开的,并且尝试了更改名称空间的操作,则NTFS允许文件具有多个名称,那么哪个名称应受到影响?为了清楚说明这一点,如果file\Foo\f.txt和file\Bar\b.txt是指向同一文件的硬链接,并且我按ID打开该文件并尝试重命名它,那么应该更改哪个名称?如果我尝试删除呢

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


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

hmm..我只是测试我自己-真的文件没有被删除,并且
文件重命名信息上的
状态参数无效-
-所以我从一开始就错了。现在更详细地看一下。是的,我完全错了。ntfs真的不允许idi t打开的raname或删除文件hink你可以在这里问这个问题——删除所有链接的最佳论坛权限不应该是问题。如果句柄具有删除访问权限,则该权限必须由文件上的安全描述符授予,而不是由特定链接父目录上的删除子访问权限授予。此外,还有一组文件属性关于readonly属性。OTOH,共享模式不常见,因此必须全部或全部进行处理。如果由于现有的打开,任何链接上的共享模式都不共享删除访问,则该操作将因共享冲突而失败。
    if (FlagOn( Ccb->Flags, CCB_FLAG_DELETE_ON_CLOSE )) {

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