//TODO: align copy plan with file map in disk image
        private static List <FileExtent> CreateCopyPlan(DiskImage image, IPartitioningInfo partInfo)
        {
            //TODO: figure out if it possible to quickly zero the whole disk so we can skip writing zero blocks.
            //Using allocation bitmap from the disk image will speed thing up if the disk is sparse.
            //However not writing zeros can cause data corruption.
            var diskImageBitmap = new BitArray((int)(image.Length / SECTOR_SIZE), true);

            if (partInfo != null)
            {
                var partBitmap = GetAllocationBitmap(image.Length, partInfo.Partitions);
                diskImageBitmap = diskImageBitmap.And(partBitmap);
            }

            var  ret      = new List <FileExtent>();
            long startLba = -1;
            long currentLba;

            for (currentLba = 0; currentLba < diskImageBitmap.Length; currentLba++)
            {
                if (startLba != -1 && (currentLba - startLba) >= MAX_CHUNK_LBAS)
                {
                    ret.Add(new FileExtent(startLba * SECTOR_SIZE, (currentLba - startLba) * SECTOR_SIZE));
                    startLba = -1;
                }

                if (diskImageBitmap[checked ((int)currentLba)])
                {
                    if (startLba == -1)
                    {
                        startLba = currentLba;
                    }
                }
                else if (startLba != -1)
                {
                    ret.Add(new FileExtent(startLba * SECTOR_SIZE, (currentLba - startLba) * SECTOR_SIZE));
                    startLba = -1;
                }
            }

            if (startLba != -1)
            {
                long offset = startLba * SECTOR_SIZE;
                ret.Add(new FileExtent(offset, image.Length - offset));
            }

            return(ret);
        }
        static bool getParitionInfo(DiskImage image, out IPartitioningInfo info)
        {
            GptPartitioningInfo gpt;

            if (GptPartitioningInfo.TryGetGptInfo(image, out gpt))
            {
                info = gpt;
                return(true);
            }
            MbrPartitioningInfo mbr;

            if (MbrPartitioningInfo.TryGetMbrInfo(image, out mbr))
            {
                info = mbr;
                return(true);
            }
            info = null;
            return(false);
        }