예제 #1
0
        public void Invoke()
        {
            Partition p = PartitionOptions.GetPartition();

            if (BytesPerSlice > int.MaxValue)
            {
                throw new CommandLineArgumentException("Argument to -s is too large.");
            }
            int bytesPerSlice = (int)BytesPerSlice;

            int      fileSystemHeaderClusterSize = FileSystemHeaderCluster.CalculateClusterSize(p.BytesPerBlock);
            long     bytesAvailable = p.SizeBytes - fileSystemHeaderClusterSize;
            Geometry g           = new Geometry(bytesPerSlice, ReedSolomon.N, ReedSolomon.K, 1);
            long     totalTracks = bytesAvailable / g.CalculateTrackSizeBytes(p.BytesPerBlock);

            if (totalTracks > int.MaxValue)
            {
                throw new CommandLineArgumentException("Too many tracks, please use a larger value of Reed Solomon N and/or bytesPerCluster.");
            }
            g = new Geometry(bytesPerSlice, ReedSolomon.N, ReedSolomon.K, (int)totalTracks);
            Configuration.Geometry = g;

            Console.WriteLine($"Bytes per Cluster: {g.BytesPerCluster.ToFileSize()}");
            Console.WriteLine($"Data Clusters per Track: {g.DataClustersPerTrack}");
            Console.WriteLine($"Parity Clusters per Track: {g.ParityClustersPerTrack}");
            Console.WriteLine($"Total Clusters per Track: {g.ClustersPerTrack}");
            Console.WriteLine($"Resiliency: {(double)g.ParityClustersPerTrack / g.ClustersPerTrack:%#0.00}");
            Console.WriteLine($"Total Tracks: {g.TrackCount}");
            Console.WriteLine($"Bytes Used: {(g.CalculateFileSystemSize(p.BytesPerBlock)).ToFileSize()}");
            Console.WriteLine($"Bytes Available: {((long)g.DataClustersPerTrack * g.TrackCount * (g.BytesPerCluster - FileDataCluster.FileBaseClusterHeaderLength)).ToFileSize()}");
            Console.WriteLine($"Bytes Wasted: {(p.SizeBytes - g.CalculateFileSystemSize(p.BytesPerBlock)).ToFileSize()}");
        }
예제 #2
0
        public void Invoke()
        {
            Partition p = PartitionOptions.GetPartition();

            if (BytesPerSlice > int.MaxValue)
            {
                throw new CommandLineArgumentException("Argument to -s is too large.");
            }
            int bytesPerSlice = (int)BytesPerSlice;

            long     bytesAvailable = p.SizeBytes - FileSystemHeaderCluster.CalculateClusterSize(p.BytesPerBlock);
            Geometry g = new Geometry(bytesPerSlice, ReedSolomon.N, ReedSolomon.K, 1);

            long totalTracks = bytesAvailable / g.CalculateTrackSizeBytes(p.BytesPerBlock);

            if (totalTracks > int.MaxValue)
            {
                throw new CommandLineArgumentException("Too many chains, please use a larger value of n (Reed Solomon parameter) and/or bytesPerSlice.");
            }
            g = new Geometry(bytesPerSlice, ReedSolomon.N, ReedSolomon.K, (int)totalTracks);

            Configuration.Geometry     = g;
            Configuration.VolumeName   = VolumeName;
            Configuration.FileSystemID = Guid.NewGuid();

            Options options = Options.None;

            if (doNotVerifyHashes)
            {
                options |= Options.DoNotVerifyClusterHashes;
            }
            if (doNotVerifySignatures)
            {
                options |= Options.DoNotVerifyClusterSignatures;
            }
            Configuration.Options = options;

            CngKey encryptionKey = CryptoSettingsOptions.GetEncryptionKey();
            CngKey decryptionKey = CryptoSettingsOptions.GetDecryptionKey();
            CngKey signingKey    = CryptoSettingsOptions.GetSigningKey();

            Configuration.CryptoSettings = new CryptoSettings(decryptionKey, signingKey, encryptionKey);

            using (var f = FileSystem.Create(new PartitionIO(p))) { }
        }
예제 #3
0
        public SimpleClusterIO(IBlockIO io, Geometry geometry, PrivateKey signingKey, IDictionary <KeyThumbprint, PublicKey> signatureKeys, Options options)
        {
            if (io == null)
            {
                throw new ArgumentNullException();
            }

            _fileSystemHeaderClusterSize = FileSystemHeaderCluster.CalculateClusterSize(io.BlockSizeBytes);
            _parityClusterSize           = _geometry.BytesPerCluster + ParityCluster.CalculateHeaderLength(io.BlockSizeBytes);

            _io       = io;
            _buffer   = new byte[_parityClusterSize];
            _geometry = geometry;

            _signingKey    = signingKey;
            _signatureKeys = signatureKeys;
            _options       = options;
        }
예제 #4
0
        public long CalculateFileSystemSize(int bytesPerBlock)
        {
            int fileSystemHeaderSize = FileSystemHeaderCluster.CalculateClusterSize(bytesPerBlock);

            return(fileSystemHeaderSize + CalculateTrackSizeBytes(bytesPerBlock) * TrackCount);
        }
예제 #5
0
 public FileSystemClusterIO(FileSystem fs, IBlockIO io) : base(io, FileSystemHeaderCluster.CalculateClusterSize(io.BlockSizeBytes))
 {
     _fileSystem = fs;
 }
예제 #6
0
        // Private
        #region Methods

        private static void Create(IBlockIO deviceIO, string volumeName, Geometry geometry, Guid volumeID, PrivateKey signatureKey)
        {
            // Write the Partition Cluster
            FileSystemHeaderCluster fileSystemHeaderCluster = new FileSystemHeaderCluster(deviceIO.BlockSizeBytes, volumeID);

            fileSystemHeaderCluster.BytesPerDataCluster  = geometry.BytesPerCluster;
            fileSystemHeaderCluster.ClustersPerTrack     = geometry.ClustersPerTrack;
            fileSystemHeaderCluster.DataClustersPerTrack = geometry.DataClustersPerTrack;
            fileSystemHeaderCluster.TrackCount           = geometry.TrackCount;
            fileSystemHeaderCluster.VolumeName           = volumeName;
            byte[] data = new byte[fileSystemHeaderCluster.ClusterSizeBytes];
            fileSystemHeaderCluster.Save(data, 0, signatureKey);
            deviceIO.Write(0, data, 0, data.Length);

            // Cluster State Table
            int entryCount   = geometry.ClustersPerTrack * geometry.TrackCount;
            int clusterCount = (entryCount + ClusterStatesCluster.CalculateElementsPerCluster(geometry.BytesPerCluster) - 1) /
                               ClusterStatesCluster.CalculateElementsPerCluster(geometry.BytesPerCluster);
            ClusterTable <ClusterState> clusterStateTable = new ClusterTable <ClusterState>(
                Enumerable.Range(0, clusterCount),
                sizeof(ClusterState),
                (address) => new ClusterStatesCluster(address, geometry.BytesPerCluster, volumeID));

            // Next Cluster Address Table
            entryCount   = geometry.DataClustersPerTrack * geometry.TrackCount;
            clusterCount = (entryCount + Int32ArrayCluster.CalculateElementsPerCluster(geometry.BytesPerCluster) - 1) /
                           Int32ArrayCluster.CalculateElementsPerCluster(geometry.BytesPerCluster);
            ClusterTable <int> nextClusterAddressTable = new ClusterTable <int>(
                Enumerable.Range(clusterStateTable.ClusterAddresses.Last() + 1, clusterCount),
                sizeof(int),
                (address) => new Int32ArrayCluster(address, geometry.BytesPerCluster, volumeID, ClusterType.NextClusterAddressTable));

            // Bytes Used Table
            ClusterTable <int> bytesUsedTable = new ClusterTable <int>(
                Enumerable.Range(nextClusterAddressTable.ClusterAddresses.Last() + 1, clusterCount),
                sizeof(int),
                (address) => new Int32ArrayCluster(address, geometry.BytesPerCluster, volumeID, ClusterType.BytesUsedTable));

            entryCount   = geometry.ClustersPerTrack * geometry.TrackCount;
            clusterCount = (entryCount + VerifyTimesCluster.CalculateElementsPerCluster(geometry.BytesPerCluster) - 1) /
                           VerifyTimesCluster.CalculateElementsPerCluster(geometry.BytesPerCluster);

            // Verify Time Table
            ClusterTable <DateTime> verifyTimeTable = new ClusterTable <DateTime>(
                Enumerable.Range(bytesUsedTable.ClusterAddresses.Last() + 1, clusterCount),
                sizeof(long),
                (address) => new VerifyTimesCluster(address, geometry.BytesPerCluster, volumeID));

            // Directory Table
            MutableObjectClusterTable <Directory> directoryTable = new MutableObjectClusterTable <Directory>(
                new int[] { verifyTimeTable.ClusterAddresses.Last() + 1 },
                Directory.StorageLength,
                (address) => Directory.CreateArrayCluster(address));

            // File Table
            MutableObjectClusterTable <File> fileTable = new MutableObjectClusterTable <File>(
                new int[] { directoryTable.ClusterAddresses.Last() + 1 },
                File.StorageLength,
                (address) => File.CreateArrayCluster(address));

            // Access Rules Table
            ClusterTable <SrfsAccessRule> accessRules = new ClusterTable <SrfsAccessRule>(
                new int[] { fileTable.ClusterAddresses.Last() + 1 },
                SrfsAccessRule.StorageLength + sizeof(bool),
                (address) => SrfsAccessRule.CreateArrayCluster(address));

            // Audit Rules Table
            ClusterTable <SrfsAuditRule> auditRules = new ClusterTable <SrfsAuditRule>(
                new int[] { accessRules.ClusterAddresses.Last() + 1 },
                SrfsAuditRule.StorageLength + sizeof(bool),
                (address) => SrfsAuditRule.CreateArrayCluster(address));

            // Initialize the tables
            int nDataClusters   = geometry.DataClustersPerTrack * geometry.TrackCount;
            int nParityClusters = geometry.ParityClustersPerTrack * geometry.TrackCount;

            for (int i = 0; i < nDataClusters; i++)
            {
                clusterStateTable[i] = ClusterState.Data | ClusterState.Unwritten;
            }
            for (int i = nDataClusters; i < nDataClusters + nParityClusters; i++)
            {
                clusterStateTable[i] = ClusterState.Parity | ClusterState.Unwritten;
            }
            for (int i = nDataClusters + nParityClusters; i < clusterStateTable.Count; i++)
            {
                clusterStateTable[i] = ClusterState.Null;
            }

            for (int i = 0; i < clusterStateTable.Count; i++)
            {
                clusterStateTable[i] = ClusterState.None;
            }
            for (int i = 0; i < nextClusterAddressTable.Count; i++)
            {
                nextClusterAddressTable[i] = Constants.NoAddress;
            }
            for (int i = 0; i < bytesUsedTable.Count; i++)
            {
                bytesUsedTable[i] = 0;
            }
            for (int i = 0; i < verifyTimeTable.Count; i++)
            {
                verifyTimeTable[i] = DateTime.MinValue;
            }
            for (int i = 0; i < directoryTable.Count; i++)
            {
                directoryTable[i] = null;
            }
            for (int i = 0; i < fileTable.Count; i++)
            {
                fileTable[i] = null;
            }
            for (int i = 0; i < accessRules.Count; i++)
            {
                accessRules[i] = null;
            }
            for (int i = 0; i < auditRules.Count; i++)
            {
                auditRules[i] = null;
            }

            // Update the cluster state and next cluster address tables
            foreach (var t in new IEnumerable <int>[] {
                clusterStateTable.ClusterAddresses,
                nextClusterAddressTable.ClusterAddresses,
                bytesUsedTable.ClusterAddresses,
                verifyTimeTable.ClusterAddresses,
                directoryTable.ClusterAddresses,
                fileTable.ClusterAddresses,
                accessRules.ClusterAddresses,
                auditRules.ClusterAddresses
            })
            {
                foreach (var n in t)
                {
                    clusterStateTable[n]       = ClusterState.System | ClusterState.Used;
                    nextClusterAddressTable[n] = n + 1;
                }
                nextClusterAddressTable[t.Last()] = Constants.NoAddress;
            }

            // Create the root directory
            Directory dir = new Directory(0, "");

            dir.Attributes    = System.IO.FileAttributes.Directory;
            dir.ParentID      = Constants.NoID;
            dir.Owner         = WindowsIdentity.GetCurrent().User;
            dir.Group         = WindowsIdentity.GetCurrent().User;
            directoryTable[0] = dir;
            accessRules[0]    = new SrfsAccessRule(dir, new FileSystemAccessRule(WindowsIdentity.GetCurrent().User, FileSystemRights.FullControl,
                                                                                 InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit, PropagationFlags.None,
                                                                                 AccessControlType.Allow));

            SimpleClusterIO clusterIO = new SimpleClusterIO(deviceIO, fileSystemHeaderCluster.BytesPerDataCluster);

            clusterStateTable.Flush(clusterIO);
            nextClusterAddressTable.Flush(clusterIO);
            bytesUsedTable.Flush(clusterIO);
            verifyTimeTable.Flush(clusterIO);
            directoryTable.Flush(clusterIO);
            fileTable.Flush(clusterIO);
            accessRules.Flush(clusterIO);
            auditRules.Flush(clusterIO);
        }
예제 #7
0
        // Public
        #region Construction / Destruction

        /// <summary>
        /// Open a file system.
        /// </summary>
        /// <param name="partition"></param>
        /// <param name="signatureKeys"></param>
        /// <param name="decryptionKey"></param>
        /// <param name="options"></param>
        public FileSystem(IBlockIO device, Dictionary <KeyThumbprint, PublicKey> signatureKeys, PrivateKey decryptionKey, Options options)
        {
            _keys = new Dictionary <Signature, CngKey>();
            foreach (var p in _keys)
            {
                _keys.Add(p.Key, p.Value);
            }

            _decryptionKey = decryptionKey;

            _options = options;

            _readOnly = true;

            // Create IO Devices
            _deviceIO        = device;
            _clusterIO       = new FileSystemClusterIO(this, _deviceIO);
            _disposeDeviceIO = true;

            // Initialize Indices
            _freeClusterSearchStart = 0;
            _nextEntryID            = 0;
            _nextDirectoryIndex     = 0;
            _nextFileIndex          = 0;
            _nextAccessRuleIndex    = 0;
            _nextAuditRuleIndex     = 0;

            // Create Indexes
            _directoryIndex            = new Dictionary <int, int>();
            _containedDirectoriesIndex = new Dictionary <int, SortedList <string, Directory> >();
            _containedFilesIndex       = new Dictionary <int, SortedList <string, File> >();
            _fileIndex        = new Dictionary <int, int>();
            _accessRulesIndex = new Dictionary <int, List <int> >();
            _auditRulesIndex  = new Dictionary <int, List <int> >();

            // Read the File System Header Cluster
            FileSystemHeaderCluster fileSystemHeaderCluster = new FileSystemHeaderCluster(_deviceIO.BlockSizeBytes, Guid.Empty);

            byte[] header = new byte[FileSystemHeaderCluster.CalculateClusterSize(_deviceIO.BlockSizeBytes)];
            _deviceIO.Read(0, header, 0, header.Length);
            fileSystemHeaderCluster.Load(header, 0, signatureKeys, options);

            // Initialize values from the File System Header Cluster
            _geometry = new Geometry(
                fileSystemHeaderCluster.BytesPerDataCluster,
                fileSystemHeaderCluster.ClustersPerTrack,
                fileSystemHeaderCluster.DataClustersPerTrack,
                fileSystemHeaderCluster.TrackCount);
            _volumeName = fileSystemHeaderCluster.VolumeName;
            _volumeID   = fileSystemHeaderCluster.VolumeID;

            // Initialize the Cluster State Table
            int entryCount   = _geometry.ClustersPerTrack * _geometry.TrackCount;
            int clusterCount = (entryCount + ClusterStatesCluster.CalculateElementsPerCluster(_geometry.BytesPerCluster) - 1) /
                               ClusterStatesCluster.CalculateElementsPerCluster(_geometry.BytesPerCluster);

            _clusterStateTable = new ClusterTable <ClusterState>(
                Enumerable.Range(0, clusterCount),
                sizeof(ClusterState),
                (address) => new ClusterStatesCluster(address, _geometry.BytesPerCluster, _volumeID));
            _clusterStateTable.Load(_clusterIO);

            // Initialize the Next Cluster Address Table
            entryCount   = _geometry.DataClustersPerTrack * _geometry.TrackCount;
            clusterCount = (entryCount + Int32ArrayCluster.CalculateElementsPerCluster(_geometry.BytesPerCluster) - 1) /
                           Int32ArrayCluster.CalculateElementsPerCluster(_geometry.BytesPerCluster);

            _nextClusterAddressTable = new ClusterTable <int>(
                Enumerable.Range(_clusterStateTable.ClusterAddresses.Last() + 1, clusterCount),
                sizeof(int),
                (address) => new Int32ArrayCluster(address, _geometry.BytesPerCluster, _volumeID, ClusterType.NextClusterAddressTable));
            _nextClusterAddressTable.Load(_clusterIO);

            // Initialize the Bytes Used Table
            _bytesUsedTable = new ClusterTable <int>(
                Enumerable.Range(_nextClusterAddressTable.ClusterAddresses.Last() + 1, clusterCount),
                sizeof(int),
                (address) => new Int32ArrayCluster(address, _geometry.BytesPerCluster, _volumeID, ClusterType.BytesUsedTable));
            _bytesUsedTable.Load(_clusterIO);

            entryCount   = _geometry.ClustersPerTrack * _geometry.TrackCount;
            clusterCount = (entryCount + VerifyTimesCluster.CalculateElementsPerCluster(_geometry.BytesPerCluster) - 1) /
                           VerifyTimesCluster.CalculateElementsPerCluster(_geometry.BytesPerCluster);

            // Initialize the Verify Time Table
            _verifyTimeTable = new ClusterTable <DateTime>(
                Enumerable.Range(_bytesUsedTable.ClusterAddresses.Last() + 1, clusterCount),
                sizeof(long),
                (address) => new VerifyTimesCluster(address, _geometry.BytesPerCluster, _volumeID));
            _verifyTimeTable.Load(_clusterIO);

            int l = _verifyTimeTable.ClusterAddresses.Last() + 1;

            int[] cl = getClusterChain(l).ToArray();

            // Initialize the Directory Table
            _directoryTable = new MutableObjectClusterTable <Directory>(
                getClusterChain(_verifyTimeTable.ClusterAddresses.Last() + 1),
                Directory.StorageLength,
                (address) => Directory.CreateArrayCluster(address));
            _directoryTable.Load(_clusterIO);

            // Initialize the File Table
            _fileTable = new MutableObjectClusterTable <File>(
                getClusterChain(_directoryTable.ClusterAddresses.First() + 1),
                File.StorageLength,
                (address) => File.CreateArrayCluster(address));
            _fileTable.Load(_clusterIO);

            // Initialize the Access Rules Table
            _accessRules = new ClusterTable <SrfsAccessRule>(
                getClusterChain(_fileTable.ClusterAddresses.First() + 1),
                SrfsAccessRule.StorageLength + sizeof(bool),
                (address) => SrfsAccessRule.CreateArrayCluster(address));
            _accessRules.Load(_clusterIO);

            // Initialize the Audit Rules Table
            _auditRules = new ClusterTable <SrfsAuditRule>(
                getClusterChain(_accessRules.ClusterAddresses.First() + 1),
                SrfsAuditRule.StorageLength + sizeof(bool),
                (address) => SrfsAuditRule.CreateArrayCluster(address));
            _auditRules.Load(_clusterIO);

            // Create the Indexes
            for (int i = 0; i < _directoryTable.Count; i++)
            {
                Directory d = _directoryTable[i];
                if (d != null)
                {
                    _directoryIndex.Add(d.ID, i);
                    _containedDirectoriesIndex.Add(d.ID, new SortedList <string, Directory>(StringComparer.OrdinalIgnoreCase));
                    _containedFilesIndex.Add(d.ID, new SortedList <string, File>(StringComparer.OrdinalIgnoreCase));
                    _accessRulesIndex.Add(d.ID, new List <int>());
                    _auditRulesIndex.Add(d.ID, new List <int>());
                }
            }

            foreach (var d in from d in _directoryTable where d != null && d.ParentID != Constants.NoID select d)
            {
                _containedDirectoriesIndex[d.ParentID].Add(d.Name, d);
            }

            for (int i = 0; i < _fileTable.Count; i++)
            {
                File f = _fileTable[i];
                if (f != null)
                {
                    _fileIndex.Add(f.ID, i);
                    _containedFilesIndex[f.ParentID].Add(f.Name, f);
                    _accessRulesIndex.Add(f.ID, new List <int>());
                    _auditRulesIndex.Add(f.ID, new List <int>());
                }
            }

            for (int i = 0; i < _accessRules.Count; i++)
            {
                Data.SrfsAccessRule r = _accessRules[i];
                if (r != null)
                {
                    _accessRulesIndex[r.ID].Add(i);
                }
            }

            for (int i = 0; i < _auditRules.Count; i++)
            {
                Data.SrfsAuditRule r = _auditRules[i];
                if (r != null)
                {
                    _auditRulesIndex[r.ID].Add(i);
                }
            }

            // Update the next entry ID
            _nextEntryID = Math.Max(
                _directoryIndex.Keys.Max(),
                _fileIndex.Count == 0 ? -1 : _fileIndex.Keys.Max()) + 1;
        }