private void WriteData(Stream stream) { Log("Writing data..."); hdr.WriteToStream(stream); WriteInodes(stream); WriteSuperrootDirents(stream); allNodes.Insert(0, new FSFile(s => fpt.WriteToStream(s), "flat_path_table", fpt.Size) { ino = fpt_ino }); if (colResolver != null) { allNodes.Insert(1, new FSFile(s => colResolver.WriteToStream(s), "collision_resolver", colResolver.Size) { ino = cr_ino }); } for (var x = 0; x < allNodes.Count; x++) { var f = allNodes[x]; stream.Position = f.ino.StartBlock * hdr.BlockSize; WriteFSNode(stream, f); } }
/// <summary> /// Builds and saves a PFS image. /// </summary> /// <param name="p"></param> public void BuildPfs(PfsProperties p) { // TODO: Combine the superroot-specific stuff with the rest of the data block writing. // I think this is as simple as adding superroot and flat_path_table to allNodes hdr = new PfsHeader { BlockSize = p.BlockSize }; inodes = new List <PfsDinode32>(); dirents = new List <List <PfsDirent> >(); Console.WriteLine("Setting up root structure..."); SetupRootStructure(); BuildFSTree(root, p.proj, p.projDir); allDirs = root.GetAllChildrenDirs(); allFiles = root.GetAllChildrenFiles(); allNodes = new List <FSNode>(allDirs); allNodes.AddRange(allFiles); Console.WriteLine("Creating directory inodes ({0})...", allDirs.Count); addDirInodes(); Console.WriteLine("Creating file inodes ({0})...", allFiles.Count); addFileInodes(); Console.WriteLine("Creating flat_path_table..."); fpt = new FlatPathTable(allNodes); Console.WriteLine("Calculating data block layout..."); allNodes.Insert(0, root); CalculateDataBlockLayout(); Console.WriteLine("Writing image file..."); hdr.Ndblock = allFiles.Sum((f) => CeilDiv(f.Size, hdr.BlockSize)); { var stream = p.output; Console.WriteLine("Writing header..."); hdr.WriteToStream(stream); Console.WriteLine("Writing inodes..."); WriteInodes(stream); Console.WriteLine("Writing superroot dirents"); WriteSuperrootDirents(stream); Console.WriteLine("Writing flat_path_table"); stream.Position = fpt_ino.db[0] * hdr.BlockSize; fpt.WriteToStream(stream); Console.WriteLine("Writing data blocks..."); for (var x = 0; x < allNodes.Count; x++) { var f = allNodes[x]; stream.Position = f.ino.db[0] * hdr.BlockSize; WriteFSNode(stream, f); } } }
private void WriteData(Stream stream) { Log("Writing data..."); hdr.WriteToStream(stream); WriteInodes(stream); WriteSuperrootDirents(stream); var fpt_file = new FSFile(s => fpt.WriteToStream(s), "flat_path_table", fpt.Size); fpt_file.ino = fpt_ino; allNodes.Insert(0, fpt_file); for (var x = 0; x < allNodes.Count; x++) { var f = allNodes[x]; stream.Position = f.ino.StartBlock * hdr.BlockSize; WriteFSNode(stream, f); } }
public void WriteImage(Stream stream) { Log("Writing header..."); hdr.WriteToStream(stream); Log("Writing inodes..."); WriteInodes(stream); Log("Writing superroot dirents"); WriteSuperrootDirents(stream); var fpt_file = new FSFile(s => fpt.WriteToStream(s), "flat_path_table", fpt.Size); fpt_file.ino = fpt_ino; allNodes.Insert(0, fpt_file); Log("Writing data blocks..."); for (var x = 0; x < allNodes.Count; x++) { var f = allNodes[x]; stream.Position = f.ino.StartBlock * hdr.BlockSize; WriteFSNode(stream, f); } stream.SetLength(hdr.Ndblock * hdr.BlockSize); if (hdr.Mode.HasFlag(PfsMode.Signed)) { Log("Signing..."); var signKey = Crypto.PfsGenSignKey(properties.EKPFS, hdr.Seed); foreach (var sig in sig_order) { var sig_buffer = new byte[sig.Size]; stream.Position = sig.Block * properties.BlockSize; stream.Read(sig_buffer, 0, sig.Size); stream.Position = sig.SigOffset; stream.Write(Crypto.HmacSha256(signKey, sig_buffer), 0, 32); stream.WriteLE((int)sig.Block); } } if (hdr.Mode.HasFlag(PfsMode.Encrypted)) { Log("Encrypting..."); var encKey = Crypto.PfsGenEncKey(properties.EKPFS, hdr.Seed); var dataKey = new byte[16]; var tweakKey = new byte[16]; Buffer.BlockCopy(encKey, 0, tweakKey, 0, 16); Buffer.BlockCopy(encKey, 16, dataKey, 0, 16); stream.Position = hdr.BlockSize; var transformer = new XtsBlockTransform(dataKey, tweakKey); const int sectorSize = 0x1000; long xtsSector = 16; long totalSectors = (stream.Length + 0xFFF) / sectorSize; byte[] sectorBuffer = new byte[sectorSize]; while (xtsSector < totalSectors) { if (xtsSector / 0x10 == emptyBlock) { xtsSector += 16; } stream.Position = xtsSector * sectorSize; stream.Read(sectorBuffer, 0, sectorSize); transformer.EncryptSector(sectorBuffer, (ulong)xtsSector); stream.Position = xtsSector * sectorSize; stream.Write(sectorBuffer, 0, sectorSize); xtsSector += 1; } } }