Files
duplicati/proprietary/DiskImage/SourceItems/PartitionTableSourceEntry.cs
T

84 lines
2.9 KiB
C#
Raw Normal View History

2026-02-06 06:39:22 +01:00
// Copyright (c) 2026 Duplicati Inc. All rights reserved.
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using Duplicati.Library.Interface;
using Duplicati.Proprietary.DiskImage.Disk;
using Duplicati.Proprietary.DiskImage.General;
2026-02-06 06:39:22 +01:00
using Duplicati.Proprietary.DiskImage.Partition;
namespace Duplicati.Proprietary.DiskImage.SourceItems;
/// <summary>
/// Represents the partition table as a source entry for backup/restore purposes.
/// This allows the partition table (MBR or GPT) to be backed up and restored separately.
/// </summary>
internal class PartitionTableSourceEntry(string parentPath, IPartitionTable table, IRawDisk disk)
: DiskImageEntryBase(System.IO.Path.Combine(parentPath, $"partition_table_{table.TableType}"))
2026-02-06 06:39:22 +01:00
{
public override bool IsFolder => false;
public override bool IsMetaEntry => true;
public override long Size => GetTableSize();
public override Task<Stream> OpenRead(CancellationToken cancellationToken)
{
return table.GetPartitionTableDataAsync(cancellationToken);
}
public override async IAsyncEnumerable<ISourceProviderEntry> Enumerate([EnumeratorCancellation] CancellationToken cancellationToken)
{
// Partition table is a leaf node - no children
await Task.CompletedTask;
yield break;
}
public override async Task<Dictionary<string, string?>> GetMinorMetadata(CancellationToken cancellationToken)
{
var metadata = await base.GetMinorMetadata(cancellationToken);
// Add partition table metadata
metadata["diskimage:Type"] = "partition_table";
metadata["partition_table:Type"] = table.TableType.ToString();
metadata["partition_table:Size"] = Size.ToString();
metadata["disk:SectorSize"] = disk.SectorSize.ToString();
// Add type-specific metadata
if (table.TableType == PartitionTableType.MBR)
{
metadata["partition_table:MbrSize"] = "512";
}
else if (table.TableType == PartitionTableType.GPT)
{
metadata["partition_table:HasProtectiveMbr"] = "true";
metadata["partition_table:HeaderSize"] = "92"; // GPT header is 92 bytes
}
return metadata;
}
private long GetTableSize()
{
try
{
// Try to get the size by reading the table data
using var stream = table.GetPartitionTableDataAsync(CancellationToken.None).Result;
return stream.Length;
}
catch
{
// Fallback to estimated sizes
return table.TableType switch
{
PartitionTableType.MBR => 512,
PartitionTableType.GPT => 512 + 512 + (128 * 4), // Protective MBR + Header + 4 entries
_ => 0
};
}
}
}