/// <summary> /// Takes a directory and a root node, and recursively makes a filesystem tree. /// </summary> /// <param name="proj">GP4 Project</param> /// <param name="projDir">Directory of GP4 file</param> /// <returns>Root directory of the image</returns> public static FSDir BuildFSTree(GP4.Gp4Project proj, string projDir) { void AddDirs(FSDir parent, List <GP4.Dir> imgDir) { foreach (var d in imgDir) { FSDir dir; parent.Dirs.Add(dir = new FSDir { name = d.TargetName, Parent = parent }); AddDirs(dir, d.Children); } } var root = new FSDir(); AddDirs(root, proj.RootDir); foreach (var f in proj.files.Items) { var lastSlash = f.TargetPath.LastIndexOf('/') + 1; var name = f.TargetPath.Substring(lastSlash); var source = Path.Combine(projDir, f.OrigPath); var parent = lastSlash == 0 ? root : FindDir(f.TargetPath.Substring(0, lastSlash - 1), root); parent.Files.Add(new FSFile(source) { Parent = parent, name = name, }); } return(root); }
static void AddFile(FSDir root, string path, string name, byte[] data) { var dir = FindDir(path, root); dir.Files.Add(new FSFile(s => s.Write(data, 0, data.Length), name, data.Length) { Parent = dir }); }
/// <summary> /// Creates inodes and dirents for superroot, flat_path_table, and uroot. /// Also, creates the root node for the FS tree. /// </summary> void SetupRootStructure() { inodes.Add(super_root_ino = MakeInode( Mode: InodeMode.dir | InodeMode.rx_only, Blocks: 1, Size: 65536, SizeCompressed: 65536, Nlink: 1, Number: 0, Flags: InodeFlags.@internal | InodeFlags.@readonly )); inodes.Add(fpt_ino = MakeInode( Mode: InodeMode.file | InodeMode.rx_only, Blocks: 1, Number: 1, Flags: InodeFlags.@internal | InodeFlags.@readonly )); var uroot_ino = MakeInode( Mode: InodeMode.dir | InodeMode.rx_only, Number: 2, Size: 65536, SizeCompressed: 65536, Blocks: 1, Flags: InodeFlags.@readonly, Nlink: 3 ); super_root_dirents = new List <PfsDirent> { new PfsDirent { InodeNumber = 1, Name = "flat_path_table", Type = DirentType.File }, new PfsDirent { InodeNumber = 2, Name = "uroot", Type = DirentType.Directory } }; root = properties.root; root.name = "uroot"; root.ino = uroot_ino; root.Dirents = new List <PfsDirent> { new PfsDirent { Name = ".", Type = DirentType.Dot, InodeNumber = 2 }, new PfsDirent { Name = "..", Type = DirentType.DotDot, InodeNumber = 2 } }; if (properties.Sign) // HACK: Outer PFS lacks readonly flags { super_root_ino.Flags &= ~InodeFlags.@readonly; fpt_ino.Flags &= ~InodeFlags.@readonly; uroot_ino.Flags &= ~InodeFlags.@readonly; } }
static FSDir FindDir(string name, FSDir root) { FSDir dir = root; var breadcrumbs = name.Split('/'); foreach (var crumb in breadcrumbs) { dir = dir.Dirs.Where(d => d.name == crumb).First(); } return(dir); }
/// <summary> /// Creates inodes and dirents for superroot, flat_path_table, and uroot. /// Also, creates the root node for the FS tree. /// </summary> void SetupRootStructure() { inodes.Add(super_root_ino = new PfsDinode32 { Mode = InodeMode.dir | InodeMode.rx_only, Blocks = 1, Size = 65536, SizeCompressed = 65536, Nlink = 1, Number = 0, Flags = InodeFlags.@internal }); inodes.Add(fpt_ino = new PfsDinode32 { Mode = InodeMode.file | InodeMode.rwx, Blocks = 1, Number = 1, Flags = InodeFlags.@internal }); var uroot_ino = new PfsDinode32 { Mode = InodeMode.dir | InodeMode.rwx, Number = 2, Size = 65536, SizeCompressed = 65536, Blocks = 1 }; super_root_dirents = new List <PfsDirent> { new PfsDirent { InodeNumber = 1, Name = "flat_path_table", Type = 2 }, new PfsDirent { InodeNumber = 2, Name = "uroot", Type = 3 } }; root = new FSDir { name = "uroot", ino = uroot_ino, Dirents = new List <PfsDirent> { new PfsDirent { Name = ".", Type = 4, InodeNumber = 2 }, new PfsDirent { Name = "..", Type = 5, InodeNumber = 2 } } }; }
public static PfsProperties MakeInnerPFSProps(GP4.Gp4Project proj, string projDir) { var root = new FSDir(); BuildFSTree(root, proj, projDir); var timestamp = DateTime.Parse(proj.volume.TimeStamp).ToUniversalTime().Subtract(new DateTime(1970, 1, 1)).TotalSeconds; return(new PfsProperties() { root = root, BlockSize = 0x10000, Encrypt = false, Sign = false, FileTime = GetTimeStamp(proj), }); }
/// <summary> /// Takes a directory and a root node, and recursively makes a filesystem tree. /// </summary> /// <param name="root">Root directory of the image</param> /// <param name="proj">GP4 Project</param> /// <param name="projDir">Directory of GP4 file</param> static void BuildFSTree(FSDir root, GP4.Gp4Project proj, string projDir) { void AddDirs(FSDir parent, List <GP4.Dir> imgDir) { foreach (var d in imgDir) { FSDir dir; parent.Dirs.Add(dir = new FSDir { name = d.TargetName, Parent = parent }); AddDirs(dir, d.Children); } } FSDir FindDir(string name) { FSDir dir = root; var breadcrumbs = name.Split('/'); foreach (var crumb in breadcrumbs) { dir = dir.Dirs.Where(d => d.name == crumb).First(); } return(dir); } AddDirs(root, proj.RootDir); foreach (var f in proj.files) { var lastSlash = f.TargetPath.LastIndexOf('/') + 1; if (f.TargetPath == "sce_sys/param.sfo") { continue; } var name = f.TargetPath.Substring(lastSlash); var source = Path.Combine(projDir, f.OrigPath); var parent = lastSlash == 0 ? root : FindDir(f.TargetPath.Substring(0, lastSlash - 1)); parent.Files.Add(new FSFile(source) { Parent = parent, name = name, }); } }
/// <summary> /// Generates a PfsProperties object for the outer PFS image of a PKG with the given properties. /// </summary> /// <param name="props">PKG properties to convert from</param> /// <param name="innerPFS">Inner pfs image to use, presumably from MakeInnerPFSProps</param> /// <param name="EKPFS">Encryption key for PFS</param> /// <param name="encrypt">Set to false to make a non-encrypted PFS</param> /// <returns></returns> public static PfsProperties MakeOuterPFSProps(PKG.PkgProperties props, PfsBuilder innerPFS, byte[] EKPFS, bool encrypt = true) { var root = new FSDir(); root.Files.Add(new FSFile(innerPFS) { Parent = root, }); return(new PfsProperties() { root = root, BlockSize = 0x10000, Encrypt = encrypt, Sign = true, EKPFS = EKPFS, Seed = new byte[16], FileTime = GetTimeStamp(props), }); }
/// <summary> /// Generates a PfsProperties object for the outer PFS image of a PKG with the given properties. /// </summary> /// <param name="props">PKG properties to convert from</param> /// <param name="innerPFS">Inner pfs image to use, presumably from MakeInnerPFSProps</param> /// <param name="EKPFS">Encryption key for PFS</param> /// <param name="encrypt">Set to false to make a non-encrypted PFS</param> /// <returns></returns> public static PfsProperties MakeOuterPFSProps(PKG.PkgProperties props, PfsBuilder innerPFS, byte[] EKPFS, bool encrypt = true) { var root = new FSDir(); root.Files.Add(new FSFile(innerPFS) { Parent = root, }); return(new PfsProperties() { root = root, BlockSize = 0x10000, Encrypt = encrypt, Sign = true, EKPFS = EKPFS, // This doesn't seem to really matter when verifying a PKG so use all zeroes for now Seed = new byte[16], FileTime = GetTimeStamp(props), }); }