Also Like

📁 last Posts

OS - Task 1

using System;
using System.IO;

namespace fat_file_system_cs
{
    internal class VirtualDisk
    {
        private const int CLUSTER_SIZE = 1024;
        private const int CLUSTERS_NUMBER = 1024;
        private long diskSize = 0;
        private string? diskPath = null;
        private FileStream? diskFileStream = null;
        private bool isOpen = false;

        public void Initialize(string path, bool createIfMissing = true)
        {
            if (this.isOpen)
                throw new InvalidOperationException("Disk is already initialized");

            this.diskPath = path;
            this.diskSize = CLUSTERS_NUMBER * CLUSTER_SIZE;

            try
            {
                if (!File.Exists(diskPath))
                {
                    if (createIfMissing)
                        this.CreateEmptyDisk(path);
                    else
                        throw new FileNotFoundException("Couldn't find the specified disk path");
                }

                this.diskFileStream = new FileStream(path, FileMode.Open, FileAccess.ReadWrite);
                this.isOpen = true;
            }
            catch (Exception ex)
            {
                this.isOpen = false;
                throw new IOException($"Failed to open disk: {ex.Message}", ex);
            }
        }

        private void CreateEmptyDisk(string path)
        {
            FileStream? tempFileStream = null;

            try
            {
                tempFileStream = new FileStream(path, FileMode.Create, FileAccess.Write);
                byte[] emptyClusterPlaceholder = new byte[CLUSTER_SIZE];
                for (int i = 0; i < CLUSTERS_NUMBER; i++)
                    tempFileStream.Write(emptyClusterPlaceholder, 0, CLUSTER_SIZE);
                tempFileStream.Flush();
            }
            catch (Exception ex)
            {
                throw new IOException($"Failed to create disk file: {ex.Message}", ex);
            }
            finally
            {
                tempFileStream?.Close();
            }
        }

        public byte[] ReadCluster(int clusterNumber)
        {
            if (!this.isOpen)
                throw new InvalidOperationException("Disk is not open");
            if (clusterNumber < 0 || clusterNumber >= CLUSTERS_NUMBER)
                throw new ArgumentOutOfRangeException(nameof(clusterNumber), "Invalid cluster number");

            byte[] buffer = new byte[CLUSTER_SIZE];
            long offset = clusterNumber * CLUSTER_SIZE;

            this.diskFileStream!.Seek(offset, SeekOrigin.Begin);
            int bytesRead = this.diskFileStream.Read(buffer, 0, CLUSTER_SIZE);

            if (bytesRead < CLUSTER_SIZE)
                throw new IOException("Failed to read full cluster");

            return buffer;
        }

        public void WriteCluster(int clusterNumber, byte[] data)
        {
            if (!this.isOpen)
                throw new InvalidOperationException("Disk is not open");
            if (clusterNumber < 0 || clusterNumber >= CLUSTERS_NUMBER)
                throw new ArgumentOutOfRangeException(nameof(clusterNumber), "Invalid cluster number");
            if (data.Length != CLUSTER_SIZE)
                throw new ArgumentException("Data must be exactly one cluster in size");

            long offset = clusterNumber * CLUSTER_SIZE;
            this.diskFileStream!.Seek(offset, SeekOrigin.Begin);
            this.diskFileStream.Write(data, 0, CLUSTER_SIZE);
            this.diskFileStream.Flush();
        }

        public long GetDiskSize()
        {
            return this.diskSize;
        }

        public void CloseDisk()
        {
            if (this.diskFileStream != null)
            {
                this.diskFileStream.Flush();
                this.diskFileStream.Close();
                this.diskFileStream = null;
            }
            this.isOpen = false;
        }
    }
}
Comments