-
-
Notifications
You must be signed in to change notification settings - Fork 32
Description
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:
DiscUtils/Library/DiscUtils.OpticalDisk/DiscImageFile.cs
Lines 60 to 68 in b379b20
| 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:
DiscUtils/Library/DiscUtils.OpticalDisk/DiscFactory.cs
Lines 58 to 60 in b379b20
| 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.OpenDiskif 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).