Beispiel #1
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);
        }
        public void IntArraySaveLoadTest()
        {
            ConfigurationTest.Initialize();

            using (var io = ConfigurationTest.CreateMemoryIO()) {
                SimpleClusterIO cio = new SimpleClusterIO(io);

                Random            r   = new Random();
                Int32ArrayCluster csc = new Int32ArrayCluster(2);
                csc.Initialize();
                for (int i = 0; i < csc.Count; i++)
                {
                    csc[i] = r.Next();
                }
                csc.NextClusterAddress = Constants.NoAddress;
                csc.Type = ClusterType.NextClusterAddressTable;
                cio.Save(csc);

                int       offset = 0;
                DataBlock b      = new DataBlock(io.Bytes, 2 * Configuration.Geometry.BytesPerCluster, Configuration.Geometry.BytesPerCluster);

                byte[] marker = b.ToByteArray(offset, Constants.SrfsMarker.Length);
                Assert.IsTrue(marker.SequenceEqual(Constants.SrfsMarker));
                offset += marker.Length;

                byte[] version = b.ToByteArray(offset, Constants.CurrentVersion.Length);
                Assert.IsTrue(version.SequenceEqual(Constants.CurrentVersion));
                offset += version.Length;

                Guid guid = new Guid(b.ToByteArray(offset, Constants.GuidLength));
                Assert.AreEqual(guid, Configuration.FileSystemID);
                offset += Constants.GuidLength;

                byte[] signatureBytes = b.ToByteArray(offset, Signature.Length);
                offset += Signature.Length;

                byte[] thumbprintBytes = b.ToByteArray(offset, KeyThumbprint.Length);
                Assert.IsTrue(thumbprintBytes.SequenceEqual(Configuration.CryptoSettings.SigningKeyThumbprint.Bytes));
                offset += KeyThumbprint.Length;

                byte[] hashBytes = b.ToByteArray(offset, 32);
                offset += 32;

                ClusterType clusterType = (ClusterType)b.ToByte(offset);
                Assert.AreEqual(clusterType, ClusterType.NextClusterAddressTable);
                offset += sizeof(ClusterType);

                int nextClusterAddress = b.ToInt32(offset);
                Assert.AreEqual(nextClusterAddress, Constants.NoAddress);
                offset += sizeof(int);

                int[] cs = new int[csc.Count];
                for (int i = 0; i < csc.Count; i++)
                {
                    cs[i] = b.ToInt32(offset + i * sizeof(int));
                }
                Assert.IsTrue(cs.SequenceEqual(csc));

                Int32ArrayCluster csc2 = new Int32ArrayCluster(2);
                cio.Load(csc2);
                Assert.AreEqual(csc.VolumeID, csc2.VolumeID);
                Assert.AreEqual(csc.Type, csc2.Type);
                Assert.AreEqual(csc.NextClusterAddress, csc2.NextClusterAddress);

                Assert.IsTrue(csc.SequenceEqual(csc2));
            }
        }
Beispiel #3
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;
        }