Exemple #1
0
        /// <summary>
        ///     Loads Btrieve Key Definitions from the Btrieve DAT File Header
        /// </summary>
        private void LoadBtrieveKeyDefinitions()
        {
            ushort              keyDefinitionBase      = 0x110;
            const ushort        keyDefinitionLength    = 0x1E;
            ReadOnlySpan <byte> btrieveFileContentSpan = LoadedFile.Data;

            //Check for Log Key
            if (btrieveFileContentSpan[0x10C] == 1)
            {
                _logger.Warn($"Btireve Log Key Present in {LoadedFile.FileName}");
                LoadedFile.LogKeyPresent = true;
            }

            ushort totalKeys         = LoadedFile.KeyCount;
            ushort currentKeyNumber  = 0;
            ushort previousKeyNumber = 0;

            while (currentKeyNumber < totalKeys)
            {
                var keyDefinition = new BtrieveKeyDefinition {
                    Data = btrieveFileContentSpan.Slice(keyDefinitionBase, keyDefinitionLength).ToArray()
                };

                if (keyDefinition.Attributes.HasFlag(EnumKeyAttributeMask.SegmentedKey))
                {
                    keyDefinition.SegmentOf = previousKeyNumber;
                    keyDefinition.Number    = previousKeyNumber;
                }
                else
                {
                    keyDefinition.Number = currentKeyNumber;
                    currentKeyNumber++;
                }

#if DEBUG
                _logger.Info("----------------");
                _logger.Info("Loaded Key Definition:");
                _logger.Info("----------------");
                _logger.Info($"Number: {keyDefinition.Number}");
                _logger.Info($"Total Records: {keyDefinition.TotalRecords}");
                _logger.Info($"Data Type: {keyDefinition.DataType}");
                _logger.Info($"Attributes: {keyDefinition.Attributes}");
                _logger.Info($"Position: {keyDefinition.Position}");
                _logger.Info($"Length: {keyDefinition.Length}");
                _logger.Info("----------------");
#endif
                if (!LoadedFile.Keys.TryGetValue(keyDefinition.Number, out var key))
                {
                    key = new BtrieveKey(keyDefinition);
                    LoadedFile.Keys.Add(keyDefinition.Number, key);
                }
                else
                {
                    key.Segments.Add(keyDefinition);
                }


                keyDefinitionBase += keyDefinitionLength;
            }
        }
        /// <summary>
        ///     Loads metadata from the loaded Sqlite table, such as RecordLength and all the key metadata.
        /// </summary>
        private void LoadSqliteMetadata()
        {
            using (var cmd = new SqliteCommand("SELECT record_length, page_length, variable_length_records FROM metadata_t;", _connection))
            {
                using var reader = cmd.ExecuteReader();
                try
                {
                    if (!reader.Read())
                    {
                        throw new ArgumentException($"Can't read metadata_t from {FullPath}");
                    }

                    RecordLength          = reader.GetInt32(0);
                    PageLength            = reader.GetInt32(1);
                    VariableLengthRecords = reader.GetBoolean(2);
                }
                finally
                {
                    reader.Close();
                }
            }

            using (var cmd =
                       new SqliteCommand(
                           "SELECT number, segment, attributes, data_type, offset, length FROM keys_t ORDER BY number, segment;",
                           _connection))
            {
                using var reader = cmd.ExecuteReader();
                while (reader.Read())
                {
                    var number = reader.GetInt32(0);
                    var btrieveKeyDefinition = new BtrieveKeyDefinition()
                    {
                        Number     = (ushort)number,
                        Segment    = reader.GetInt32(1) != 0,
                        SegmentOf  = reader.GetInt32(1) != 0 ? (ushort)number : (ushort)0,
                        Attributes = (EnumKeyAttributeMask)reader.GetInt32(2),
                        DataType   = (EnumKeyDataType)reader.GetInt32(3),
                        Offset     = (ushort)reader.GetInt32(4),
                        Length     = (ushort)reader.GetInt32(5),
                    };

                    if (!Keys.TryGetValue(btrieveKeyDefinition.Number, out var btrieveKey))
                    {
                        btrieveKey = new BtrieveKey();
                        Keys[btrieveKeyDefinition.Number] = btrieveKey;
                    }

                    var index = btrieveKey.Segments.Count;
                    btrieveKeyDefinition.SegmentIndex = index;
                    btrieveKey.Segments.Add(btrieveKeyDefinition);

                    if (btrieveKeyDefinition.DataType == EnumKeyDataType.AutoInc)
                    {
                        AutoincrementedKeys[btrieveKeyDefinition.Number] = btrieveKey;
                    }
                }
                reader.Close();
            }
        }
Exemple #3
0
 public BtrieveKey(BtrieveKeyDefinition keyDefinition)
 {
     Segments = new List <BtrieveKeyDefinition> {
         keyDefinition
     };
 }
Exemple #4
0
        /// <summary>
        ///     Loads Btrieve Key Definitions from the Btrieve DAT File Header
        /// </summary>
        private void LoadBtrieveKeyDefinitions(ILogger logger)
        {
            var          keyDefinitionBase      = 0x110;
            const ushort keyDefinitionLength    = 0x1E;
            var          btrieveFileContentSpan = Data.AsSpan();

            LogKeyPresent = (btrieveFileContentSpan[0x10C] == 1);

            var totalKeys        = KeyCount;
            var currentKeyNumber = (ushort)0;

            while (currentKeyNumber < totalKeys)
            {
                var data = btrieveFileContentSpan.Slice(keyDefinitionBase, keyDefinitionLength).ToArray();

                EnumKeyDataType dataType;
                var             attributes = (EnumKeyAttributeMask)BitConverter.ToUInt16(data, 0x8);
                if (attributes.HasFlag(EnumKeyAttributeMask.UseExtendedDataType))
                {
                    dataType = (EnumKeyDataType)data[0x1C];
                }
                else
                {
                    dataType = attributes.HasFlag(EnumKeyAttributeMask.OldStyleBinary) ? EnumKeyDataType.OldBinary : EnumKeyDataType.OldAscii;
                }

                var keyDefinition = new BtrieveKeyDefinition {
                    Number     = currentKeyNumber,
                    Attributes = attributes,
                    DataType   = dataType,
                    Offset     = BitConverter.ToUInt16(data, 0x14),
                    Length     = BitConverter.ToUInt16(data, 0x16),
                    Segment    = attributes.HasFlag(EnumKeyAttributeMask.SegmentedKey),
                    SegmentOf  = attributes.HasFlag(EnumKeyAttributeMask.SegmentedKey) ? currentKeyNumber : (ushort)0,
                    NullValue  = data[0x1D],
                };

                if (keyDefinition.RequiresACS)
                {
                    if (ACS == null)
                    {
                        throw new ArgumentException($"Key {keyDefinition.Number} requires ACS, but none was read. This database is likely corrupt: {FileName}");
                    }

                    keyDefinition.ACS = ACS;
                }

                //If it's a segmented key, don't increment so the next key gets added to the same ordinal as an additional segment
                if (!keyDefinition.Segment)
                {
                    currentKeyNumber++;
                }

#if DEBUG
                logger.Info("----------------");
                logger.Info("Loaded Key Definition:");
                logger.Info("----------------");
                logger.Info($"Number: {keyDefinition.Number}");
                logger.Info($"Data Type: {keyDefinition.DataType}");
                logger.Info($"Attributes: {keyDefinition.Attributes}");
                logger.Info($"Offset: {keyDefinition.Offset}");
                logger.Info($"Length: {keyDefinition.Length}");
                logger.Info($"Segment: {keyDefinition.Segment}");
                logger.Info($"SegmentOf: {keyDefinition.SegmentOf}");
                logger.Info("----------------");
#endif
                if (!Keys.TryGetValue(keyDefinition.Number, out var key))
                {
                    key = new BtrieveKey(keyDefinition);
                    Keys.Add(keyDefinition.Number, key);
                }
                else
                {
                    key.Segments.Add(keyDefinition);
                }

                keyDefinitionBase += keyDefinitionLength;
            }

            // update segment indices
            foreach (var key in Keys)
            {
                var i = 0;
                foreach (var segment in key.Value.Segments)
                {
                    segment.SegmentIndex = i++;
                }
            }
        }