Ejemplo n.º 1
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="driveLetter"></param>
        /// <param name="fileName"></param>
        /// <param name="eCompType"></param>
        /// <returns></returns>
        public bool WriteDrive(string driveLetter, string fileName, EnumCompressionType eCompType)
        {
            IsCancelling = false;

            var dtStart = DateTime.Now;

            if (!File.Exists(fileName))
            {
                throw new ArgumentException(fileName + " doesn't exist");
            }

            //
            // Get physical drive partition for logical partition
            //
            var physicalDrive = _diskAccess.GetPhysicalPathForLogicalPath(driveLetter);

            if (string.IsNullOrEmpty(physicalDrive))
            {
                LogMsg(@"Error: Couldn't map partition to physical drive");
                _diskAccess.UnlockDrive();
                return(false);
            }

            //
            // Lock logical drive
            //
            var success = _diskAccess.LockDrive(driveLetter);

            if (!success)
            {
                LogMsg(@"Failed to lock drive");
                return(false);
            }


            //
            // Get drive size
            //
            var driveSize = _diskAccess.GetDriveSize(physicalDrive);

            if (driveSize <= 0)
            {
                LogMsg(@"Failed to get device size");
                _diskAccess.UnlockDrive();
                return(false);
            }

            //
            // Open the physical drive
            //
            var physicalHandle = _diskAccess.Open(physicalDrive);

            if (physicalHandle == null)
            {
                LogMsg(@"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))
            {
                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(@"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;

                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(@"Error writing data to drive: " + Marshal.GetHRForLastWin32Error());
                            goto readfail1;
                        }

                        if (wroteBytes != bytesToWrite)
                        {
                            LogMsg(@"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(@"Wrote " + percentDone + @"%, " + (offset / (1024 * 1024)) + @" MB / " +
                               (uncompressedlength / (1024 * 1024) + " MB, " +
                                string.Format("{0:F}", (bytesPerSec / (1024 * 1024))) + @" MB/sec, Elapsed time: " + tsElapsed.ToString(@"dd\.hh\:mm\:ss")));
                    }
                }
            }
            errored = false;

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

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

            if (IsCancelling)
            {
                LogMsg("Cancelled");
            }
            else
            {
                LogMsg("All Done - Wrote " + offset + " bytes. Elapsed time " + tstotalTime.ToString(@"dd\.hh\:mm\:ss"));
            }

            Progress(0);
            return(!errored);
        }
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);
        }