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()}"); }
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))) { } }
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; }
public long CalculateFileSystemSize(int bytesPerBlock) { int fileSystemHeaderSize = FileSystemHeaderCluster.CalculateClusterSize(bytesPerBlock); return(fileSystemHeaderSize + CalculateTrackSizeBytes(bytesPerBlock) * TrackCount); }
public FileSystemClusterIO(FileSystem fs, IBlockIO io) : base(io, FileSystemHeaderCluster.CalculateClusterSize(io.BlockSizeBytes)) { _fileSystem = fs; }
// 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; }