예제 #1
0
        static void Unpack(PackerSettings settings)
        {
            Console.WriteLine("-- Unpack Files in " + settings.target + " --");
            FileStream        stream = new FileStream(settings.target, FileMode.Open);
            BinaryReader      r      = new BinaryReader(stream);
            DiskArchiveHeader header = new DiskArchiveHeader();

            header.Read(r);
            if (header.HasValidMagicValue() == false)
            {
                Console.WriteLine("Error: " + settings.target + " is not a P.A.C.K file");
                return;
            }
            Console.WriteLine("Files: " + header.numFiles);
            Console.WriteLine("Manifest position: " + header.fileListOffset);

            string outputDir = "output\\" + Path.GetFileNameWithoutExtension(settings.target);

            Console.WriteLine("Writing contents to " + outputDir);

            Directory.CreateDirectory(outputDir);

            r.BaseStream.Seek(header.fileListOffset, SeekOrigin.Begin);
            for (int i = 0; i < header.numFiles; ++i)
            {
                DiskArchiveFile file = new DiskArchiveFile();
                uint            manifestReadPosition = file.Read(r);

                r.BaseStream.Seek(file.offset, SeekOrigin.Begin);

                byte[] bytes = r.ReadBytes((int)file.numBytes);
                // remember seek back to manifest position
                r.BaseStream.Seek(manifestReadPosition, SeekOrigin.Begin);

                string fileName = outputDir + file.fileName.Trim('\0');
                Console.WriteLine("Writing " + fileName + ": Size: " + bytes.Length);

                // Make sure directory exists
                Directory.CreateDirectory(Path.GetDirectoryName(fileName));

                File.WriteAllBytes(fileName, bytes);
            }
        }
예제 #2
0
        static void ListContents(PackerSettings settings)
        {
            Console.WriteLine("-- List Files in " + settings.target + " --");
            FileStream        stream = new FileStream(settings.target, FileMode.Open);
            BinaryReader      r      = new BinaryReader(stream);
            DiskArchiveHeader header = new DiskArchiveHeader();

            header.Read(r);
            if (header.HasValidMagicValue() == false)
            {
                Console.WriteLine("Error: " + settings.target + " is not a P.A.C.K file");
                return;
            }
            Console.WriteLine("Files: " + header.numFiles);
            Console.WriteLine("Manifest position: " + header.fileListOffset);
            r.BaseStream.Seek(header.fileListOffset, SeekOrigin.Begin);
            for (int i = 0; i < header.numFiles; ++i)
            {
                DiskArchiveFile file = new DiskArchiveFile();
                file.Read(r);
                Console.WriteLine(file.fileName + ": Size: " + file.numBytes + " offset: " + file.offset + " type: " + file.info[0]);
            }
        }
예제 #3
0
        static void Pack(PackerSettings settings)
        {
            string        outputFile = settings.target + ".dat";
            List <string> list       = new List <string>(100);

            GetRecursiveFileList(settings.target, list);

            if (list.Count == 0)
            {
                throw new Exception("No files found in directory '" + settings.target + "'");
            }

            int memSizeOfFileList = DiskArchiveFile.SIZE_IN_BYTES * list.Count;

            Console.WriteLine("Size of file table: " + memSizeOfFileList + " bytes, or 64 * " + list.Count + " files");

            //////////////////////////////////////////////////////////////////////
            // Build manifest
            // headers are stored in memory until write is finished, then appended to the end.
            //////////////////////////////////////////////////////////////////////
            List <DiskArchiveFile> fileHeaders = new List <DiskArchiveFile>(list.Count);

            foreach (string path in list)
            {
                int    properStart = path.IndexOf('\\');
                string output;
                if (properStart >= 0)
                {
                    output = path.Remove(0, properStart);
                }
                else
                {
                    output = path;
                }

                // validate filename
                if (output.Length > MAX_ARCHIVE_FILE_NAME_SIZE)
                {
                    throw new Exception("File path " + output + " is too long. Must be 51 chars or lower");
                }
                foreach (char c in output)
                {
                    if (c > 255)
                    {
                        throw new Exception("File path " + output + " contains non-ascii characters");
                    }
                }

                DiskArchiveFile file = new DiskArchiveFile();
                file.SetFileName(path);
                file.numBytes = (uint)GetFileSize(path);
                file.offset   = 0;
                fileHeaders.Add(file);
            }


            //////////////////////////////////////////////////////////////////////
            // Write files
            //////////////////////////////////////////////////////////////////////
            // open streams
            FileStream   stream = new FileStream(outputFile, FileMode.Create);
            BinaryWriter writer = new BinaryWriter(stream);

            DiskArchiveHeader header = new DiskArchiveHeader();

            header.numFiles = (uint)fileHeaders.Count;
            writer.Seek(DiskArchiveHeader.SIZE_IN_BYTES, SeekOrigin.Begin);

            Console.WriteLine("Writing files:");
            // Build the actual file, updating the manifest
            foreach (DiskArchiveFile file in fileHeaders)
            {
                Console.WriteLine("Writing " + file.fullFilePath + " at " + writer.BaseStream.Position);
                file.offset   = (uint)writer.BaseStream.Position;
                file.numBytes = (uint)GetFileSize(file.fullFilePath);
                writer.Write(File.ReadAllBytes(file.fullFilePath));
            }

            Console.WriteLine("Writing manifest:");

            // Note the position of the file table in the header
            header.fileListOffset = (uint)writer.BaseStream.Position;

            // Write the manifest table
            foreach (DiskArchiveFile file in fileHeaders)
            {
                file.Write(writer);
            }

            // Write header now that manifest is completed
            writer.Seek(0, SeekOrigin.Begin);
            header.Write(writer);

            // cleanup
            writer.Close();
            stream.Close();

            long   outputSize = GetFileSize(outputFile);
            string sizeStr;

            if (outputSize >= (1024 * 1024))
            {
                sizeStr = (outputSize / (1024 * 1024)).ToString() + " MB (" + outputSize + " bytes)";
            }
            else if (outputSize > 1024)
            {
                sizeStr = (outputSize / 1024).ToString() + " KB (" + outputSize + " bytes)";
            }
            else
            {
                sizeStr = outputSize.ToString() + " B";
            }
            Console.Write("Wrote \"" + outputFile + "\": " + sizeStr);
        }