Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,11 @@ private static unsafe void Preallocate(string fullPath, long preallocationSize,
int errorCode = Marshal.GetLastPInvokeError();

// Only throw for errors that indicate there is not enough space.
if (errorCode == Interop.Errors.ERROR_DISK_FULL ||
errorCode == Interop.Errors.ERROR_FILE_TOO_LARGE)
// SetFileInformationByHandle fails with ERROR_DISK_FULL in certain cases when the size is disallowed by filesystem,
// such as >4GB on FAT32 volume. We cannot distinguish them currently.
if (errorCode is Interop.Errors.ERROR_DISK_FULL or
Interop.Errors.ERROR_FILE_TOO_LARGE or
Interop.Errors.ERROR_INVALID_PARAMETER)
{
fileHandle.Dispose();

Expand All @@ -147,7 +150,7 @@ private static unsafe void Preallocate(string fullPath, long preallocationSize,
throw new IOException(SR.Format(errorCode == Interop.Errors.ERROR_DISK_FULL
? SR.IO_DiskFull_Path_AllocationSize
: SR.IO_FileTooLarge_Path_AllocationSize,
fullPath, preallocationSize));
fullPath, preallocationSize), Win32Marshal.MakeHRFromErrorCode(errorCode));
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,5 +95,43 @@ public void DeleteOnClose_FileDeletedAfterSafeHandleDispose(FileOptions options)
}
Assert.False(File.Exists(path));
}

[Fact]
[PlatformSpecific(TestPlatforms.Windows)]
public void PreallocationSizeVeryLargeThrowsCorrectHResult()
{
const long VeryLargeFileSize = (long)128 * 1024 * 1024 * 1024 * 1024; // 128TB

// The largest file size depends on cluster size.
// See https://learn.microsoft.com/en-us/windows-server/storage/file-server/ntfs-overview#support-for-large-volumes


const int ERROR_INVALID_PARAMETER = unchecked((int)0x80070057);
const int ERROR_DISK_FULL = unchecked((int)0x80070070);

string path = GetTestFilePath();
if (!IOServices.IsDriveNTFS(Path.GetPathRoot(path)))
{
// Skip the test for non-NTFS filesystems
return;
}

if (new DriveInfo(path).TotalFreeSpace >= VeryLargeFileSize)
{
// Skip the test if somehow the drive is really big.
return;
}

try
{
using (File.OpenHandle(path, mode: FileMode.Create, access: FileAccess.ReadWrite, preallocationSize: VeryLargeFileSize)) { }
Assert.Fail("File.OpenHandle should throw due to failure to preallocate a very large file.");
}
catch (IOException ex)
{
// Accept both results since we cannot assume the cluster size of testing volume
Assert.True(ex.HResult is ERROR_INVALID_PARAMETER or ERROR_DISK_FULL);
}
}
}
}
Loading