Skip to content

Linux - FileStream.Length, FileStream.Seek & File.ReadAllBytes misbehaves with files in procfs #25571

@VasiliyNovikov

Description

@VasiliyNovikov

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

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions