public void ClearFATChain(uint[] Chain) { Streams.Reader r = Parent.Drive.Reader(); Streams.Writer w = new CLKsFATXLib.Streams.Writer(r.BaseStream); long buffersize = 0x1000; long lastoffset = 0;//VariousFunctions.BlockToFATOffset(Chain[0], Parent).DownToNearestCluster(buffersize); byte[] Buffer = new byte[buffersize]; for (int i = 0; i < Chain.Length; i++) { // Read the chain buffer if (lastoffset != VariousFunctions.BlockToFATOffset(Chain[i], Parent).DownToNearestCluster(0x1000)) { if (i != 0) { w.BaseStream.Position = lastoffset; w.Write(Buffer); } lastoffset = VariousFunctions.BlockToFATOffset(Chain[i], Parent).DownToNearestCluster(0x1000); r.BaseStream.Position = lastoffset; Buffer = r.ReadBytes((int)buffersize); } // Write the chain Streams.Writer mem = new CLKsFATXLib.Streams.Writer(new System.IO.MemoryStream(Buffer)); mem.BaseStream.Position = VariousFunctions.BlockToFATOffset(Chain[i], Parent) - VariousFunctions.BlockToFATOffset(Chain[i], Parent).DownToNearestCluster(0x1000); byte[] writing = new byte[0]; switch (Parent.PartitionInfo.EntrySize) { case 2: writing = BitConverter.GetBytes((ushort)0); break; case 4: writing = BitConverter.GetBytes(0); break; } mem.Write(writing); mem.Close(); if (i == Chain.Length - 1) { w.BaseStream.Position = lastoffset; w.Write(Buffer); } } }
public long GetNewEntryOffset(Folder Destination) { // Go to the last block since we want to speed things up and not have to go // through all of them EntryData[] Entries = EntryDataFromBlock(Destination.BlocksOccupied[Destination.BlocksOccupied.Length - 1]); if (Entries.Length == 0) { return(Destination.StartingOffset); } // If there isn't the maximum amount of entries for a cluster... if (Entries.Length < Destination.PartitionInfo.ClusterSize / 0x40) { foreach (EntryData e in Entries) { if (e.NameSize == 0xE5) { return(e.EntryOffset); } } return(Entries[Entries.Length - 1].EntryOffset + 0x40); } // Max amount of entries, let's add another cluster to our parent... else { uint[] NewBlocks = new uint[Destination.BlocksOccupied.Length + 1]; Array.Copy(Destination.BlocksOccupied, NewBlocks, Destination.BlocksOccupied.Length); NewBlocks[NewBlocks.Length - 1] = Destination.Drive.GetFreeBlocks((Folder)Destination, 1, 0, 0, false)[0]; byte[] FF = new byte[Destination.PartitionInfo.ClusterSize]; for (int i = 0; i < FF.Length; i++) { FF[i] = 0xFF; } Streams.Writer w = Destination.Drive.Writer(); w.BaseStream.Position = VariousFunctions.BlockToFATOffset(NewBlocks[NewBlocks.Length - 1], Destination); w.Write(FF); Destination.BlocksOccupied = NewBlocks; return(VariousFunctions.BlockToFATOffset(NewBlocks[NewBlocks.Length - 1], Destination)); } }
/// <summary> /// Returns an array of free blocks based off of the number of blocks needed /// </summary> public uint[] GetFreeBlocks(Folder Partition, int blocksNeeded, uint StartBlock, long end, bool SecondLoop) { int Clustersize = 0x10000; uint Block = StartBlock; if (end == 0) { end = Partition.PartitionInfo.FATOffset + Partition.PartitionInfo.FATSize; } List <uint> BlockList = new List <uint>(); // Create our reader for the drive Streams.Reader br = Reader(); // Create our reader for the memory stream Streams.Reader mr = null; for (long i = VariousFunctions.DownToNearest200(VariousFunctions.BlockToFATOffset(StartBlock, Partition)); i < end; i += Clustersize) { //Set our position to i br.BaseStream.Position = i; byte[] buffer = new byte[0]; if ((end - i) < Clustersize) { buffer = VariousFunctions.ReadBytes(ref br, end - i); } else { //Read our buffer buffer = br.ReadBytes(Clustersize); } try { mr.Close(); } catch { } mr = new Streams.Reader(new System.IO.MemoryStream(buffer)); //Re-open our binary reader using the buffer/memory stream for (int j = 0; j < buffer.Length; j += (int)Partition.PartitionInfo.EntrySize, Block += (uint)Partition.PartitionInfo.EntrySize) { mr.BaseStream.Position = j; //If we've gotten all of our requested blocks... if (BlockList.Count == blocksNeeded) { //Close our reader -> break the loop mr.Close(); break; } //Read the next block entry byte[] reading = mr.ReadBytes((int)Partition.PartitionInfo.EntrySize); //For each byte in our reading for (int k = 0; k < reading.Length; k++) { //If the byte isn't null (if the block isn't open) if (reading[k] != 0x00) { //Break break; } //If we've reached the end of the array, and the last byte //is 0x00, then the block is free if (k == reading.Length - 1 && reading[k] == 0x00) { //Do some maths to get the block numbah long fOff = Partition.PartitionInfo.FATOffset; long blockPosition = (long)i + j; uint block = (uint)(blockPosition - fOff) / (uint)Partition.PartitionInfo.EntrySize; BlockList.Add(block); } } } //We're putting in one last check so that we don't loop more than we need to if (BlockList.Count == blocksNeeded) { break; } } //If we found the required amount of free blocks - return our list if (BlockList.Count == blocksNeeded) { return(BlockList.ToArray()); } //If we didn't find the amount of blocks required, but we started from a //block other than the first one... if (BlockList.Count < blocksNeeded && SecondLoop == false) { BlockList.AddRange(GetFreeBlocks(Partition, blocksNeeded - BlockList.Count, 1, VariousFunctions.DownToNearest200(VariousFunctions.BlockToFATOffset(StartBlock, Partition)), true)); return(BlockList.ToArray()); } //We didn't find the amount of free blocks required, meaning we're ref of //disk space if (BlockList.Count != blocksNeeded) { throw new Exception("Out of Xbox 360 hard disk space"); } return(BlockList.ToArray()); }
public uint[] GetBlocksOccupied() { List <uint> Blocks = new List <uint>(); Streams.Reader r = Parent.Drive.Reader(); Blocks.Add(Parent.StartingCluster); byte[] Buffer = new byte[0x1000]; int buffersize = 0x1000; long lastoffset = 0; for (int i = 0; i < Blocks.Count; i++) { r.BaseStream.Position = VariousFunctions.BlockToFATOffset(Blocks[i], Parent).DownToNearestCluster(0x1000); // We use this so that we aren't reading the same buffer // a zillion times if (r.BaseStream.Position != lastoffset) { lastoffset = r.BaseStream.Position; Buffer = r.ReadBytes(buffersize); } Streams.Reader r1 = new CLKsFATXLib.Streams.Reader(new System.IO.MemoryStream(Buffer)); int OffsetInBuffer = (int)(VariousFunctions.BlockToFATOffset(Blocks[i], Parent) - VariousFunctions.BlockToFATOffset(Blocks[i], Parent).DownToNearestCluster(0x1000)); r1.BaseStream.Position = OffsetInBuffer; switch (Parent.PartitionInfo.EntrySize) { case 2: ushort Value = r1.ReadUInt16(); if (Value != 0xFFFF && Value != 0xFFF8) { if (Value == 0) { EntryData ed = Parent.EntryData; ed.NameSize = 0xE5; CreateNewEntry(ed); if (Blocks.Count > 0) { ClearFATChain(Blocks.ToArray()); } throw new Exception(string.Format("Bad FAT chain in file or folder {0}\r\nEntry Offset: 0x{1}\r\nLast block in FAT: 0x{2}\r\nEntry marked as deleted to avoid further errors! Please reload this device", Parent.FullPath, Parent.EntryOffset.ToString("X"), Blocks.Last().ToString("X"))); } Blocks.Add(Value); } break; case 4: uint Value2 = r1.ReadUInt32(); if (Value2 != 0xFFFFFFFF && Value2 != 0xFFFFFFF8) { if (Value2 == 0) { EntryData ed = Parent.EntryData; ed.NameSize = 0xE5; CreateNewEntry(ed); if (Blocks.Count > 0) { ClearFATChain(Blocks.ToArray()); } throw new Exception(string.Format("Bad FAT chain in file or folder {0}\r\nEntry Offset: 0x{1}\r\nLast block in FAT: 0x{2}\r\nEntry marked as deleted to avoid further errors! Please reload this device", Parent.FullPath, Parent.EntryOffset.ToString("X"), Blocks.Last().ToString("X"))); } Blocks.Add(Value2); } break; } r1.Close(); } return(Blocks.ToArray()); }