为什么我不能删除在 ProgramData 中创建的目录?
Why can't I delete a directory created in ProgramData?
我正在尝试创建一个目录,然后将其删除(出于测试目的,我会省略,但如果需要可以提供详细信息)。
像这样:
>>> import os
>>> os.makedirs('C:\ProgramData\dir\test')
>>> os.remove('C:\ProgramData\dir\test')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
PermissionError: [WinError 5] Access is denied: 'C:\ProgramData\dir\test'
尽管我是 运行 作为管理员的口译员,但我总是被拒绝访问。另外我手动删除目录也没问题。
使用os.rmdir
删除目录。在 Windows 上,这是通过调用 WinAPI 函数 RemoveDirectory
. os.remove
is implemented by calling DeleteFile
, which is only meant for deleting files. If the filename argument is a directory, the call fails and it sets the last error code to ERROR_ACCESS_DENIED
实现的,Python 3 为此引发了一个 PermissionError
。
在这种情况下,拒绝访问错误是基于内核、系统进程、服务、环境子系统和应用程序之间的 NTSTATUS
code STATUS_FILE_IS_A_DIRECTORY
, i.e. RtlNtStatusToDosError
(0xC00000BA) == 5
. Often the kernel's status code is more informative than the corresponding WinAPI error, but not always, and there isn't always a simple mapping from one to the other, depending on the division of labor。在这种情况下,我认为内核状态代码无疑比一般的访问被拒绝错误更能提供信息。
在较低级别上,尝试通过 DeleteFile
删除目录时出错的原因是它调用系统服务 NtOpenFile
with the FILE_NON_DIRECTORY_FILE
flag set in OpenOptions
, whereas RemoveDirectory
specifies FILE_DIRECTORY_FILE
. Subsequently both functions call NtSetInformationFile
来设置 FileDispositionInformation
以删除文件或目录。
作为一个逆向投资者,让我们在 NTFS 文件系统上仅使用 file 操作来实现整个序列。
>>> import os, pathlib
>>> base = pathlib.Path(os.environ['ProgramData'])
创建'dir'目录:
>>> dirp = base / 'dir::$INDEX_ALLOCATION'
>>> open(str(dirp), 'w').close()
>>> os.path.isdir(str(dirp))
True
通过手动指定流类型为$INDEX_ALLOCATION
,打开这个'file'实际上创建了一个NTFS目录。顺便说一句,您还可以将多个命名的 $DATA
流添加到 目录 。请参阅 file streams 主题。
接下来创建'test'子目录并调用os.remove
删除它:
>>> test = base / 'dir' / 'test::$INDEX_ALLOCATION'
>>> open(str(test), 'w').close()
>>> os.path.isdir(str(test))
True
>>> os.remove(str(test))
>>> os.path.exists(str(test))
False
您可能会惊讶于这有效。请记住,本例中的文件名明确指定了 $INDEX_ALLOCATION
流。这会否决 FILE_NON_DIRECTORY_FILE
标志。你得到你所要求的。但不要依赖于此,因为这些流是 NTFS 的实现细节,它不是 Windows.
上唯一使用的文件系统
我正在尝试创建一个目录,然后将其删除(出于测试目的,我会省略,但如果需要可以提供详细信息)。
像这样:
>>> import os
>>> os.makedirs('C:\ProgramData\dir\test')
>>> os.remove('C:\ProgramData\dir\test')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
PermissionError: [WinError 5] Access is denied: 'C:\ProgramData\dir\test'
尽管我是 运行 作为管理员的口译员,但我总是被拒绝访问。另外我手动删除目录也没问题。
使用os.rmdir
删除目录。在 Windows 上,这是通过调用 WinAPI 函数 RemoveDirectory
. os.remove
is implemented by calling DeleteFile
, which is only meant for deleting files. If the filename argument is a directory, the call fails and it sets the last error code to ERROR_ACCESS_DENIED
实现的,Python 3 为此引发了一个 PermissionError
。
在这种情况下,拒绝访问错误是基于内核、系统进程、服务、环境子系统和应用程序之间的 NTSTATUS
code STATUS_FILE_IS_A_DIRECTORY
, i.e. RtlNtStatusToDosError
(0xC00000BA) == 5
. Often the kernel's status code is more informative than the corresponding WinAPI error, but not always, and there isn't always a simple mapping from one to the other, depending on the division of labor。在这种情况下,我认为内核状态代码无疑比一般的访问被拒绝错误更能提供信息。
在较低级别上,尝试通过 DeleteFile
删除目录时出错的原因是它调用系统服务 NtOpenFile
with the FILE_NON_DIRECTORY_FILE
flag set in OpenOptions
, whereas RemoveDirectory
specifies FILE_DIRECTORY_FILE
. Subsequently both functions call NtSetInformationFile
来设置 FileDispositionInformation
以删除文件或目录。
作为一个逆向投资者,让我们在 NTFS 文件系统上仅使用 file 操作来实现整个序列。
>>> import os, pathlib
>>> base = pathlib.Path(os.environ['ProgramData'])
创建'dir'目录:
>>> dirp = base / 'dir::$INDEX_ALLOCATION'
>>> open(str(dirp), 'w').close()
>>> os.path.isdir(str(dirp))
True
通过手动指定流类型为$INDEX_ALLOCATION
,打开这个'file'实际上创建了一个NTFS目录。顺便说一句,您还可以将多个命名的 $DATA
流添加到 目录 。请参阅 file streams 主题。
接下来创建'test'子目录并调用os.remove
删除它:
>>> test = base / 'dir' / 'test::$INDEX_ALLOCATION'
>>> open(str(test), 'w').close()
>>> os.path.isdir(str(test))
True
>>> os.remove(str(test))
>>> os.path.exists(str(test))
False
您可能会惊讶于这有效。请记住,本例中的文件名明确指定了 $INDEX_ALLOCATION
流。这会否决 FILE_NON_DIRECTORY_FILE
标志。你得到你所要求的。但不要依赖于此,因为这些流是 NTFS 的实现细节,它不是 Windows.