Esempio n. 1
0
 /// <summary>
 /// Adds inodes for each dir.
 /// </summary>
 void addDirInodes()
 {
     inodes.Add(root.ino);
     foreach (var dir in allDirs)
     {
         var ino = new PfsDinode32
         {
             Mode   = InodeMode.dir | InodeMode.rwx,
             Number = (uint)inodes.Count,
             Blocks = 1,
             Size   = 65536
         };
         dir.ino = ino;
         dir.Dirents.Add(new PfsDirent {
             Name = ".", InodeNumber = ino.Number, Type = 4
         });
         dir.Dirents.Add(new PfsDirent {
             Name = "..", InodeNumber = dir.Parent.ino.Number, Type = 5
         });
         dirents.Add(dir.Dirents);
         var dirent = new PfsDirent {
             Name = dir.name, InodeNumber = (uint)inodes.Count, Type = 3
         };
         dir.Parent.Dirents.Add(dirent);
         dir.Parent.ino.Nlink++;
         inodes.Add(ino);
     }
 }
Esempio n. 2
0
        /// <summary>
        /// Adds inodes for each dir.
        /// </summary>
        void addDirInodes()
        {
            inodes.Add(properties.root.ino);
            foreach (var dir in allDirs.OrderBy(x => x.FullPath()))
            {
                var ino = MakeInode(
                    Mode: InodeMode.dir | inode.RXOnly,
                    Number: (uint)inodes.Count,
                    Blocks: 1,
                    Size: 65536,
                    Flags: InodeFlags.@readonly,
                    Nlink: 2 // 1 link each for its own dirent and its . dirent
                    );
                dir.ino = ino;
                dir.Dirents.Add(new PfsDirent {
                    Name = ".", InodeNumber = ino.Number, Type = DirentType.Dot
                });
                dir.Dirents.Add(new PfsDirent {
                    Name = "..", InodeNumber = dir.Parent.ino.Number, Type = DirentType.DotDot
                });

                var dirent = new PfsDirent {
                    Name = dir.name, InodeNumber = (uint)inodes.Count, Type = DirentType.Directory
                };
                dir.Parent.Dirents.Add(dirent);
                dir.Parent.ino.Nlink++;
                inodes.Add(ino);
            }
        }
Esempio n. 3
0
        private Dir LoadDir(uint dinode, Dir parent, string name)
        {
            // 100M blocks is enough for a 6TB file.
            const int MAX_BLOCKS = 100_000_000;
            var       ret        = new Dir()
            {
                name = name, parent = parent
            };
            var ino      = dinodes[dinode];
            var postLoad = new List <Func <Dir> >();
            var blocks   = (int)ino.Blocks;

            if (blocks < 1 || ino.StartBlock < 1 || ino.StartBlock > MAX_BLOCKS || blocks > MAX_BLOCKS)
            {
                throw new Exception($"inode {dinode} is corrupt. ");
            }
            foreach (var x in Enumerable.Range(ino.StartBlock, blocks))
            {
                var position = hdr.BlockSize * x;
                reader.Read(position, sectorBuf, 0, sectorBuf.Length);
                sectorStream.Position = 0;
                while (position < hdr.BlockSize * (x + 1))
                {
                    var dirent = PfsDirent.ReadFromStream(sectorStream);
                    if (dirent.EntSize == 0)
                    {
                        break;
                    }
                    switch (dirent.Type)
                    {
                    case DirentType.File:
                        ret.children.Add(LoadFile(dirent.InodeNumber, ret, dirent.Name));
                        break;

                    case DirentType.Directory:
                        postLoad.Add(() => LoadDir(dirent.InodeNumber, ret, dirent.Name));
                        break;

                    case DirentType.Dot:
                        break;

                    case DirentType.DotDot:
                        break;

                    default:
                        break;
                    }
                    position += dirent.EntSize;
                }
            }
            foreach (var p in postLoad)
            {
                ret.children.Add(p());
            }
            return(ret);
        }
Esempio n. 4
0
        public static Tuple <FlatPathTable, CollisionResolver> Create(List <FSNode> nodes)
        {
            var  hashMap   = new SortedDictionary <uint, uint>();
            var  nodeMap   = new Dictionary <uint, List <FSNode> >();
            bool collision = false;

            foreach (var n in nodes)
            {
                var hash = HashFunction(n.FullPath());
                if (hashMap.ContainsKey(hash))
                {
                    hashMap[hash] = 0x80000000;
                    nodeMap[hash].Add(n);
                    collision = true;
                }
                else
                {
                    hashMap[hash] = n.ino.Number | (n is FSDir ? 0x20000000u : 0u);
                    nodeMap[hash] = new List <FSNode>();
                    nodeMap[hash].Add(n);
                }
            }
            if (!collision)
            {
                return(Tuple.Create(new FlatPathTable(hashMap), (CollisionResolver)null));
            }

            uint offset  = 0;
            var  colEnts = new List <List <PfsDirent> >();

            foreach (var kv in hashMap.Where(kv => kv.Value == 0x80000000).ToList())
            {
                hashMap[kv.Key] = 0x80000000 | offset;
                var entList = new List <PfsDirent>();
                colEnts.Add(entList);
                foreach (var node in nodeMap[kv.Key])
                {
                    var d = new PfsDirent()
                    {
                        InodeNumber = node.ino.Number,
                        Type        = node is FSDir ? DirentType.Directory : DirentType.File,
                        Name        = node.FullPath(),
                    };
                    entList.Add(d);
                    offset += (uint)d.EntSize;
                }
                offset += 0x18;
            }
            return(Tuple.Create(new FlatPathTable(hashMap), new CollisionResolver(colEnts)));
        }
        private Dir LoadDir(uint dinode, Node parent, string name)
        {
            var ret = new Dir()
            {
                name = name, parent = parent
            };
            var ino      = dinodes[dinode];
            var postLoad = new List <Func <Dir> >();

            foreach (var x in Enumerable.Range(ino.StartBlock, (int)ino.Blocks))
            {
                var position = hdr.BlockSize * x;
                reader.Read(position, sectorBuf, 0, sectorBuf.Length);
                sectorStream.Position = 0;
                while (position < hdr.BlockSize * (x + 1))
                {
                    var dirent = PfsDirent.ReadFromStream(sectorStream);
                    if (dirent.EntSize == 0)
                    {
                        break;
                    }
                    switch (dirent.Type)
                    {
                    case DirentType.File:
                        ret.children.Add(LoadFile(dirent.InodeNumber, ret, dirent.Name));
                        break;

                    case DirentType.Directory:
                        postLoad.Add(() => LoadDir(dirent.InodeNumber, ret, dirent.Name));
                        break;

                    case DirentType.Dot:
                        break;

                    case DirentType.DotDot:
                        break;

                    default:
                        break;
                    }
                    position += dirent.EntSize;
                }
            }
            foreach (var p in postLoad)
            {
                ret.children.Add(p());
            }
            return(ret);
        }
        public static PfsDirent ReadFromStream(Stream s)
        {
            var pos = s.Position;
            var d   = new PfsDirent
            {
                InodeNumber = s.ReadUInt32LE(),
                Type        = (DirentType)s.ReadInt32LE(),
                NameLength  = s.ReadInt32LE(),
                EntSize     = s.ReadInt32LE(),
            };

            d.name     = s.ReadASCIINullTerminated(d.NameLength);
            s.Position = pos + d.EntSize;
            return(d);
        }
Esempio n. 7
0
 /// <summary>
 /// Adds inodes for each file.
 /// </summary>
 void addFileInodes()
 {
     foreach (var file in allFiles)
     {
         var ino = new PfsDinode32
         {
             Mode           = InodeMode.file | InodeMode.rwx,
             Size           = file.Size,
             SizeCompressed = file.Size,
             Number         = (uint)inodes.Count,
             Blocks         = (uint)CeilDiv(file.Size, hdr.BlockSize)
         };
         file.ino = ino;
         var dirent = new PfsDirent {
             Name = file.name, Type = 2, InodeNumber = (uint)inodes.Count
         };
         file.Parent.Dirents.Add(dirent);
         inodes.Add(ino);
     }
 }
Esempio n. 8
0
 /// <summary>
 /// Adds inodes for each file.
 /// </summary>
 void addFileInodes()
 {
     foreach (var file in allFiles.OrderBy(x => x.FullPath()))
     {
         var ino = MakeInode(
             Mode: InodeMode.file | inode.RXOnly,
             Size: file.Size,
             SizeCompressed: file.CompressedSize,
             Number: (uint)inodes.Count,
             Blocks: (uint)CeilDiv(file.Size, hdr.BlockSize),
             Flags: InodeFlags.@readonly | (file.Compress ? InodeFlags.compressed : 0)
             );
         if (properties.Sign) // HACK: Outer PFS images don't use readonly?
         {
             ino.Flags &= ~InodeFlags.@readonly;
         }
         file.ino = ino;
         var dirent = new PfsDirent {
             Name = file.name, Type = DirentType.File, InodeNumber = (uint)inodes.Count
         };
         file.Parent.Dirents.Add(dirent);
         inodes.Add(ino);
     }
 }