Skip to content

VirtualDisk.OpenDisk too reliant on extensions? #47

@mitchcapper

Description

@mitchcapper

In general, for the more common disc image extensions (bin/iso/img) if VirtualDisk.OpenDisk returns 0 partitions I always fall back to trying to force a raw type.

Now I am sure part of this is extension abuse where .iso should be a certain spec or what have you but some people do end up using the wrong extension.

I recently noticed that it was throwing an exception when going to access disk.Partitions even though disk.IsPartitioned is true.

due to:

https://github.com/LTRData/DiscUtils/blob/b379b2038392485f58135f58d8c20be254d17686/Library/DiscUtils.Core/Partitions/GuidPartitionTable.cs#L370
throw new IOException("No valid GUID Partition Table found");

 	DiscUtils.Core.dll!DiscUtils.Partitions.GuidPartitionTable.Init(System.IO.Stream disk, DiscUtils.Geometry diskGeometry) Line 370	C#
 	DiscUtils.Core.dll!DiscUtils.Partitions.GuidPartitionTable.GuidPartitionTable(DiscUtils.VirtualDisk disk) Line 51	C#
>	DiscUtils.Core.dll!DiscUtils.Partitions.DefaultPartitionTableFactory.DetectPartitionTable(DiscUtils.VirtualDisk disk) Line 43	C#
 	DiscUtils.Core.dll!DiscUtils.Partitions.PartitionTable.GetPartitionTables(DiscUtils.VirtualDisk disk) Line 126	C#

An example would be: https://download.truenas.com/truenas-scale-goldeye-nightly/TrueNAS-SCALE-25.10.0-MASTER-20250801-015503.iso?wrap=1

maybe they shouldn't be using .iso here but I noticed as well that while DiscImageFile's constructor can attempt to automatically detect the mode:

if (format == OpticalFormat.None)
{
if (stream.Length % Mode1SectorSize == 0 && stream.Length % Mode2SectorSize != 0)
{
_format = OpticalFormat.Mode1;
}
else if (stream.Length % Mode1SectorSize != 0 && stream.Length % Mode2SectorSize == 0)
{
_format = OpticalFormat.Mode2;

When used from the OpenDisk call that is bypassed and extension only is used:

var format = path.EndsWith(".bin", StringComparison.OrdinalIgnoreCase)
? OpticalFormat.Mode2
: OpticalFormat.Mode1;

I am sure again technically extension wise it may meet that spec but certainly img/bin/iso getting used semi-interchangeably means what could be opened would fail down that path. This can be worked around by re-calling the DiscUtils.OpticalDisk.Disc constructor myself without forcing a format and seeing if that succeeds.

Slightly more confusing is that while RAW works, and you get back 4 partitions (including a fat and HFS+ partition) the HFS+ partition throws an exception when you try to access the file system and none of them give you the bulk of files in the ISO (using FileSystemManager.DetectFileSystems(vol) none of them return a CDReader).

FileSystemManager.DetectFileSystems(stream)
will actually return you a CDReader so that would seem to be the correct way to go although that then throws another error but that is another issue #48 :)

In terms of actually trying to enumerate all the files in any img/disk format we are up to:

  • detect and manually open WimFile
  • try VirtualDisk.OpenDisk if that fails: Try the OpticalDisk.Disc constructor. If that fails try RAW
  • Do a final FileSystemManager.DetectFileSystems(stream) and maybe use volume ids or similar to see if we have already handled the FS's detected there (as while it does detect the ISO 9660 FS it then doesn't actually return the EFI fat/HFS systems the other did).

Just to note the idea of using volume ID to eliminate any duplicates between DetectFileSystems(stream) and DetectFileSystems(vol) does not work as while you do get a CDReader for both the volume ids are different (as it ends up just being the hashcode for the object itself for CDReader).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions