private ExtentBlock LoadExtentBlock(ExtentIndex idxEntry) { uint blockSize = _context.SuperBlock.BlockSize; _context.RawStream.Position = idxEntry.LeafPhysicalBlock * blockSize; byte[] buffer = StreamUtilities.ReadFully(_context.RawStream, (int)blockSize); ExtentBlock subBlock = EndianUtilities.ToStruct <ExtentBlock>(buffer, 0); return(subBlock); }
public override int Read(long pos, byte[] buffer, int offset, int count) { if (pos > _inode.FileSize) { return(0); } long blockSize = _context.SuperBlock.BlockSize; int totalRead = 0; int totalBytesRemaining = (int)Math.Min(count, _inode.FileSize - pos); ExtentBlock extents = _inode.Extents; while (totalBytesRemaining > 0) { uint logicalBlock = (uint)((pos + totalRead) / blockSize); int blockOffset = (int)(pos + totalRead - logicalBlock * blockSize); int numRead = 0; Extent extent = FindExtent(extents, logicalBlock); if (extent == null) { throw new IOException("Unable to find extent for block " + logicalBlock); } if (extent.FirstLogicalBlock > logicalBlock) { numRead = (int) Math.Min(totalBytesRemaining, (extent.FirstLogicalBlock - logicalBlock) * blockSize - blockOffset); Array.Clear(buffer, offset + totalRead, numRead); } else { long physicalBlock = logicalBlock - extent.FirstLogicalBlock + (long)extent.FirstPhysicalBlock; int toRead = (int) Math.Min(totalBytesRemaining, (extent.NumBlocks - (logicalBlock - extent.FirstLogicalBlock)) * blockSize - blockOffset); _context.RawStream.Position = physicalBlock * blockSize + blockOffset; numRead = _context.RawStream.Read(buffer, offset + totalRead, toRead); } totalBytesRemaining -= numRead; totalRead += numRead; } return(totalRead); }
public int ReadFrom(byte[] buffer, int offset) { Mode = Utilities.ToUInt16LittleEndian(buffer, offset + 0); UserIdLow = Utilities.ToUInt16LittleEndian(buffer, offset + 2); FileSize = Utilities.ToUInt32LittleEndian(buffer, offset + 4); AccessTime = Utilities.ToUInt32LittleEndian(buffer, offset + 8); CreationTime = Utilities.ToUInt32LittleEndian(buffer, offset + 12); ModificationTime = Utilities.ToUInt32LittleEndian(buffer, offset + 16); DeletionTime = Utilities.ToUInt32LittleEndian(buffer, offset + 20); GroupIdLow = Utilities.ToUInt16LittleEndian(buffer, offset + 24); LinksCount = Utilities.ToUInt16LittleEndian(buffer, offset + 26); BlocksCount = Utilities.ToUInt32LittleEndian(buffer, offset + 28); Flags = (InodeFlags)Utilities.ToUInt32LittleEndian(buffer, offset + 32); FastSymlink = null; Extents = null; DirectBlocks = null; if (FileType == UnixFileType.Link && BlocksCount == 0) { FastSymlink = new byte[60]; Array.Copy(buffer, offset + 40, FastSymlink, 0, 60); } else if ((Flags & InodeFlags.ExtentsUsed) != 0) { Extents = Utilities.ToStruct <ExtentBlock>(buffer, offset + 40); } else { DirectBlocks = new uint[12]; for (int i = 0; i < 12; ++i) { DirectBlocks[i] = Utilities.ToUInt32LittleEndian(buffer, offset + 40 + i * 4); } IndirectBlock = Utilities.ToUInt32LittleEndian(buffer, offset + 88); DoubleIndirectBlock = Utilities.ToUInt32LittleEndian(buffer, offset + 92); TripleIndirectBlock = Utilities.ToUInt32LittleEndian(buffer, offset + 96); } FileVersion = Utilities.ToUInt32LittleEndian(buffer, offset + 100); FileAcl = Utilities.ToUInt32LittleEndian(buffer, offset + 104); DirAcl = Utilities.ToUInt32LittleEndian(buffer, offset + 108); FragAddress = Utilities.ToUInt32LittleEndian(buffer, offset + 112); Fragment = buffer[offset + 116]; FragmentSize = buffer[offset + 117]; UserIdHigh = Utilities.ToUInt16LittleEndian(buffer, offset + 120); GroupIdHigh = Utilities.ToUInt16LittleEndian(buffer, offset + 122); return(128); }
private Extent FindExtent(ExtentBlock node, uint logicalBlock) { if (node.Index != null) { ExtentIndex idxEntry = null; if (node.Index.Length == 0) { return(null); } if (node.Index[0].FirstLogicalBlock >= logicalBlock) { idxEntry = node.Index[0]; } else { for (int i = 0; i < node.Index.Length; ++i) { if (node.Index[i].FirstLogicalBlock > logicalBlock) { idxEntry = node.Index[i - 1]; break; } } } if (idxEntry == null) { idxEntry = node.Index[node.Index.Length - 1]; } ExtentBlock subBlock = LoadExtentBlock(idxEntry); return(FindExtent(subBlock, logicalBlock)); } if (node.Extents != null) { Extent entry = null; if (node.Extents.Length == 0) { return(null); } if (node.Extents[0].FirstLogicalBlock >= logicalBlock) { return(node.Extents[0]); } for (int i = 0; i < node.Extents.Length; ++i) { if (node.Extents[i].FirstLogicalBlock > logicalBlock) { entry = node.Extents[i - 1]; break; } } if (entry == null) { entry = node.Extents[node.Extents.Length - 1]; } return(entry); } return(null); }
private Extent FindExtent(ExtentBlock node, uint logicalBlock) { if (node.Index != null) { ExtentIndex idxEntry = null; if (node.Index.Length == 0) { return null; } else if (node.Index[0].FirstLogicalBlock >= logicalBlock) { idxEntry = node.Index[0]; } else { for (int i = 0; i < node.Index.Length; ++i) { if (node.Index[i].FirstLogicalBlock > logicalBlock) { idxEntry = node.Index[i - 1]; break; } } } if (idxEntry == null) { idxEntry = node.Index[node.Index.Length - 1]; } ExtentBlock subBlock = LoadExtentBlock(idxEntry); return FindExtent(subBlock, logicalBlock); } else if (node.Extents != null) { Extent entry = null; if (node.Extents.Length == 0) { return null; } else if (node.Extents[0].FirstLogicalBlock >= logicalBlock) { return node.Extents[0]; } else { for (int i = 0; i < node.Extents.Length; ++i) { if (node.Extents[i].FirstLogicalBlock > logicalBlock) { entry = node.Extents[i - 1]; break; } } } if (entry == null) { entry = node.Extents[node.Extents.Length - 1]; } return entry; } else { return null; } }
public int ReadFrom(byte[] buffer, int offset) { Mode = Utilities.ToUInt16LittleEndian(buffer, offset + 0); UserIdLow = Utilities.ToUInt16LittleEndian(buffer, offset + 2); FileSize = Utilities.ToUInt32LittleEndian(buffer, offset + 4); AccessTime = Utilities.ToUInt32LittleEndian(buffer, offset + 8); CreationTime = Utilities.ToUInt32LittleEndian(buffer, offset + 12); ModificationTime = Utilities.ToUInt32LittleEndian(buffer, offset + 16); DeletionTime = Utilities.ToUInt32LittleEndian(buffer, offset + 20); GroupIdLow = Utilities.ToUInt16LittleEndian(buffer, offset + 24); LinksCount = Utilities.ToUInt16LittleEndian(buffer, offset + 26); BlocksCount = Utilities.ToUInt32LittleEndian(buffer, offset + 28); Flags = (InodeFlags)Utilities.ToUInt32LittleEndian(buffer, offset + 32); FastSymlink = null; Extents = null; DirectBlocks = null; if (FileType == UnixFileType.Link && BlocksCount == 0) { FastSymlink = new byte[60]; Array.Copy(buffer, offset + 40, FastSymlink, 0, 60); } else if ((Flags & InodeFlags.ExtentsUsed) != 0) { Extents = Utilities.ToStruct<ExtentBlock>(buffer, offset + 40); } else { DirectBlocks = new uint[12]; for (int i = 0; i < 12; ++i) { DirectBlocks[i] = Utilities.ToUInt32LittleEndian(buffer, offset + 40 + (i * 4)); } IndirectBlock = Utilities.ToUInt32LittleEndian(buffer, offset + 88); DoubleIndirectBlock = Utilities.ToUInt32LittleEndian(buffer, offset + 92); TripleIndirectBlock = Utilities.ToUInt32LittleEndian(buffer, offset + 96); } FileVersion = Utilities.ToUInt32LittleEndian(buffer, offset + 100); FileAcl = Utilities.ToUInt32LittleEndian(buffer, offset + 104); DirAcl = Utilities.ToUInt32LittleEndian(buffer, offset + 108); FragAddress = Utilities.ToUInt32LittleEndian(buffer, offset + 112); Fragment = buffer[offset + 116]; FragmentSize = buffer[offset + 117]; UserIdHigh = Utilities.ToUInt16LittleEndian(buffer, offset + 120); GroupIdHigh = Utilities.ToUInt16LittleEndian(buffer, offset + 122); return 128; }