Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
5d5e1a3
Enhance project structure and versioning
devedse Dec 18, 2025
1408dd4
Refactor plugin registration for AoT compatibility
devedse Dec 18, 2025
88fcbb3
Refactor SetupComplete method and remove console logging from Factory…
devedse Dec 18, 2025
b31443d
Refactor source generator structure and update project references
devedse Dec 18, 2025
8fc75f5
Wip
devedse Dec 18, 2025
34da27d
Update package project URLs and identifiers to reflect correct ownership
devedse Dec 18, 2025
b9044a3
Refactor publish-nuget workflow to build before packing
devedse Dec 18, 2025
808bc08
Update to version 101
devedse Dec 30, 2025
5e3e244
Update file version to 1.0.102 and add tests for handling large data …
devedse Dec 31, 2025
0937a4e
to 103
devedse Apr 15, 2026
a63dbb7
iSCSI: Add NOP-Out keepalive and handle target-initiated NOP-In + bum…
devedse Apr 16, 2026
24388ff
Merge upstream/LTRData.DiscUtils-initial into fork
devedse Jun 19, 2026
e587fa1
Fix InvalidCastException in SubKeyIndirectListCell write paths for mi…
devedse Jun 19, 2026
aa72b3f
Bump version to 1.0.105
devedse Jun 19, 2026
2f855a1
Fix Bin.AllocateCell 8-byte alignment check (regressed to % 0x7 by up…
devedse Jun 19, 2026
dd629af
Fix NtfsFileSystem.GetFileLength ignoring FileLengthFromDirectoryEntr…
devedse Jun 19, 2026
950ed00
Fix infinite loop in DynamicStream sector scan (regressed in f7bf7550)
devedse Jun 19, 2026
e1d5c3a
Fix SynchronizedSparseStream Position never advancing (regressed in 4…
devedse Jun 19, 2026
8cc0103
Merge remote-tracking branch 'upstream/LTRData.DiscUtils-initial' int…
devedse Jun 25, 2026
ad6dff0
Bump version to 1.0.106
devedse Jun 25, 2026
6f59aad
Merge upstream/LTRData.DiscUtils-initial into fork (GPT protective MB…
devedse Jul 4, 2026
128e0b2
Strip trailing whitespace to match upstream in Bin.cs and RegistryKey…
devedse Jul 4, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 10 additions & 14 deletions .github/workflows/publish-nuget.yml
Original file line number Diff line number Diff line change
@@ -1,32 +1,28 @@
name: NuGet push (tag)

on:
push:
tags:
- 'v[0-9]+.[0-9]+.[0-9]+'
on:
workflow_dispatch:

env:
DOTNET_CLI_TELEMETRY_OPTOUT: true
DOTNET_NOLOGO: true

jobs:
build:
runs-on: windows-2019
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v5
- name: Setup .NET Core
uses: actions/setup-dotnet@v5
with:
fetch-depth: 50
lfs: 'true'
# We do not need to fetch tags, as we're already at a tagged build - it should be available automatically
dotnet-version: 10.0.x

- name: Setup .NET Core 7.0
uses: actions/setup-dotnet@v1
with:
dotnet-version: '7.0.x'
- name: Build
run: dotnet build -c Release

- name: Pack
run: dotnet pack -c Release -o ${{ github.workspace }}/build
run: dotnet pack -c Release -o ${{ github.workspace }}/build --no-build

- name: NuGet push
run: dotnet nuget push *.nupkg --skip-duplicate -k ${{secrets.NUGET_KEY}} -s https://api.nuget.org/v3/index.json
Expand Down
16 changes: 16 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -386,3 +386,19 @@ artifacts-dotnet-releaser/
# Verify
*.received.*
*#

# Build outputs in Library folder
Library/net*/
Library/netstandard*/
net10.0/

# Build outputs in root
netstandard*/

# Build outputs in Tests folder
Tests/net*/
Tests/netstandard*/

# Build outputs in Utilities folder
Utilities/net*/
Utilities/netstandard*/
6 changes: 4 additions & 2 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,20 @@

<DebugType>portable</DebugType>

<PackageProjectUrl>https://github.com/LTRData/DiscUtils</PackageProjectUrl>
<PackageProjectUrl>https://github.com/Devedse/DiscUtils</PackageProjectUrl>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<RepositoryType>git</RepositoryType>

<Company>LTR Data</Company>
<Authors>Kenneth Bell;LordMike;Olof Lagerkvist</Authors>
<OutputPath>..\$(Configuration)</OutputPath>
<FileVersion>1.0.85</FileVersion>
<FileVersion>1.0.107</FileVersion>
<Version>1.0.107</Version>

<GenerateDocumentationFile>true</GenerateDocumentationFile>

<NoWarn>CS1591;CS0649</NoWarn>
<EmitCompilerGeneratedFiles>false</EmitCompilerGeneratedFiles>

</PropertyGroup>

Expand Down
1 change: 1 addition & 0 deletions DiscUtils.slnx
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
<Project Path="Library/DiscUtils.Xfs/DiscUtils.Xfs.csproj" />
<Project Path="Library/DiscUtils.Xva/DiscUtils.Xva.csproj" />
<Project Path="Library/DiscUtils/DiscUtils.csproj" />
<Project Path="Library/DiscUtils.SourceGenerator/DiscUtils.SourceGenerator.csproj" />
</Folder>
<Folder Name="/Solution Items/">
<File Path=".editorconfig" />
Expand Down
16 changes: 15 additions & 1 deletion Library/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<PropertyGroup>
<TargetFrameworks>netstandard2.0;netstandard2.1;net46;net48;net8.0;net9.0;net10.0</TargetFrameworks>
<GeneratePackageOnBuild Condition="'$(Configuration)' == 'Release'">true</GeneratePackageOnBuild>
<PackageId>LTRData.$(MSBuildProjectName)</PackageId>
<PackageId>Devedse.$(MSBuildProjectName)</PackageId>
<PackageOutputPath>$(LocalNuGetPath)</PackageOutputPath>
<PackageVersion>$(FileVersion)</PackageVersion>
<PackageReadmeFile>README.md</PackageReadmeFile>
Expand All @@ -26,7 +26,21 @@
<PropertyGroup>
<AssemblyOriginatorKeyFile>$(MSBuildThisFileDirectory)../SigningKey.snk</AssemblyOriginatorKeyFile>
<SignAssembly>false</SignAssembly>
<EmitCompilerGeneratedFiles>false</EmitCompilerGeneratedFiles>
<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)Generated</CompilerGeneratedFilesOutputPath>
<DelaySign>false</DelaySign>
</PropertyGroup>

<!-- Add PolySharp for supporting more recent language features -->
<ItemGroup>
<PackageReference Include="PolySharp" Version="1.14.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>

<ItemGroup Condition="'$(IsSourceGenerator)' != 'true'">
<ProjectReference Include="$(MSBuildThisFileDirectory)DiscUtils.SourceGenerator\DiscUtils.SourceGenerator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" GlobalPropertiesToRemove="TargetFramework" SkipGetTargetFrameworkProperties="true" />
</ItemGroup>

</Project>
9 changes: 9 additions & 0 deletions Library/DiscUtils.Core/DiskImageBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,18 @@ public static DiskImageBuilder GetBuilder(string type, string variant)
/// 'foo', the files 'foo.vmdk' and 'foo-flat.vmdk' could be returned.</remarks>
public abstract IEnumerable<DiskImageFileSpecification> Build(string baseName);

// Set this to true to enable AoT compatiblity
public static bool ShouldUseVirtualDiskManagerTypeMap { get; set; }

[MemberNotNull(nameof(_typeMap))]
private static void InitializeMaps()
{
if (ShouldUseVirtualDiskManagerTypeMap)
{
_typeMap = VirtualDiskManager.TypeMap;
return;
}

var typeMap = new Dictionary<string, VirtualDiskFactory>();

foreach (var type in typeof(VirtualDisk).Assembly.GetTypes())
Expand Down
20 changes: 15 additions & 5 deletions Library/DiscUtils.Core/Partitions/PartitionTable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,29 +54,39 @@ public abstract class PartitionTable
/// </summary>
public abstract Geometry? DiskGeometry { get; }

private static List<PartitionTableFactory>? _factories;

private static List<PartitionTableFactory> Factories
{
get
{
if (field == null)
if (_factories == null)
{
var factories = new List<PartitionTableFactory>();

foreach (var type in typeof(VolumeManager).Assembly.GetTypes())
{
foreach (var attr in type.GetCustomAttributes<PartitionTableFactoryAttribute>(false))
{
factories.Add((PartitionTableFactory)Activator.CreateInstance(type)!);
factories.Add((PartitionTableFactory)Activator.CreateInstance(type, true)!);
}
}

field = factories;
_factories = factories;
}

return field;
return _factories;
}
}

internal static void RegisterPartitionTableFactory(PartitionTableFactory factory)
{
if (_factories == null)
{
_factories = new List<PartitionTableFactory>();
}

set;
_factories.Add(factory);
}

/// <summary>
Expand Down
8 changes: 4 additions & 4 deletions Library/DiscUtils.Core/VirtualDisk.cs
Original file line number Diff line number Diff line change
Expand Up @@ -375,12 +375,12 @@ public static VirtualDisk CreateDisk(DiscFileSystem fileSystem, string type, str
var uri = PathToUri(path);
VirtualDisk result;

if (!VirtualDiskManager.DiskTransports.TryGetValue(uri.Scheme, out var transportType))
if (!VirtualDiskManager.DiskTransports.TryGetValue(uri.Scheme, out var transportFactory))
{
throw new FileNotFoundException($"Unable to parse path '{path}'", path);
}

var transport = (VirtualDiskTransport)Activator.CreateInstance(transportType)!;
var transport = transportFactory();

try
{
Expand Down Expand Up @@ -499,12 +499,12 @@ public static VirtualDisk CreateDisk(DiscFileSystem fileSystem, string type, str
var uri = PathToUri(path);
VirtualDisk? result = null;

if (!VirtualDiskManager.DiskTransports.TryGetValue(uri.Scheme, out var transportType))
if (!VirtualDiskManager.DiskTransports.TryGetValue(uri.Scheme, out var transportFactory))
{
throw new FileNotFoundException($"Unable to parse path '{uri}'", path);
}

var transport = (VirtualDiskTransport)Activator.CreateInstance(transportType)!;
var transport = transportFactory();

try
{
Expand Down
51 changes: 45 additions & 6 deletions Library/DiscUtils.Core/VirtualDiskManager.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using System;
using DiscUtils.Internal;
using System;
using System.Collections.Generic;
using System.Reflection;
using DiscUtils.Internal;

namespace DiscUtils;

Expand All @@ -14,10 +14,10 @@ static VirtualDiskManager()
{
ExtensionMap = new Dictionary<string, VirtualDiskFactory>(StringComparer.OrdinalIgnoreCase);
TypeMap = new Dictionary<string, VirtualDiskFactory>(StringComparer.OrdinalIgnoreCase);
DiskTransports = new Dictionary<string, Type>(StringComparer.OrdinalIgnoreCase);
DiskTransports = new Dictionary<string, Func<VirtualDiskTransport>>(StringComparer.OrdinalIgnoreCase);
}

internal static Dictionary<string, Type> DiskTransports { get; }
internal static Dictionary<string, Func<VirtualDiskTransport>> DiskTransports { get; }
internal static Dictionary<string, VirtualDiskFactory> ExtensionMap { get; }

/// <summary>
Expand All @@ -33,7 +33,46 @@ static VirtualDiskManager()
internal static Dictionary<string, VirtualDiskFactory> TypeMap { get; }

/// <summary>
/// Locates VirtualDiskFactory factories attributed with VirtualDiskFactoryAttribute, and types marked with VirtualDiskTransportAttribute, that are able to work with Virtual Disk types.
/// Registers a VirtualDiskFactory instance.
/// </summary>
/// <param name="factory">The factory to register.</param>
public static void RegisterVirtualDiskFactory(VirtualDiskFactory factory)
{
var type = factory.GetType();
var diskFactoryAttribute = type.GetCustomAttribute<VirtualDiskFactoryAttribute>(false);
if (diskFactoryAttribute != null)
{
if (!TypeMap.ContainsKey(diskFactoryAttribute.Type))
{
TypeMap.Add(diskFactoryAttribute.Type, factory);
}

foreach (var extension in diskFactoryAttribute.FileExtensions)
{
if (!ExtensionMap.ContainsKey(extension))
{
ExtensionMap.Add(extension, factory);
}
}
}
}

/// <summary>
/// Registers a VirtualDiskTransport factory.
/// </summary>
/// <param name="scheme">The URI scheme.</param>
/// <param name="factory">The factory method.</param>
internal static void RegisterVirtualDiskTransport(string scheme, Func<VirtualDiskTransport> factory)
{
if (!DiskTransports.ContainsKey(scheme))
{
DiskTransports.Add(scheme, factory);
}
}

/// <summary>
/// Locates VirtualDiskFactory factories attributed with VirtualDiskFactoryAttribute, and types marked with VirtualDiskTransportAttribute,
/// that are able to work with Virtual Disk types.
/// </summary>
/// <param name="assembly">An assembly to scan</param>
public static void RegisterVirtualDiskTypes(Assembly assembly)
Expand All @@ -55,7 +94,7 @@ public static void RegisterVirtualDiskTypes(Assembly assembly)
var diskTransportAttribute = type.GetCustomAttribute<VirtualDiskTransportAttribute>(false);
if (diskTransportAttribute != null)
{
DiskTransports.Add(diskTransportAttribute.Scheme, type);
DiskTransports.Add(diskTransportAttribute.Scheme, () => (VirtualDiskTransport)Activator.CreateInstance(type)!);
}
}
}
Expand Down
31 changes: 25 additions & 6 deletions Library/DiscUtils.Core/VolumeManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,26 +82,45 @@ public VolumeManager(Stream initialDiskContent)

private static readonly object _syncObj = new();

private static ConcurrentBag<LogicalVolumeFactory>? _logicalVolumeFactories;

private static ConcurrentBag<LogicalVolumeFactory> LogicalVolumeFactories
{
get
{
if (field == null)
if (_logicalVolumeFactories == null)
{
lock (_syncObj)
{
if (field == null)
if (_logicalVolumeFactories == null)
{
var factories = new ConcurrentBag<LogicalVolumeFactory>(GetLogicalVolumeFactories(_coreAssembly));
field = factories;
_logicalVolumeFactories = new ConcurrentBag<LogicalVolumeFactory>(GetLogicalVolumeFactories(_coreAssembly));
}
}
}

return field;
return _logicalVolumeFactories;
}
}

/// <summary>
/// Register a new LogicalVolumeFactory instance.
/// </summary>
/// <param name="factory">The factory to register.</param>
internal static void RegisterLogicalVolumeFactory(LogicalVolumeFactory factory)
{
if (_logicalVolumeFactories == null)
{
lock (_syncObj)
{
if (_logicalVolumeFactories == null)
{
_logicalVolumeFactories = new ConcurrentBag<LogicalVolumeFactory>();
}
}
}

set;
_logicalVolumeFactories.Add(factory);
}

private static IEnumerable<LogicalVolumeFactory> GetLogicalVolumeFactories(Assembly assembly)
Expand Down
22 changes: 22 additions & 0 deletions Library/DiscUtils.SourceGenerator/DiscUtils.SourceGenerator.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">


<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<TargetFrameworks></TargetFrameworks>
<IsSourceGenerator>true</IsSourceGenerator>
<Description>Source Generator for DiscUtils</Description>
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
<PackageTags>DiscUtils;SourceGenerator;Analyzer</PackageTags>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.8.0" />
</ItemGroup>

</Project>
Loading
Loading