/// <summary> /// Returns an array of free blocks based off of the number of blocks needed /// </summary> public uint[] GetFreeBlocks(int blocksNeeded, uint StartBlock, long end, bool SecondLoop) { int Clustersize = 0x1000; uint Block = StartBlock; if (end == 0) { end = DataOffset(); } List<uint> BlockList = new List<uint>(); Misc m = new Misc(); for (long i = m.DownToNearest200(m.BlockToFATOffset(StartBlock, Partition)); i < end; i += Clustersize) { //Create our reader FATX_Browser.FATX.IOReader br = ourDrive.GetIO(); //Set our position to i br.BaseStream.Position = i; //Read our buffer byte[] buffer = br.ReadBytes(Clustersize); br.Close(); //Re-open our binary reader using the buffer/memory stream for (int j = 0; j < Clustersize; j+= (int)Partition.EntrySize, Block += (uint)Partition.EntrySize) { br = new FATX_Browser.FATX.IOReader(new System.IO.MemoryStream(buffer)); br.BaseStream.Position = j; //If we've gotten all of our requested blocks... if (BlockList.ToArray().Length == blocksNeeded) { //Close our reader -> break the loop br.Close(); break; } //Read the next block entry byte[] reading = br.ReadBytes((int)Partition.EntrySize); //Close our reader - it's no longer needed br.Close(); //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 = FATOffset; long blockPosition = (long)i + j; uint block = (uint)(blockPosition - fOff) / (uint)EntrySize; BlockList.Add(block); } } } //We're putting in one last check so that we don't loop more than we need to if (BlockList.ToArray().Length == 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(blocksNeeded - BlockList.ToArray().Length, 1, m.DownToNearest200(m.BlockToFATOffset(StartBlock, Partition)), true)); } //We didn't find the amount of free blocks required, meaning we're out of //disk space throw new Exception("Out of Xbox 360 hard disk space"); }
//For getting an array of blocks occupied /// <summary> /// Returns an array of blocks that a file/folder entry occupies /// </summary> /// <param name="baseBlock">The base block to read from the FAT chain (the root)</param> public uint[] GetBlocksOccupied(uint baseBlock) { //Create our list to hold the uints List<uint> l = new List<uint>(); l.Add(baseBlock); //Create a new byte array with random input byte[] ourReturn = { 0xAA, 0xAA }; //Increase the number of blocks - keep the loop going until we've //reached the end of the blocks (0xFFFF or equal) for (int i = 0; !EOF(ourReturn, false); i++) { uint CurrentBlock = l.ToArray()[i]; //Get our next block in the series //Create our list of our Misc m = new Misc(); //Create our binary reader FATX_Browser.FATX.IOReader br = xDrive.GetIO(); //Read our buffer to load in to the memory stream long BufferOffset = m.BlockToFATOffset(CurrentBlock, Holder); BufferOffset = BufferOffset - (BufferOffset % 0x200); long BlockOffsetInBuffer = m.BlockToFATOffset(CurrentBlock, Holder) - BufferOffset; //Go to the buffer we're reading's offset br.BaseStream.Position = BufferOffset; //Read our buffer byte[] buffer = br.ReadBytes(0x200); br.Close(); //Re-open our reader using the memorystream this time FATX_Browser.FATX.IOReader mem = new FATX_Browser.FATX.IOReader(new System.IO.MemoryStream(buffer)); //Close our reader mem.BaseStream.Position = BlockOffsetInBuffer; ourReturn = mem.ReadBytes(EntrySize); mem.Close(); //If the block is the ending block if (EOF(ourReturn, false)) { //Break break; } //The block isn't the ending block, reverse the array so we can //convert it to big endian uintxx Array.Reverse(ourReturn); //Create our value to add to the list uint addVal; if (bit == Info.PartitionBit.FATX32) { addVal = BitConverter.ToUInt32(ourReturn, 0); } else { addVal = BitConverter.ToUInt16(ourReturn, 0); } //Add our value to the list l.Add(addVal); Array.Reverse(ourReturn); if (BufferOffset == (long)(m.DownToNearest200(m.BlockToFATOffset(addVal, Holder)))) { object[] stuff = CheckBlock(ref buffer, ourReturn, BufferOffset); l.AddRange(((List<uint>)stuff[1]).ToArray()); i += ((List<uint>)stuff[1]).Count; if ((bool)stuff[0] == true) { break; } } } return l.ToArray(); }