c# 文件系统

24 阅读4分钟
  1. 磁盘情况

using System.Runtime.InteropServices;
using static DiskInfo.FileSystemInfo;

namespace DiskInfo
{
    internal class Program
    {
        static void Main(string[] args)
        {
            try
            {
                try
                {
                    string path = args.Length > 0 ? args[0] : "."; // 默认当前目录
                    FileSystemStats info = GetFileSystemInfo(path);

                    Console.WriteLine($"tsize: {info.tsize}");
                    Console.WriteLine($"bsize: {info.bsize}");
                    Console.WriteLine($"blocks: {info.blocks}");
                    Console.WriteLine($"bfree: {info.bfree}");
                    Console.WriteLine($"bavail: {info.bavail}");
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
                Console.WriteLine("end");
                Console.ReadLine();
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Error: {ex.Message}");
            }
        }
    }

    class FileSystemInfo
    {
        // 定义结构体
        public class FileSystemStats
        {
            public uint tsize;  // 最佳传输大小
            public uint bsize;  // 文件系统块大小
            public ulong blocks; // 总块数
            public ulong bfree;  // 空闲块数
            public ulong bavail; // 可用块数(非特权用户)
        }

        // Windows API
        [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        private static extern bool GetDiskFreeSpaceEx(
            string lpDirectoryName,
            out ulong lpFreeBytesAvailable,
            out ulong lpTotalNumberOfBytes,
            out ulong lpTotalNumberOfFreeBytes);

        // Linux API
        [DllImport("libc", SetLastError = true)]
        private static extern int statvfs(string path, out StatVfs buf);

        private class StatVfs
        {
            public ulong f_bsize;  // 文件系统块大小
            public ulong f_frsize; // 片段大小
            public ulong f_blocks; // 总块数
            public ulong f_bfree;  // 空闲块数
            public ulong f_bavail; // 可用块数(非特权用户)
            public ulong f_files;  // 总文件节点数
            public ulong f_ffree;  // 空闲文件节点数
            public ulong f_favail; // 可用文件节点数(非特权用户)
            public ulong f_fsid;   // 文件系统 ID
            public ulong f_flag;   // 挂载标志
            public ulong f_namemax;// 最大文件名长度
        }

        // 获取文件系统信息
        public static FileSystemStats GetFileSystemInfo(string path)
        {
            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                return GetWindowsFileSystemInfo(path);
            }
            else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
            {
                return GetLinuxFileSystemInfo(path);
            }
            else
            {
                throw new PlatformNotSupportedException("Unsupported platform.");
            }
        }

        // 获取 Windows 文件系统信息
        private static FileSystemStats GetWindowsFileSystemInfo(string path)
        {
            if (!GetDiskFreeSpaceEx(path, out ulong freeBytesAvailable, out ulong totalNumberOfBytes, out ulong totalNumberOfFreeBytes))
            {
                throw new Exception("Failed to get disk space information.");
            }

            var info = new FileSystemStats
            {
                tsize = 4096, // 假设最佳传输大小为 4KB
                bsize = 4096, // 假设块大小为 4KB
                blocks = totalNumberOfBytes / 4096,
                bfree = totalNumberOfFreeBytes / 4096,
                bavail = freeBytesAvailable / 4096
            };

            return info;
        }

        // 获取 Linux 文件系统信息
        private static FileSystemStats GetLinuxFileSystemInfo(string path)
        {
            if (statvfs(path, out StatVfs buf) != 0)
            {
                throw new Exception("Failed to get filesystem information.");
            }

            var info = new FileSystemStats
            {
                tsize = (uint)buf.f_bsize, // 最佳传输大小
                bsize = (uint)buf.f_bsize, // 块大小
                blocks = buf.f_blocks,     // 总块数
                bfree = buf.f_bfree,       // 空闲块数
                bavail = buf.f_bavail      // 可用块数(非特权用户)
            };

            return info;
        }
    }
}

  1. 文件属性
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace FattrTest
{
    public enum FType
    {
        NFDIR = 0x40000,  // Directory
        NFCHR = 0x20000,  // Character device
        NFBLK = 0x60000,  // Block device
        NFREG = 0x100000, // Regular file
        NFLNK = 0x120000, // Symbolic link
        NFNOC = 0x140000, // Named socket (or unknown)
    }

    public struct TimeVal
    {
        public long tv_sec;   // seconds
        public long tv_usec;  // microseconds
    }

    public struct Fattr
    {
        public FType type;
        public uint mode;
        public uint nlink;
        public uint uid;
        public uint gid;
        public uint size;
        public uint blocksize;
        public uint rdev;
        public uint blocks;
        public uint fsid;
        public uint fileid;
        public TimeVal atime;
        public TimeVal mtime;
        public TimeVal ctime;
    }
}

namespace FattrTest
{
    public static class FattrHelper
    {
        public static Fattr GetFattr(string path)
        {
            var info = new FileInfo(path);
            //if (!File.Exists(path))
            //    throw new FileNotFoundException("文件不存在", path);

            var attr = new Fattr();
            if (File.GetAttributes(path).HasFlag(FileAttributes.Directory))
            {
                // Directory
                var dirInfo = new DirectoryInfo(path);
                attr.type = FType.NFDIR;
                attr.mode = (uint)0x40000; // Directory mode
                attr.size = (uint)dirInfo.EnumerateFiles("*", SearchOption.AllDirectories).Sum(file => file.Length); // Total size of all files in directory

                // Set other properties as needed
                attr.atime.tv_sec = ToUnixTime(dirInfo.LastAccessTimeUtc);
                attr.mtime.tv_sec = ToUnixTime(dirInfo.LastWriteTimeUtc);
                attr.ctime.tv_sec = ToUnixTime(dirInfo.CreationTimeUtc);
            }
            else
            {
                // type
                if ((info.Attributes & FileAttributes.Directory) != 0)
                    attr.type = FType.NFDIR;
                else if ((info.Attributes & FileAttributes.ReparsePoint) != 0)
                    attr.type = FType.NFLNK;
                else
                    attr.type = FType.NFREG;

                // mode(简化处理)
                attr.mode = 0;
                if ((info.Attributes & FileAttributes.ReadOnly) != 0)
                    attr.mode |= 0x0000200; // Write permission for owner?

                // 其他字段模拟(Windows 不支持 UID/GID)
                attr.nlink = 1;
                attr.uid = 0;
                attr.gid = 0;
                attr.size = (uint)info.Length;
                attr.blocksize = 4096; // 默认块大小
                attr.blocks = (uint)(info.Length / 512 + 1); // 假设每块512字节
                attr.rdev = 0;
                attr.fsid = 0;
                attr.fileid = 0;

                // 时间戳
                attr.atime.tv_sec = ToUnixTime(info.LastAccessTimeUtc);
                attr.mtime.tv_sec = ToUnixTime(info.LastWriteTimeUtc);
                attr.ctime.tv_sec = ToUnixTime(info.CreationTimeUtc);
            }
            return attr;
        }

        private static long ToUnixTime(DateTime time)
        {
            var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
            return (long)(time.ToUniversalTime() - epoch).TotalSeconds;
        }
    }
}
using System.Runtime.InteropServices;
namespace FattrTest
{
    [StructLayout(LayoutKind.Sequential)]
    public struct Stat
    {
        public ulong dev;
        public uint ino;
        public uint mode;
        public uint nlink;
        public uint uid;
        public uint gid;
        public ulong rdev;
        public long size;
        public long blksize;
        public long blocks;
        public long atim;
        public long mtim;
        public long ctim;
    }

    public static class NativeMethods
    {
        [DllImport("libc", SetLastError = true)]
        public static extern int stat(string path, out Stat buf);
    }

    public static class FattrHelperLinux
    {
        public static Fattr GetFattr(string path)
        {
            var stat = new Stat();
            if (NativeMethods.stat(path, out stat) != 0)
                throw new Exception("无法获取文件属性");

            var attr = new Fattr();
            attr.type = (FType)(stat.mode & 0x1FF0000);
            attr.mode = stat.mode;
            attr.nlink = stat.nlink;
            attr.uid = stat.uid;
            attr.gid = stat.gid;
            attr.size = (uint)stat.size;
            attr.blocksize = (uint)stat.blksize;
            attr.rdev = (uint)stat.rdev;
            attr.blocks = (uint)stat.blocks;
            attr.fsid = (uint)stat.dev;
            attr.fileid = (uint)stat.ino;

            attr.atime.tv_sec = stat.atim;
            attr.mtime.tv_sec = stat.mtim;
            attr.ctime.tv_sec = stat.ctim;

            return attr;
        }
    }
}
namespace FattrTest
{
    internal class Program
    {
        static void Main(string[] args)
        {
            string path = "E:\\opensource_code\\nfs_path\\send\\1.txt"; // 或 Windows 路径 "C:\\test\\testfile.txt"

            try
            {
                Fattr attr = OperatingSystem.IsWindows()
                    ? FattrHelper.GetFattr(path)
                    : FattrHelperLinux.GetFattr(path);

                Console.WriteLine("文件属性:");
                Console.WriteLine($"类型: {attr.type}");
                Console.WriteLine($"模式: {Convert.ToString(attr.mode, 8)}"); // 以八进制格式显示模式
                Console.WriteLine($"链接数: {attr.nlink}");
                Console.WriteLine($"用户ID (UID): {attr.uid} (在Windows上可能不准确)");
                Console.WriteLine($"组ID (GID): {attr.gid} (在Windows上可能不准确)");
                Console.WriteLine($"大小: {attr.size} 字节");
                Console.WriteLine($"块大小: {attr.blocksize} 字节");
                Console.WriteLine($"设备号: {attr.rdev}");
                Console.WriteLine($"占用块数: {attr.blocks}");
                Console.WriteLine($"文件系统ID: {attr.fsid}");
                Console.WriteLine($"文件ID: {attr.fileid}");

                Console.WriteLine($"最后访问时间: {UnixTimeToDateTime(attr.atime.tv_sec)}");
                Console.WriteLine($"最后修改时间: {UnixTimeToDateTime(attr.mtime.tv_sec)}");
                Console.WriteLine($"状态改变时间: {UnixTimeToDateTime(attr.ctime.tv_sec)}");
                Console.ReadLine();
            }
            catch (Exception ex)
            {
                Console.WriteLine("错误:" + ex.Message);
            }
        }
        private static DateTime UnixTimeToDateTime(long unixTime)
        {
            var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
            return epoch.AddSeconds(unixTime);
        }
    }
}
  1. 读写权限
 public class FileCheck
 {
     public static bool CanAccessFile(string path, FileAccessMode mode)
     {
         if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
         {
             return CheckAccessWindows(path, mode);
         }
         else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
         {
             return CheckAccessUnix(path, mode);
         }
         else
         {
             throw new PlatformNotSupportedException("不支持的操作系统");
         }
     }

     private static bool CheckAccessWindows(string path, FileAccessMode mode)
     {
         try
         {
             using (var fs = new FileStream(path, FileMode.Open,
                 mode == FileAccessMode.Read ? FileAccess.Read : FileAccess.Write))
             {
                 return true;
             }
         }
         catch (UnauthorizedAccessException)
         {
             return false;
         }
         catch (IOException)
         {
             return false;
         }
     }

     [DllImport("libc", SetLastError = true)]
     private static extern int access(string pathname, int mode);

     public enum FileAccessMode
     {
         Read,
         Write
     }

     private static readonly int R_OK = 4; // Read permission
     private static readonly int W_OK = 2; // Write permission

     private static bool CheckAccessUnix(string path, FileAccessMode mode)
     {
         int m = mode == FileAccessMode.Read ? R_OK :
                 mode == FileAccessMode.Write ? W_OK : 0;

         return access(path, m) == 0;
     }
 }