【问题标题】:Modify access time of Windows read only file through WSL通过 WSL 修改 Windows 只读文件的访问时间
【发布时间】:2019-05-27 13:11:49
【问题描述】:

我有一个只读文件,比如 samp.txt,我在 PowerShell 上运行以下命令:

> $file = Get-Item .\samp.txt
> $file.LastAccessTime = (get-date)

我们得到:"Access to the path 'G:\Study_Material\Coding\samp.txt' is denied."

在我们继续之前,先看看访问时间: > $file.LastAccessTime 会是

Sunday, December 30, 2018 11:02:49 PM

现在我们打开 WSL 并执行:$ touch samp.txt

回到我们做的 PowerShell:

> $file = Get-Item .\samp.txt
> $file.LastAccessTime

我们得到:

Sunday, December 30, 2018 11:19:16 PM

因此它已被修改,没有提升权限。

现在我的问题是:如何在不通过修改 $file.Attributes 删除 ReadOnly 标记的情况下单独在 PowerShell 中模拟此操作。

【问题讨论】:

  • 只读属性保护文件数据,而不是元数据。它不应阻止使用FILE_WRITE_ATTRIBUTES 访问权限打开文件或导致SetFileTime 失败。 Python 的 os.utime 在 Windows 上调用后一个函数,它适用于只读文件。我将在此处研究 PowerShell 失败的原因。
  • 这是一个 .NET 错误。 System.IO.File.SetLastAccessTimeUtc 的实现尝试以GENERIC_WRITE 访问权限打开文件,这超出了要求,并且对于只读文件失败。
  • 感谢您的回复。那么touch命令或者os.utime是不是以不同的方式打开文件呢?
  • Python 的 os.utime 请求写入属性访问。这是对CreateFile 始终请求的最低要求的补充:读取属性和同步访问。相比之下,通用写入访问包括写入数据和附加数据访问,这对于只读文件是不允许的。
  • Linux touch 基于utimensat。起初touch 尝试获得写访问权限,但由于只读属性(在 WSL 中映射为没有写权限,但它应该映射到具有 NTFS 语义的“不可变”属性),它不能。它仍然可以在没有启用写入的 fd 的情况下成功,因为时间只是当前的并且调用者是所有者。当 WSL 在“/mnt”下挂载卷时,WSL 使用 Windows 会话用户作为所有文件的所有者,因此这本身是不够的。它必须进行另一次 NT 访问检查以确定用户是否具有所需的写入属性访问权限。

标签: windows powershell windows-subsystem-for-linux


【解决方案1】:

处理 ReadOnly 文件时,不能简单地更改 LastAccessTime。
(见eryksun 的cmets)。

为了让它在 PowerShell 中工作,您需要首先从文件的属性中删除 ReadOnly 标志,进行更改并重置 ReadOnly 标志,如下所示:

$file = Get-Item .\samp.txt -Force

# test if the ReadOnly flag on the file is set
if ($file.Attributes -band 1) {
    # remove the ReadOnly flag from the file. (FILE_ATTRIBUTE_READONLY = 1)
    $file.Attributes = $file.Attributes -bxor 1
    # or use: $file | Set-ItemProperty -Name IsReadOnly -Value $false

    $file.LastAccessTime = (Get-Date)

    # reset the ReadOnly flag
    $file.Attributes = $file.Attributes -bxor 1
    # or use: $file | Set-ItemProperty -Name IsReadOnly -Value $true
}
else {
    # the file is not ReadOnly, so just do the 'touch' on the LastAccessTime
    $file.LastAccessTime = (Get-Date)
}

您可以阅读有关文件属性及其数值的所有信息here

【讨论】:

  • 使用[System.IO.FileAttributes]::ReadOnly而不是幻数“1”会更简洁和自我记录。
  • 感谢您的回复,正如 eryksun 在他的第一条评论中提到的,文件元数据不应该像 Linux 如何处理它一样不受只读标签的影响吗?
  • @GaneshK,PowerShell 是一个 .NET 程序,它正在解决其 SetLastAccessTimeUtc 方法中的错误(或至少是设计缺陷),该方法请求的访问权限超过了操作所需的权限。跨度>
猜你喜欢
  • 1970-01-01
  • 2020-11-17
  • 2017-03-30
  • 2014-02-05
  • 2017-05-21
  • 1970-01-01
  • 1970-01-01
  • 2012-07-07
  • 2016-09-06
相关资源
最近更新 更多