Errno CacheFile(string path) { string[] pathElements = path.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries); if (pathElements.Length != 1) { return(Errno.NotSupported); } string filename = pathElements[0].ToUpperInvariant(); if (filename.Length > 30) { return(Errno.NameTooLong); } if (!catalogCache.TryGetValue(filename, out ushort ts)) { return(Errno.NoSuchFile); } ulong lba = (ulong)(((ts & 0xFF00) >> 8) * sectorsPerTrack + (ts & 0xFF)); MemoryStream fileMs = new MemoryStream(); MemoryStream tsListMs = new MemoryStream(); ushort expectedBlock = 0; while (lba != 0) { usedSectors++; byte[] tsSectorB = device.ReadSector(lba); if (debug) { tsListMs.Write(tsSectorB, 0, tsSectorB.Length); } // Read the track/sector list sector IntPtr tsPtr = Marshal.AllocHGlobal(256); Marshal.Copy(tsSectorB, 0, tsPtr, 256); TrackSectorList tsSector = (TrackSectorList)Marshal.PtrToStructure(tsPtr, typeof(TrackSectorList)); Marshal.FreeHGlobal(tsPtr); if (tsSector.sectorOffset > expectedBlock) { byte[] hole = new byte[(tsSector.sectorOffset - expectedBlock) * vtoc.bytesPerSector]; fileMs.Write(hole, 0, hole.Length); expectedBlock = tsSector.sectorOffset; } foreach (TrackSectorListEntry entry in tsSector.entries) { track1UsedByFiles |= entry.track == 1; track2UsedByFiles |= entry.track == 2; usedSectors++; ulong blockLba = (ulong)(entry.track * sectorsPerTrack + entry.sector); if (blockLba == 0) { break; } byte[] fileBlock = device.ReadSector(blockLba); fileMs.Write(fileBlock, 0, fileBlock.Length); expectedBlock++; } lba = (ulong)(tsSector.nextListTrack * sectorsPerTrack + tsSector.nextListSector); } if (fileCache.ContainsKey(filename)) { fileCache.Remove(filename); } if (extentCache.ContainsKey(filename)) { extentCache.Remove(filename); } fileCache.Add(filename, fileMs.ToArray()); extentCache.Add(filename, tsListMs.ToArray()); return(Errno.NoError); }
Errno CacheFile(string path) { string[] pathElements = path.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries); if (pathElements.Length != 1) { return(Errno.NotSupported); } string filename = pathElements[0].ToUpperInvariant(); if (filename.Length > 30) { return(Errno.NameTooLong); } if (!_catalogCache.TryGetValue(filename, out ushort ts)) { return(Errno.NoSuchFile); } ulong lba = (ulong)((((ts & 0xFF00) >> 8) * _sectorsPerTrack) + (ts & 0xFF)); var fileMs = new MemoryStream(); var tsListMs = new MemoryStream(); ushort expectedBlock = 0; while (lba != 0) { _usedSectors++; byte[] tsSectorB = _device.ReadSector(lba); if (_debug) { tsListMs.Write(tsSectorB, 0, tsSectorB.Length); } // Read the track/sector list sector TrackSectorList tsSector = Marshal.ByteArrayToStructureLittleEndian <TrackSectorList>(tsSectorB); if (tsSector.sectorOffset > expectedBlock) { byte[] hole = new byte[(tsSector.sectorOffset - expectedBlock) * _vtoc.bytesPerSector]; fileMs.Write(hole, 0, hole.Length); expectedBlock = tsSector.sectorOffset; } foreach (TrackSectorListEntry entry in tsSector.entries) { _track1UsedByFiles |= entry.track == 1; _track2UsedByFiles |= entry.track == 2; _usedSectors++; ulong blockLba = (ulong)((entry.track * _sectorsPerTrack) + entry.sector); if (blockLba == 0) { break; } byte[] fileBlock = _device.ReadSector(blockLba); fileMs.Write(fileBlock, 0, fileBlock.Length); expectedBlock++; } lba = (ulong)((tsSector.nextListTrack * _sectorsPerTrack) + tsSector.nextListSector); } if (_fileCache.ContainsKey(filename)) { _fileCache.Remove(filename); } if (_extentCache.ContainsKey(filename)) { _extentCache.Remove(filename); } _fileCache.Add(filename, fileMs.ToArray()); _extentCache.Add(filename, tsListMs.ToArray()); return(Errno.NoError); }