如何通过具有删除访问权限的 id 打开文件?



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

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

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

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

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

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

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

我查找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 -> %08lxn", 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 )) {

因此,NTF由于某种原因不允许重命名或删除文件,如果未在文件上设置CCB_FLAG_OPEN_AS_FILE。(当文件由ID打开时未设置(

最新更新