runtime: Linux - FileStream.Length, FileStream.Seek & File.ReadAllBytes misbehaves with files in procfs
I did the following experiment:
using System;
using System.IO;
namespace TestProcStatFile
{
class Program
{
static void Main(string[] args)
{
const string procStat = "/proc/stat";
using (var file = File.OpenRead(procStat))
{
Console.WriteLine($"Stream length: {file.Length}");
Console.WriteLine($"Actual length (via File.ReadAllBytes): {File.ReadAllBytes(procStat).Length}");
Console.WriteLine($"Actual length (via File.ReadAllText): {File.ReadAllText(procStat).Length}");
Console.WriteLine($"Can seek: {file.CanSeek}");
Console.WriteLine($"Seek(8192), Position: {file.Seek(8192, SeekOrigin.Begin)}");
try
{
file.Seek(0, SeekOrigin.End);
}
catch (Exception e)
{
Console.WriteLine($"Seek from end: {e}");
}
}
}
}
}
Which reports the following:
Stream length: 0
Actual length (via File.ReadAllBytes): 0
Actual length (via File.ReadAllText): 5085
Can seek: True
Seek(8192), Position: 8192
Seek from end: System.IO.IOException: Invalid argument
at System.IO.FileStream.CheckFileCall(Int64 result, Boolean ignoreNotSupported)
at System.IO.FileStream.Seek(Int64 offset, SeekOrigin origin)
at TestProcStatFile.Program.Main(String[] args) in /home/netem/RiderProjects/TestProcStatFile/Program.cs:line 21
https://github.com/dotnet/corefx/blob/a8cfc6a498f0455c59b0030f74cba4dabeee86e1/src/System.IO.FileSystem/src/System/IO/File.cs#L320 This guy relays on FileStream.Length. I’m thinking if FileStream.Length should actually throw for files in procfs and CanSeek should return false for them and File.ReadAllBytes should check CanSeek and if it is false then don’t pre-allocate buffer of the final size but allocate it dynamically while reading
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Comments: 18 (18 by maintainers)
@tmds
Would it work if you tried to read a single byte (or read into a small stack-allocated buffer)? If that succeeds, you know the file size is lying and you have to deal with it in a special way.
This would mean some seemingly unnecessary allocations and copying for
procand similar cases, but I think that’s still better than returning the wrong result. And for actual empty files, there would be no heap allocations, and the total overhead should be fairly small.Shouldn’t we at least fix
File.ReadAllBytesto not return empty result?