public Folder(FATXDrive DRIVE, PartitionInfo partition) { PartInfo = partition; e = new Entries(this); Drive = DRIVE; Misc = new Misc(); isfolder = true; }
/// <summary> /// Used for quickly reading bytes for a length that is not a multiple of 0x200 /// </summary> internal byte[] ReadBytes(ref FATX_Browser.FATX.IOReader br, long length) { Misc m = new Misc(); m.UpToNearest200(length); byte[] buffer = br.ReadBytes((int)length); List<byte> bl = buffer.ToList<byte>(); bl.RemoveRange((int)(length - 1), (int)(buffer.Length - length)); buffer = bl.ToArray(); return buffer; }
public File(FATXDrive DRIVE, PartitionInfo partition) { PartInfo = partition; e = new Entries(this); Drive = DRIVE; Misc = new Misc(); }
/// <summary> /// Total size of the partition (in bytes) /// </summary> public long PartitionSize() { if (Partition.Size == 0) { long psize = 0; Misc m = new Misc(); if (ourDrive.DriveType == Info.DriveType.Backup | ourDrive.DriveType == Info.DriveType.HDD) { switch (Partition.Offset) { case (long)Info.HDDFATX.Partitions.Compatibility: psize = (long)Info.HDDFATX.Lengths.Compatibility; break; case (long)Info.HDDFATX.Partitions.Data: if (ourDrive.DriveType == Info.DriveType.HDD) { FATX.IO.HDDFATX hddio = new IO.HDDFATX(false, null); psize = (ourDrive.DriveSize - Partition.Offset); } else { psize = (ourDrive.DriveSize - Partition.Offset); } break; case (long)Info.HDDFATX.Partitions.GameCache: psize = (long)Info.HDDFATX.Lengths.GameCache; break; case (long)Info.HDDFATX.Partitions.SystemCache: psize = (long)Info.HDDFATX.Lengths.SystemCache; break; } } else { switch (Partition.Offset) { case (long)Info.USBOffsets.Cache: psize = (long)Info.USBPartitionSizes.Cache; break; case (long)Info.USBOffsets.Data: psize = (long)Info.USBOffsets.Data + 0x1000 + FATSize(); break; } } if (psize == 0) { psize = ourDrive.GetIO().BaseStream.Length; } Partition.Size = psize; } return Partition.Size; }
public Write(FATXDrive drive) { ourDrive = drive; m = new Misc(); }
/// <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"); }
/// <summary> /// Partition ID /// </summary> public uint PartitionID() { uint rVal = 0; Misc m = new Misc(); //Open our binary reader FATX_Browser.FATX.IOReader br = ourDrive.GetIO(); //Seek to the data partition offset br.BaseStream.Position = Partition.Offset; //Read our buffer FATX_Browser.FATX.IOReader mem = new FATX_Browser.FATX.IOReader(new System.IO.MemoryStream(br.ReadBytes(0x200))); br.Close(); mem.BaseStream.Position = 0x4; rVal = m.ReadUInt32(ref mem); mem.Close(); return rVal; }
//For reading a single block private byte[] GetOccupiedBlock(uint baseBlock) { //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(baseBlock, Holder); BufferOffset = BufferOffset - (BufferOffset % 0x200); long BlockOffsetInBuffer = m.BlockToFATOffset(baseBlock, 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; byte[] rVal = mem.ReadBytes(EntrySize); //The following checks to see if the next block in the sequence is uint nextBlock; if (EntrySize == 4) { byte[] blockCopy = rVal; nextBlock = BitConverter.ToUInt32(blockCopy, 0x0); } else { byte[] blockCopy = rVal; nextBlock = BitConverter.ToUInt16(blockCopy, 0x0); } mem.Close(); return rVal; }
/// <summary> /// Number of File Allocation Tables /// </summary> public uint FATCopies() { uint rVal = 0; Misc m = new Misc(); //Open our binary reader FATX_Browser.FATX.IOReader br = ourDrive.GetIO(); //Seek to the data partition offset + 0xC (where the FATCopies int is) br.BaseStream.Position = Partition.Offset; //Create our mem reader / buffer FATX_Browser.FATX.IOReader mem = new FATX_Browser.FATX.IOReader(new System.IO.MemoryStream(br.ReadBytes(0x200))); br.Close(); mem.BaseStream.Position = 0xC; //Get our value (uses outside class for bigendian) rVal = m.ReadUInt32(ref mem); mem.Close(); return rVal; }
/// <summary> /// Returns EntryData for an entry in a block /// </summary> /// <param name="br">The binary reader to use</param> /// <param name="EntryBlock">The entry in the block to read</param> /// <param name="Block">The block to read from</param> internal EntryData GetEData(long originalOffset, FATX_Browser.FATX.IOReader br, uint EntryBlock, uint Block) { Misc r = new Misc(); //br.BaseStream.Position = 0x131229000;//(r.GetBlockOffset(Block, Partition, DeviceID)) + (0x40 * EntryBlock); //Create our return EntryData data = new EntryData(); //Read our variables data.EntryOffset = originalOffset + br.BaseStream.Position; data.FileNameSize = br.ReadByte(); data.Flags = br.ReadByte(); data.FileName = Encoding.ASCII.GetString(br.ReadBytes((int)data.FileNameSize)); //Go to the end of the name to continue reading the variables br.BaseStream.Position += (0x2A - (int)data.FileNameSize); data.StartingCluster = r.ReadUInt32(ref br); data.Size = r.ReadUInt32(ref br); data.CreationDate = r.ReadUInt16(ref br); data.CreationTime = r.ReadUInt16(ref br); data.AccessDate = r.ReadUInt16(ref br); data.AccessTime = r.ReadUInt16(ref br); data.ModifiedDate = r.ReadUInt16(ref br); data.ModifiedTime = r.ReadUInt16(ref br); //br.BaseStream.Position += 0xC; br.Close(); return data; //TODO: Datetime conversion from FAT to DateTime }
internal bool ExtractFileInternal(File f, FATX_Browser.FATX.IOWriter outIO, ref long sizeWritten, ref long maxVal) { //Create our binaryreader FATX_Browser.FATX.IOReader br; try { //Create our new misc class Misc m = new Misc(); //Create our blocks occupied list to speed some things up if the //blocks haven't been loaded yet System.Diagnostics.Stopwatch s = new System.Diagnostics.Stopwatch(); s.Start(); List<uint> BlocksOccupied = f.BlocksOccupied.ToList<uint>(); maxVal = BlocksOccupied.Count; if (BlocksOccupied.Count >= 1) { //Get our IO... br = xDrive.GetIO(); //For each loop increase our sizewritten, and keep looping //until we've reached the block BEFORE the final (size may not //be 0x4000 bytes) for (int i = 0; i < BlocksOccupied.Count - 1; i++, sizeWritten++) { //Get and set our reader position long position = m.GetBlockOffset(BlocksOccupied.ToArray()[i], f.PartInfo); br.BaseStream.Position = position; //Write to our output file what we just read outIO.Write(br.ReadBytes((int)f.PartInfo.ClusterSize)); br.BaseStream.Flush(); outIO.BaseStream.Flush(); } //KAY, now we've reached the final block in the series br.BaseStream.Position = m.GetBlockOffset(BlocksOccupied.ToArray()[BlocksOccupied.Count - 1], f); //Right here, we read the remaining data, and write it all //in one swoop outIO.Write(m.ReadBytes(ref br, m.RemainingData(f))); br.BaseStream.Flush(); outIO.BaseStream.Flush(); //Close our IO's br.Close(); outIO.Close(); sizeWritten++; return true; } return false; } catch (Exception e) { outIO.Close(); throw e; } }
/// <summary> /// Returns an array of EntryData for a specified block /// </summary> /// <param name="block">The block to read from</param> public EntryData[] GetEntries(uint block) { FATX_Browser.FATX.IOReader br = xDrive.GetIO(); //Get the block offset Misc r = new Misc(); br.BaseStream.Position = r.GetBlockOffset(block, Holder.PartInfo); long position = br.BaseStream.Position; //Create another binary reader that will hold our 0x200 bytes to read //(we can not seek to something that's not a multiple of 0x200) long OOFFSET = br.BaseStream.Position; byte[] buffer = br.ReadBytes(0x200); //Our placeholder for the bytes in the buffer read int bufferRead = 0; List<EntryData> l = new List<EntryData>(); for (uint i = 1; i <= 100; i++) { //If we've reached the end of the buffer if (bufferRead == 0x200) { OOFFSET = br.BaseStream.Position; //Read the next 0x200 bytes buffer = br.ReadBytes(0x200); bufferRead = 0; } //Create our stream for the reader FATX_Browser.FATX.IOReader mem = new FATX_Browser.FATX.IOReader(new System.IO.MemoryStream(buffer)); mem.BaseStream.Position = bufferRead; //Make sure that we're not at the end of the block byte[] end = mem.ReadBytes(2); if (EOF(end, true)) { break; } //We have to reset the reader back to the beginning of the block mem.BaseStream.Position -= 0x2; l.Add(GetEData(OOFFSET, mem, i, block)); position += 0x40; bufferRead += 0x40; br.BaseStream.Position = position; mem.Close(); } br.Close(); return l.ToArray(); }
//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(); }
/// <summary> /// Extracts your file to the specified path /// </summary> /// <param name="f">File to extract</param> /// <param name="path">Path to extract the file to</param> /// <param name="sizeWritten">Used for updating progress on the file(not necessary)</param> /// <param name="maxVal">Used for updating the file size (not necessary)</param> public bool ExtractFile(File f, string path, ref long sizeWritten, ref long maxVal) { //try // { Misc m = new Misc(); //Create our binary writer FATX_Browser.FATX.IOWriter bw = new FATX_Browser.FATX.IOWriter(new System.IO.FileStream(path, System.IO.FileMode.Create)); //Set our maxVal maxVal = f.Block; sizeWritten = 0; return ExtractFileInternal(f, bw, ref sizeWritten, ref maxVal); // } //catch { return false; } }