2026-02-05 11:14:01 +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.Partition;
|
|
|
|
|
using Duplicati.Proprietary.DiskImage.Filesystem;
|
2026-02-20 15:29:25 +01:00
|
|
|
using Duplicati.Library.Utility;
|
2026-03-05 15:30:36 +01:00
|
|
|
using Duplicati.Proprietary.DiskImage.General;
|
2026-02-05 11:14:01 +01:00
|
|
|
|
|
|
|
|
namespace Duplicati.Proprietary.DiskImage.SourceItems;
|
|
|
|
|
|
2026-02-15 12:45:59 +01:00
|
|
|
/// <summary>
|
|
|
|
|
/// Represents a partition as a source entry for backup operations.
|
|
|
|
|
/// Acts as a container for the filesystem within the partition.
|
|
|
|
|
/// </summary>
|
2026-02-05 11:14:01 +01:00
|
|
|
internal class PartitionSourceEntry(string parentPath, IPartition partition)
|
2026-02-12 16:54:35 +01:00
|
|
|
: DiskImageEntryBase(System.IO.Path.Combine(parentPath, $"part_{partition.PartitionTable.TableType}_{partition.PartitionNumber}{System.IO.Path.DirectorySeparatorChar}"))
|
2026-02-05 11:14:01 +01:00
|
|
|
{
|
2026-02-15 12:45:59 +01:00
|
|
|
/// <inheritdoc />
|
2026-02-05 11:14:01 +01:00
|
|
|
public override bool IsFolder => true;
|
2026-02-15 12:45:59 +01:00
|
|
|
|
|
|
|
|
/// <inheritdoc />
|
2026-02-05 11:14:01 +01:00
|
|
|
public override long Size => partition.Size;
|
|
|
|
|
|
2026-02-15 12:45:59 +01:00
|
|
|
/// <summary>
|
|
|
|
|
/// Gets the underlying partition instance.
|
|
|
|
|
/// </summary>
|
2026-02-09 11:36:15 +01:00
|
|
|
public IPartition Partition => partition;
|
|
|
|
|
|
2026-02-15 12:45:59 +01:00
|
|
|
/// <inheritdoc />
|
2026-02-05 11:14:01 +01:00
|
|
|
public override async IAsyncEnumerable<ISourceProviderEntry> Enumerate([EnumeratorCancellation] CancellationToken cancellationToken)
|
|
|
|
|
{
|
2026-02-15 11:12:08 +01:00
|
|
|
var fs = partition.FilesystemType switch
|
2026-02-05 11:14:01 +01:00
|
|
|
{
|
2026-02-15 11:12:08 +01:00
|
|
|
|
|
|
|
|
FileSystemType.Unknown => new UnknownFilesystem(partition),
|
|
|
|
|
_ => new UnknownFilesystem(partition)
|
|
|
|
|
};
|
|
|
|
|
yield return new FilesystemSourceEntry(this.Path, fs);
|
2026-02-05 11:14:01 +01:00
|
|
|
}
|
|
|
|
|
|
2026-02-15 12:45:59 +01:00
|
|
|
/// <inheritdoc />
|
2026-02-06 06:12:55 +01:00
|
|
|
public override async Task<Dictionary<string, string?>> GetMinorMetadata(CancellationToken cancellationToken)
|
|
|
|
|
{
|
|
|
|
|
var metadata = await base.GetMinorMetadata(cancellationToken);
|
|
|
|
|
|
|
|
|
|
// Add partition-level metadata
|
|
|
|
|
metadata["diskimage:Type"] = "partition";
|
|
|
|
|
metadata["partition:Number"] = partition.PartitionNumber.ToString();
|
|
|
|
|
metadata["partition:Type"] = partition.Type.ToString();
|
|
|
|
|
metadata["partition:StartOffset"] = partition.StartOffset.ToString();
|
|
|
|
|
metadata["partition:Size"] = partition.Size.ToString();
|
|
|
|
|
metadata["partition:FilesystemType"] = partition.FilesystemType.ToString();
|
|
|
|
|
metadata["partition:TableType"] = partition.PartitionTable.TableType.ToString();
|
|
|
|
|
|
|
|
|
|
if (!string.IsNullOrEmpty(partition.Name))
|
2026-02-20 15:29:25 +01:00
|
|
|
{
|
2026-02-06 06:12:55 +01:00
|
|
|
metadata["partition:Name"] = partition.Name;
|
2026-02-20 15:29:25 +01:00
|
|
|
metadata["diskimage:Name"] = $"{partition.Name} ({partition.Type}, {Utility.FormatSizeString(partition.Size)})";
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2026-03-05 15:30:36 +01:00
|
|
|
metadata["diskimage:Name"] = $"{partition.Type} ({Utility.FormatSizeString(partition.Size)})";
|
2026-02-20 15:29:25 +01:00
|
|
|
}
|
2026-02-06 06:12:55 +01:00
|
|
|
|
|
|
|
|
if (partition.VolumeGuid.HasValue)
|
|
|
|
|
metadata["partition:VolumeGuid"] = partition.VolumeGuid.Value.ToString();
|
|
|
|
|
|
|
|
|
|
return metadata;
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-05 11:14:01 +01:00
|
|
|
}
|