Skip to content

Commit 721c445

Browse files
authored
Fix invalid parameters in SetFileInformationByHandle (#95235)
* Add failing unit test for SetFileInformationByHandle (#95096) * Fix invalid parameters in SetFileInformationByHandle (#95096) According to MS-FSCC, "a value of -1 indicates to the server that it MUST NOT change this attribute for all subsequent operations" This behavior is incorrect in the scope of .NET, since a call to File.SetLastAccessTime on a open file handle will cause all future writes to not update the last write tim. It also triggers STATUS_INVALID_PARAMETER on NFS, since the Windows driver doesn't seem to implement the -1 value (tracking of subsequent write operations) Fixes #95096
1 parent 2f991a6 commit 721c445

File tree

2 files changed

+30
-10
lines changed

2 files changed

+30
-10
lines changed

src/libraries/System.Private.CoreLib/src/System/IO/FileSystem.Windows.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -464,10 +464,10 @@ public static unsafe void SetAttributes(SafeFileHandle fileHandle, FileAttribute
464464
private static void SetFileTime(
465465
string fullPath,
466466
bool asDirectory,
467-
long creationTime = -1,
468-
long lastAccessTime = -1,
469-
long lastWriteTime = -1,
470-
long changeTime = -1,
467+
long creationTime = 0,
468+
long lastAccessTime = 0,
469+
long lastWriteTime = 0,
470+
long changeTime = 0,
471471
uint fileAttributes = 0)
472472
{
473473
using SafeFileHandle handle = OpenHandleToWriteAttributes(fullPath, asDirectory);
@@ -477,10 +477,10 @@ private static void SetFileTime(
477477
private static unsafe void SetFileTime(
478478
SafeFileHandle fileHandle,
479479
string? fullPath = null,
480-
long creationTime = -1,
481-
long lastAccessTime = -1,
482-
long lastWriteTime = -1,
483-
long changeTime = -1,
480+
long creationTime = 0,
481+
long lastAccessTime = 0,
482+
long lastWriteTime = 0,
483+
long changeTime = 0,
484484
uint fileAttributes = 0)
485485
{
486486
var basicInfo = new Interop.Kernel32.FILE_BASIC_INFO

src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/File/GetSetTimes_SafeFileHandle.cs

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4+
using System.Threading.Tasks;
45
using Microsoft.Win32.SafeHandles;
56
using Xunit;
67

@@ -91,15 +92,34 @@ protected override DateTime GetLastWriteTimeUtc(string path)
9192
return File.GetLastWriteTimeUtc(fileHandle);
9293
}
9394

95+
[Fact]
96+
public async Task WritingShouldUpdateWriteTime_After_SetLastAccessTime()
97+
{
98+
string filePath = GetTestFilePath();
99+
using var handle = OpenFileHandle(filePath, FileAccess.ReadWrite);
100+
101+
File.SetLastAccessTime(handle, DateTime.Now.Subtract(TimeSpan.FromDays(1)));
102+
var timeBeforeWrite = File.GetLastWriteTime(handle);
103+
104+
using var writer = new StreamWriter(new FileStream(handle, FileAccess.ReadWrite));
105+
writer.AutoFlush = true;
106+
writer.WriteLine("now: " + DateTime.Now);
107+
await Task.Delay(2000);
108+
writer.WriteLine("now: " + DateTime.Now);
109+
110+
var timeAfterWrite = File.GetLastWriteTime(handle);
111+
Assert.True(timeAfterWrite > timeBeforeWrite);
112+
}
113+
94114
[Fact]
95115
public void NullArgumentValidation()
96116
{
97117
Assert.Throws<ArgumentNullException>("fileHandle", static () => File.GetCreationTime(default(SafeFileHandle)!));
98118
Assert.Throws<ArgumentNullException>("fileHandle", static () => File.SetCreationTime(default(SafeFileHandle)!, DateTime.Now));
99-
119+
100120
Assert.Throws<ArgumentNullException>("fileHandle", static () => File.GetCreationTimeUtc(default(SafeFileHandle)!));
101121
Assert.Throws<ArgumentNullException>("fileHandle", static () => File.SetCreationTimeUtc(default(SafeFileHandle)!, DateTime.Now));
102-
122+
103123
Assert.Throws<ArgumentNullException>("fileHandle", static () => File.GetLastAccessTime(default(SafeFileHandle)!));
104124
Assert.Throws<ArgumentNullException>("fileHandle", static () => File.SetLastAccessTime(default(SafeFileHandle)!, DateTime.Now));
105125

0 commit comments

Comments
 (0)