Exemplo n.º 1
0
        private void UpdateLocalDirectoryOrFile(List <LocalDirectoryContentInfo> localDirectoryContentInfos, byte[] directoryData,
                                                int directoryClusterIndex, int directoryEntryIndex, int entryStartClusterIndex, string newContentName)
        {
            string newContentPath = null;

            if (directoryClusterIndex != _rootDirectoryClusterIndex)
            {
                string newPathDirectory = _clusterInfos[directoryClusterIndex].LocalDirectoryContent.LocalPath;
                newContentPath = Path.Combine(newPathDirectory, newContentName);
            }

            else
            {
                newContentPath = newContentName;
            }

            try
            {
                if (directoryData[directoryEntryIndex + 11] == FAT16Helper.DirectoryIdentifier)
                {
                    // Is it a directory with a valid start cluster?
                    if (entryStartClusterIndex != 0)
                    {
                        _logger.Log("Creating local directory \"" + newContentPath + "\"", Constants.LoggingLevel.Info);

                        var CreatedLocalDirectory = Directory.CreateDirectory(GetAbsolutePath(newContentPath));

                        var newLocalDirectoryContent = new LocalDirectoryContentInfo
                        {
                            ParentDirectory  = _clusterInfos[directoryClusterIndex]?.LocalDirectoryContent,
                            LocalFileName    = newContentName,
                            TOSFileName      = newContentName,
                            EntryIndex       = directoryEntryIndex,
                            DirectoryCluster = directoryClusterIndex,
                            StartCluster     = entryStartClusterIndex,
                            FinalCluster     = entryStartClusterIndex,
                            WriteInProgress  = false
                        };

                        localDirectoryContentInfos.Add(newLocalDirectoryContent);

                        _clusterInfos[entryStartClusterIndex].LocalDirectoryContent = newLocalDirectoryContent;
                        _clusterInfos[entryStartClusterIndex].FileOffset            = FAT16Helper.DirectoryFileOffset;
                    }
                }

                // it's a file
                else
                {
                    _logger.Log($"Checking if local file {newContentPath} should be updated", Constants.LoggingLevel.Debug);

                    int fileSize = directoryData[directoryEntryIndex + 28] | (directoryData[directoryEntryIndex + 29] << 8) | (directoryData[directoryEntryIndex + 30] << 16) | (directoryData[directoryEntryIndex + 31] << 24);

                    _logger.Log("File size to write:" + fileSize, Constants.LoggingLevel.All);

                    int fileClusterIndex = entryStartClusterIndex;

                    _logger.Log("Finding existing content info for local file \"" + newContentPath + "\".", Constants.LoggingLevel.All);

                    var localDirectoryContent = localDirectoryContentInfos.Where(ldci => ldci.LocalPath == newContentPath).SingleOrDefault();

                    if (localDirectoryContent == null)
                    {
                        _logger.Log($"Creating local file: {newContentPath}", Constants.LoggingLevel.Info);
                        File.Create(GetAbsolutePath(newContentPath)).Dispose();

                        var newLocalDirectoryContent = new LocalDirectoryContentInfo
                        {
                            ParentDirectory  = _clusterInfos[directoryClusterIndex]?.LocalDirectoryContent,
                            LocalFileName    = newContentName,
                            TOSFileName      = newContentName,
                            EntryIndex       = directoryEntryIndex,
                            DirectoryCluster = directoryClusterIndex,
                            StartCluster     = entryStartClusterIndex,
                            FinalCluster     = -1
                        };

                        localDirectoryContentInfos.Add(newLocalDirectoryContent);

                        localDirectoryContent = newLocalDirectoryContent;
                    }

                    localDirectoryContent.StartCluster = entryStartClusterIndex;
                    _logger.Log("File start cluster: " + localDirectoryContent.StartCluster + " (" + FatGetClusterValue(localDirectoryContent.StartCluster) + ")", Constants.LoggingLevel.All);

                    // Entry cluster will be assigned if this is a non-empty file
                    if (entryStartClusterIndex != 0)
                    {
                        localDirectoryContent.WriteInProgress = true;
                        _logger.Log("Content marked for write: " + localDirectoryContent.WriteInProgress, Constants.LoggingLevel.All);

                        int remainingBytes = fileSize;

                        // Check if the file has been completely written.
                        // Number of bytes in the cluster chain must be checked in case this file is being written
                        // in multiple passes due to lack of available RAM on the Atari
                        while (!FAT16Helper.IsEndOfClusterChain(fileClusterIndex))
                        {
                            // Keep final cluster updated in case this file is being written in multiple passes
                            localDirectoryContent.FinalCluster = fileClusterIndex;
                            remainingBytes  -= Parameters.BytesPerCluster;
                            fileClusterIndex = FatGetClusterValue(fileClusterIndex);
                        }

                        bool allBytesAvailable = remainingBytes <= 0 && FAT16Helper.IsEndOfFile(fileClusterIndex);

                        _logger.Log("All bytes available?: " + allBytesAvailable, Constants.LoggingLevel.All);

                        // Final FAT cluster value in chain matches a fully written file
                        if (allBytesAvailable)
                        {
                            localDirectoryContent.WriteInProgress = false;

                            try
                            {
                                _logger.Log("Finding existing content info for local file \"" + newContentPath + "\".", Constants.LoggingLevel.All);

                                localDirectoryContent = localDirectoryContentInfos.Where(ldci => ldci.LocalPath == newContentPath).Single();

                                localDirectoryContent.StartCluster = entryStartClusterIndex;


                                _logger.Log("Writing to local file \"" + newContentPath + "\".", Constants.LoggingLevel.Info);

                                using (BinaryWriter FileBinaryWriter = new BinaryWriter(File.OpenWrite(GetAbsolutePath(newContentPath))))
                                {
                                    fileClusterIndex = entryStartClusterIndex;
                                    remainingBytes   = fileSize;
                                    int fileOffset = 0;

                                    while (!FAT16Helper.IsEndOfFile(fileClusterIndex))
                                    {
                                        _clusterInfos[fileClusterIndex].LocalDirectoryContent = localDirectoryContent;
                                        _clusterInfos[fileClusterIndex].FileOffset            = fileOffset;

                                        FileBinaryWriter.Write(_clusterInfos[fileClusterIndex].DataBuffer, 0, Math.Min(_clusterInfos[fileClusterIndex].DataBuffer.Length, remainingBytes));

                                        remainingBytes -= _clusterInfos[fileClusterIndex].DataBuffer.Length;
                                        fileOffset     += _clusterInfos[fileClusterIndex].DataBuffer.Length;

                                        // Buffer has been written to disk; free up RAM
                                        _clusterInfos[fileClusterIndex].DataBuffer = null;

                                        localDirectoryContent.FinalCluster = fileClusterIndex;
                                        fileClusterIndex = FatGetClusterValue(fileClusterIndex);
                                    }

                                    _logger.Log("Bytes remaining after write:" + remainingBytes, Constants.LoggingLevel.All);
                                }
                            }

                            catch (Exception ex)
                            {
                                _logger.LogException(ex);
                            }
                        }
                    }
                }
            }

            catch (Exception ex)
            {
                _logger.LogException(ex);
            }
        }
Exemplo n.º 2
0
        private void SyncDirectoryClusterToLocalDisk(List <LocalDirectoryContentInfo> localDirectoryContentInfos, int clusterIndex)
        {
            byte[] directoryData;

            directoryData = GetDirectoryClusterData(clusterIndex);

            // Only check for changes if this cluster contains directory entry information
            if (clusterIndex == _rootDirectoryClusterIndex || _clusterInfos[clusterIndex].FileOffset == -1)
            {
                bool continueCheckingEntries = true;

                do
                {
                    _logger.Log($"Updating directory cluster {clusterIndex}", Constants.LoggingLevel.All);
                    int directoryEntryIndex = 0;

                    while (directoryEntryIndex < directoryData.Length && directoryData[directoryEntryIndex] != 0)
                    {
                        // The entry is not "." or "..".
                        if (directoryData[directoryEntryIndex] != 0x2e)
                        {
                            string fileName      = ASCIIEncoding.ASCII.GetString(directoryData, directoryEntryIndex, 8).Trim();
                            string fileExtension = ASCIIEncoding.ASCII.GetString(directoryData, directoryEntryIndex + 8, 3).Trim();

                            if (fileExtension != "")
                            {
                                fileName += "." + fileExtension;
                            }

                            int entryStartClusterIndex = directoryData[directoryEntryIndex + 26] | (directoryData[directoryEntryIndex + 27] << 8);

                            // Find the matching local content and check what happened to it.
                            var localContent = FindLocalDirectoryContentInfo(localDirectoryContentInfos, clusterIndex, directoryEntryIndex, entryStartClusterIndex);

                            if (localContent != null)
                            {
                                if (localContent.TOSFileName != fileName)
                                {
                                    if (directoryData[directoryEntryIndex] == FAT16Helper.DeletedEntryIdentifier)
                                    {
                                        DeleteLocalDirectoryOrFile(localDirectoryContentInfos, directoryData, directoryEntryIndex, localContent);
                                    }

                                    else
                                    {
                                        RenameLocalDirectoryOrFile(directoryData, directoryEntryIndex, localContent, fileName);
                                    }
                                }
                            }

                            // Entry is new
                            else if (directoryData[directoryEntryIndex] != FAT16Helper.DeletedEntryIdentifier)
                            {
                                UpdateLocalDirectoryOrFile(localDirectoryContentInfos, directoryData, clusterIndex, directoryEntryIndex, entryStartClusterIndex, fileName);
                            }
                        }

                        directoryEntryIndex += 32;
                    }

                    if (directoryEntryIndex < directoryData.Length || FAT16Helper.IsEndOfClusterChain(FatGetClusterValue(clusterIndex)))
                    {
                        continueCheckingEntries = false;
                    }

                    else
                    {
                        var nextClusterIndex = FatGetClusterValue(clusterIndex);
                        _logger.Log($"Directory cluster {clusterIndex} continues in cluster {nextClusterIndex}", Constants.LoggingLevel.All);

                        // If the next directory cluster is new, ensure it has a LocalDirectoryContentInfo assigned
                        if (_clusterInfos[nextClusterIndex].LocalDirectoryContent == null)
                        {
                            _clusterInfos[nextClusterIndex].LocalDirectoryContent = _clusterInfos[clusterIndex].LocalDirectoryContent;
                            _clusterInfos[nextClusterIndex].FileOffset            = FAT16Helper.DirectoryFileOffset;
                            _logger.Log($"Directory cluster {clusterIndex} extended to cluster {nextClusterIndex}", Constants.LoggingLevel.All);
                        }

                        clusterIndex = nextClusterIndex;

                        directoryData = GetDirectoryClusterData(clusterIndex);
                    }
                } while (continueCheckingEntries);
            }
        }