Пример #1
0
        private void ExtractCallback(object ctx)
        {
            WorkUnit         unit = (WorkUnit)ctx;
            EmbeddedFileInfo efi  = unit.efi;

            byte[] buffer         = new byte[efi.size];
            IntPtr fileMemAddress = new IntPtr(unit.fileVolAddress);

            Marshal.Copy(fileMemAddress, buffer, 0, buffer.Length);
            if (unit.callback != null)
            {
                unit.callback(String.Format("Extracted {0} from VOL", efi.name));
            }

            // I tried async-ing this write in the decomp case, but it was magnitudes slower
            unit.destFile.Write(buffer, 0, buffer.Length);
            if (unit.callback != null)
            {
                unit.callback(String.Format("Finished writing {0} bytes of {1}", buffer.Length, efi.name));
            }
            if (unit.shouldDecompAfter)
            {
                // create a mem stream on the buffer so we can decomp without having to hit the filesystem
                // on both the read and the write
                MemoryStream memGz = new MemoryStream(buffer, false);
                using (FileStream destFile = GetUnzippedFileFromOrig(unit.destFile.Name))
                    using (GZipInputStream srcStream = new GZipInputStream(memGz))
                    {
                        byte[] readBuf = new byte[0x8000];
                        StreamUtils.Copy(srcStream, destFile, readBuf);
                        if (unit.callback != null)
                        {
                            unit.callback(String.Format("Ungzipped {0} bytes to {1} for {2}", memGz.Length, destFile.Position, efi.name));
                        }
                    }
            }
            unit.finishedHandle.Set();
            string fileName = unit.destFile.Name;

            unit.destFile.Close();
            DateTime fileTime = new DateTime(1970, 1, 1, 0, 0, 0).AddSeconds(unit.efi.dateTime);

            File.SetCreationTime(fileName, fileTime);
            File.SetLastWriteTime(fileName, fileTime);
            File.SetLastAccessTime(fileName, fileTime);
        }
Пример #2
0
        private void ExtractSingleFile(EmbeddedFileInfo efi, string dir, bool decompGZ, bool waitForCompletion, ExplodeProgressCallback epc)
        {
            ManualResetEvent finEvent = new ManualResetEvent(false);

            if (!waitForCompletion)
            {
                outstandingRequests.Add(finEvent);
            }
            WorkUnit unit = new WorkUnit(dir, efi, this, decompGZ, finEvent, epc);

            if (!ThreadPool.QueueUserWorkItem(new WaitCallback(ExtractCallback), unit))
            {
                throw new ThreadInterruptedException("No Threadpool Threads");
            }
            if (waitForCompletion)
            {
                finEvent.WaitOne();
                finEvent.Close();
            }
        }
Пример #3
0
 public WorkUnit(
     string dir,
     EmbeddedFileInfo efiParam,
     VolFile volFile,
     bool decompGZ,
     ManualResetEvent compEvent,
     ExplodeProgressCallback epc
     )
 {
     efi      = efiParam;
     destFile = new FileStream(
         Path.Combine(dir, efi.name),
         FileMode.Create,
         FileAccess.ReadWrite,
         FileShare.None,
         8192,
         false
         );
     fileVolAddress    = volFile.volMappingAddrAsNum + efi.fileAddress;
     shouldDecompAfter = (decompGZ && efi.name.EndsWith(".gz"));
     finishedHandle    = compEvent;
     callback          = epc;
 }
Пример #4
0
 public void ExtractSingleFile(EmbeddedFileInfo efi, string dir, bool decompGZ)
 {
     ExtractSingleFile(efi, dir, decompGZ, true, null);
 }
Пример #5
0
        static void ReadEmbeddedFileData(
            List <EmbeddedFileInfo> files,
            short numFiles,
            BinaryReader src,
            uint[] fileOffsets,
            TocFileNotify notifyFn,
            long volStartAddress
            )
        {
            List <string>    directories = new List <string>();
            string           dirBeingParsed = String.Empty;
            EmbeddedFileInfo lastFile = null;
            int   dirIndex = 0, dirInsertIndex = 0;
            short i = 0;

            for (; i < numFiles; ++i)
            {
                EmbeddedFileInfo efi = new EmbeddedFileInfo();
                efi.dateTime = src.ReadInt32();
                int  offsetIndex = src.ReadInt16();
                byte flags       = src.ReadByte();

                uint bytesFromLastSector = 0;
                // flags
                // 0x00 = regular file
                // 0x01 = directory
                // 0x80 = last entry for this directory
                if (offsetIndex == 0 || (flags & 0x1) == 0x1)
                {
                    // '..' entries and directories don't have an offset
                    efi.fileAddress = 0;
                    efi.pFileStart  = IntPtr.Zero;
                }
                else
                {
                    efi.fileAddress = SanitiseOffset(fileOffsets[offsetIndex], out bytesFromLastSector);
                    efi.pFileStart  = new IntPtr(volStartAddress + efi.fileAddress);
                }

                // cache this here for now, it's not the actual size, but it's used in its calculation
                efi.size = bytesFromLastSector;
                efi.name = Path.Combine(dirBeingParsed, Encoding.ASCII.GetString(src.ReadBytes(25)).TrimEnd('\0'));

                if ((flags & 0x1) != 0)
                {
                    // '..' don't need saving
                    if (!efi.name.EndsWith(".."))
                    {
                        // if we're parsing one, this is a child directory
                        // its' contents are after the one being parsed, not at the end of the list
                        if (dirBeingParsed != String.Empty)
                        {
                            directories.Insert(dirInsertIndex++, efi.name);
                        }
                        else
                        {
                            directories.Add(efi.name);
                        }
                    }
                }
                else
                {
                    if (lastFile != null)
                    {
                        uint realSize = efi.fileAddress - lastFile.fileAddress - lastFile.size;
                        // realsize can be 0 if files are 0 bytes (everything in the replay dir)
                        lastFile.size = realSize;
                        if (notifyFn != null)
                        {
                            notifyFn(lastFile);
                        }
                    }
                    lastFile = efi;
                }
                // if this is the last entry for this directory
                // change which dir we use as the parent
                if ((flags & 0x80) != 0)
                {
                    // directories are listed in order of first encounter
                    // so a simple iteration will suffice
                    dirBeingParsed =
                        (dirIndex < directories.Count) ? directories[dirIndex++] : String.Empty;
                    dirInsertIndex = dirIndex;
                }
                // '..' entries don't need to be saved
                if (offsetIndex != 0)
                {
                    files.Add(efi);
                }
            }
            // the last fileOffset is the length of the whole file
            lastFile.size = fileOffsets[fileOffsets.Length - 1] - lastFile.fileAddress - lastFile.size;
            lastFile.size = (lastFile.size > 0) ? lastFile.size : 0x800;
            if (notifyFn != null)
            {
                notifyFn(lastFile);
            }
        }
Пример #6
0
 static void EmbeddedFileNotify(EmbeddedFileInfo efi)
 {
     Console.WriteLine("{3:x}: Found {0} at offset 0x{1:X} of size {2}", efi.name, efi.fileAddress, efi.size, i++);
 }