Ejemplo n.º 1
0
        internal static MemoryStream Extract(Stream s, SLFormat slf)
        {
            byte[] fread_buf = new byte[131072]; // Buffer for reading from the file
              MemoryStream reader = new MemoryStream();
              switch (slf)
              {
            case SLFormat.OTTX:
              XZInputStream xz = new XZInputStream(s);
              int i = fread_buf.Length;
              while (i == fread_buf.Length)
              {
            i = xz.Read(fread_buf, 0, fread_buf.Length);
            reader.Write(fread_buf, 0, i);
              }
              reader.Seek(0, SeekOrigin.Begin);
              break;

              // TODO: Implement other save game formats
              }
              return reader;
        }
Ejemplo n.º 2
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="driveLetter"></param>
        /// <param name="fileName"></param>
        /// <param name="eCompType"></param>
        /// <param name="removeAfter"></param>
        /// <returns></returns>
        public bool WriteDrive(string driveLetter, string fileName, EnumCompressionType eCompType, bool removeAfter)
        {
            IsCancelling = false;

            var dtStart = DateTime.Now;

            if(!File.Exists(fileName))
                throw new ArgumentException(fileName + Resources.Disk_WriteDrive__doesn_t_exist);

            //
            // Get physical drive partition for logical partition
            //
            var physicalDrive = _diskAccess.GetPhysicalPathForLogicalPath(driveLetter);
            if (string.IsNullOrEmpty(physicalDrive))
            {
                LogMsg(Resources.Disk_WriteDrive_Error__Couldn_t_map_partition_to_physical_drive);
                _diskAccess.UnlockDrive();
                return false;
            }

            //
            // Lock logical drive
            //
            var success = _diskAccess.LockDrive(driveLetter);
            if (!success)
            {
                LogMsg(Resources.Disk_WriteDrive_Failed_to_lock_drive);
                return false;
            }

            //
            // Get drive size
            //
            var driveSize = _diskAccess.GetDriveSize(physicalDrive);
            if (driveSize <= 0)
            {
                LogMsg(Resources.Disk_WriteDrive_Failed_to_get_device_size);
                _diskAccess.UnlockDrive();
                return false;
            }

            //
            // Open the physical drive
            //
            var physicalHandle = _diskAccess.Open(physicalDrive);
            if (physicalHandle == null)
            {
                LogMsg(Resources.Disk_WriteDrive_Failed_to_open_physical_drive);
                _diskAccess.UnlockDrive();
                return false;
            }

            var buffer = new byte[Globals.MaxBufferSize];
            long offset = 0;

            var fileLength = new FileInfo(fileName).Length;

            var uncompressedlength = fileLength;

            var errored = true;

            using (var basefs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                Stream fs;

                switch (eCompType)
                {
                    case EnumCompressionType.Zip:

                        var zipFile = new ZipFile(basefs);

                        var ze = (from ZipEntry zipEntry in zipFile
                                        where zipEntry.IsFile
                                        select zipEntry).FirstOrDefault();

                        if(ze == null)
                        {
                            LogMsg(Resources.Disk_WriteDrive_Error_reading_zip_input_stream);
                            goto readfail2;
                        }

                        var zis = zipFile.GetInputStream(ze);

                        uncompressedlength = ze.Size;
                        fs = zis;

                        break;

                    case EnumCompressionType.Gzip:

                        var gzis = new GZipInputStream(basefs) {IsStreamOwner = true};

                        uncompressedlength = gzis.Length;
                        fs = gzis;

                        break;

                    case EnumCompressionType.Targzip:

                        var gzos = new GZipInputStream(basefs) {IsStreamOwner = true};
                        var tis = new TarInputStream(gzos);

                        TarEntry tarEntry;
                        do
                        {
                            tarEntry = tis.GetNextEntry();
                        } while (tarEntry.IsDirectory);

                        uncompressedlength = tarEntry.Size;
                        fs = tis;

                        break;

                    case EnumCompressionType.XZ:

                        var xzs = new XZInputStream(basefs);

                        uncompressedlength = xzs.Length;
                        fs = xzs;

                        break;

                    default:

                        // No compression - direct to file stream
                        fs = basefs;
                        uncompressedlength = fs.Length;

                        break;
                }

                var bufferOffset = 0;
                using (var br = new BinaryReader(fs))
                {
                    while (offset < uncompressedlength && !IsCancelling)
                    {
                        // Note: There's a problem writing certain lengths to the underlying physical drive.
                        //       This appears when we try to read from a compressed stream as it gives us
                        //       "strange" lengths which then fail to be written via Writefile() so try to build
                        //       up a decent block of bytes here...
                        int readBytes;
                        do
                        {
                            readBytes = br.Read(buffer, bufferOffset, buffer.Length - bufferOffset);
                            bufferOffset += readBytes;
                        } while (bufferOffset < Globals.MaxBufferSize && readBytes != 0);

                        int wroteBytes;
                        var bytesToWrite = bufferOffset;
                        var trailingBytes = 0;

                        // Assume that the underlying physical drive will at least accept powers of two!
                        if(!IsPowerOfTwo((ulong)bufferOffset))
                        {
                            // Find highest bit (32-bit max)
                            var highBit = 31;
                            for (; ((bufferOffset & (1 << highBit)) == 0) && highBit >= 0; highBit--)
                            {
                            }

                            // Work out trailing bytes after last power of two
                            var lastPowerOf2 = 1 << highBit;

                            bytesToWrite = lastPowerOf2;
                            trailingBytes = bufferOffset - lastPowerOf2;
                        }

                        if (_diskAccess.Write(buffer, bytesToWrite, out wroteBytes) < 0)
                        {
                            LogMsg(Resources.Disk_WriteDrive_Error_writing_data_to_drive__ + Marshal.GetHRForLastWin32Error());
                            goto readfail1;
                        }

                        if (wroteBytes != bytesToWrite)
                        {
                            LogMsg(Resources.Disk_WriteDrive_Error_writing_data_to_drive___past_EOF_);
                            goto readfail1;
                        }

                        // Move trailing bytes up - Todo: Suboptimal
                        if (trailingBytes > 0)
                        {
                            Buffer.BlockCopy(buffer, bufferOffset - trailingBytes, buffer, 0, trailingBytes);
                            bufferOffset = trailingBytes;
                        }
                        else
                        {
                            bufferOffset = 0;
                        }
                        offset += (uint)wroteBytes;

                        var percentDone = (int)(100 * offset / uncompressedlength);
                        var tsElapsed = DateTime.Now.Subtract(dtStart);
                        var bytesPerSec = offset / tsElapsed.TotalSeconds;

                        Progress(percentDone);

                        LogMsg(Resources.Disk_WriteDrive_Wrote + @": " + (offset / Globals.MbModifier) + @" / " +
                                                     (uncompressedlength / Globals.MbModifier) + " MB; " +
                                                      string.Format("{0:F}", (bytesPerSec / Globals.MbModifier)) + @" MB/s; " +  Resources.Disk_Elapsed_time + ": " + tsElapsed.ToString(@"hh\:mm\:ss"));
                    }
                }

                if (fs is ZipOutputStream)
                {
                    ((ZipOutputStream)fs).CloseEntry();
                    ((ZipOutputStream)fs).Close();
                } else if (fs is TarOutputStream)
                {
                    ((TarOutputStream)fs).CloseEntry();
                    fs.Close();
                } else if (fs is GZipOutputStream)
                {
                    fs.Close();
                } else if (fs is XZOutputStream)
                {
                    fs.Close();
                }
            }
            errored = false;

            if (removeAfter && !IsCancelling)
                _diskAccess.UnmountDrive();

            readfail1:
            _diskAccess.Close();
            readfail2:
            _diskAccess.UnlockDrive();

            var tstotalTime = DateTime.Now.Subtract(dtStart);

            if (IsCancelling)
                LogMsg(Resources.Disk_WriteDrive_Cancelled);
            else
                LogMsg(Resources.Disk_WriteDrive_Wrote + @" " + offset + @" " + Resources.Disk_WriteDrive_bytes + @". " + Resources.Disk_Elapsed_time + @": " + tstotalTime.ToString(@"hh\:mm\:ss"));

            Progress(0);
            return !errored;
        }