Skip to content

Read disc files without mounting - #1063

Open
gmipf wants to merge 7 commits into
SabreTools:masterfrom
gmipf:pr/12-read-disc-files
Open

gmipf wants to merge 7 commits into
SabreTools:masterfrom
gmipf:pr/12-read-disc-files

Conversation

@gmipf

@gmipf gmipf commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

As proposed in #1058, MPF reads the files of the disc itself, so the disc does not have to be mounted:

System detection, the volume label, the submission information and the protection scan read the files through the new DiscFileSystem in MPF.Frontend/FileSystems. The mounted path input from c8fe80d stays as it is: a path that is set is still used after dumping and in Check Dump, as now. It is no longer needed for ISO 9660 and UDF discs on any of the three systems, so I can remove it from both Avalonia windows in this pull request if you agree.

On Linux and macOS, the file system and size of the disc in an optical drive are read the same way when the drives are listed, and are named and sized as Windows reports them: CDFS with the size of the ISO 9660 volume, or UDF with the size up to the end of the UDF partition. DriveInfo only reports them for a mounted disc, and on macOS it reports cd9660 and a different size for the mount point. On macOS, the disc is read from the raw device of the whole disc, which the user logged in at the console can read while macOS has the disc mounted. The media type detection and the size check of the Xbox 360 detection use them.

After a dump, a drive path that is not a folder is no longer scanned as one. The files of the dump image are scanned instead, also by MPF.Check with --scan and without --path. The scanner takes paths, so the files are written to a temporary folder, but only what the scanner reads: files of a known type that open as that type are copied in full, all other files only get the bytes read to identify and open them, with their full length as a sparse file, so the path checks still see them. On Windows, the new "Scan Dump Image Files" option scans the dump image instead of the drive letter; on Linux and macOS it is hidden, as the dump image is scanned there anyway. If no files can be read at all, neither from the dump image nor from the drive, the protection field says [EXTERNAL SCAN NEEDED], the marker MPF already uses when no scan was run, instead of "No protections found".

This needs a Serialization release with SabreTools/SabreTools.Serialization#99 and SabreTools/SabreTools.Serialization#100, and the UDF reader in turn needs a SabreTools.IO release with SabreTools/SabreTools.IO#3. The package versions are not changed here, so the build fails until they are bumped. The measurements below use local packages built from both pull requests.

Measured:

  • Commandos - Hinter feindlichen Linien (Germany) (Rerelease), Linux, disc in the drive and not mounted: CD-Lock in 20.0–20.7 s, the same result as mounting and scanning in 22.1–22.5 s. The current code scans the device path as a single file and reports "No protections found".
  • Kingdoms of Amalur - Reckoning (Germany), Windows, the 8.1 GB UDF image: scanning the image without mounting in 172–179 s, mounting it with Mount-DiskImage and scanning in 185–204 s, with the same protections and a similar peak memory (478–513 vs 473–525 MB). This run also included Locate the PKZIP file data instead of reading it into the model SabreTools.Serialization#102.
  • Star Wars - Episode I - Die dunkle Bedrohung (Germany) (Rerelease), MPF.Check with --scan and no --path, no disc: Bitpool from the dump image on Linux, macOS and Windows.
  • A PlayStation 2 disc on Linux: detected as Sony PlayStation 2, with serial, version and EXE date, both from the drive without a mount and on the mounted disc, where Linux shows the file names in lower case. The current code detects it in neither case: it cannot read the device path, and on the mounted disc it looks for SYSTEM.CNF with exact case.
  • File system, size and media type on Linux, macOS and Windows, with the Commandos - Hinter feindlichen Linien (Germany) (Rerelease) disc in the drive and five disc images (two CDs, two DVDs and an Xbox 360 disc), mounted with Mount-DiskImage on Windows and attached with hdiutil and read like a drive on macOS, where one of the DVD images was also inserted into the virtual drive of a VM: the same values on all three, for example CDFS and 495921152 bytes for Commandos, UDF and 7204864 bytes for the Xbox 360 disc. The current code has neither on Linux, has no file system and the size of the whole disc in raw sectors on macOS (806512560 bytes for Commandos), and detects no media type on either. Listing the drives now reads the disc in each drive that has one: on Linux, with the Commandos disc spinning, listing took 62–88 ms instead of 20–22 ms, and 2.1 s when the disc first had to spin up; on macOS, in a VM with the drive passed through by USB, reading the Commandos disc takes 253–283 ms, and listing took 3.1–3.5 s instead of 2.5–2.9 s.

Prepared with AI assistance (Claude Opus 5.5) and reviewed before submission.

gmipf and others added 3 commits October 19, 2026 19:53
DiscFileSystem gives read-only access to the files of a disc. A drive
letter or a mounted folder is read as a folder, a dump image or the
device path of an optical drive on Linux is read through the ISO 9660
and UDF readers of SabreTools.Serialization, and on macOS the mount
point macOS created is found with "mount".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
System detection, the submission information and the protection scan
read the files of the disc through DiscFileSystem, so a disc in a drive
that is not mounted is read as well. After a dump, a drive path that is
not a folder is no longer scanned as one: the files of the dump image
are scanned instead, writing to a temporary folder only what the
scanner reads. The new "Scan Dump Image Files" option does the same for
drive letters on Windows, and MPF.Check scans the dump image when
--scan is given without --path.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Opening the device of an optical drive makes the Linux kernel close the
tray if it is open, and MPF opens the device to read the disc files when
it starts, when a drive is selected and when the label is updated. udev
keeps whether there is a disc in the drive, so the device is not opened
if udev saw no disc in it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@gmipf

gmipf commented Oct 19, 2026

Copy link
Copy Markdown
Contributor Author

While testing on Linux, I found that this pull request closes an open tray. Opening the device of an optical drive makes the kernel close the tray if it is open, and the device is now opened to read the disc files when MPF starts, when a drive is selected and when the label is updated. A /dev/sg* drive is read through its block device, so selecting it closes the tray as well. d823f15 reads the entry of the drive in the udev database first, which says whether there is a disc in the drive without accessing it, and does not open the device if there is none. Without a udev entry for the drive, the device is opened as before.

Measured on Linux with the tray open:

  • master, ASUS BW-16D1HT: the tray stays open when /dev/sr0 is selected.
  • 5b9ceb8, ASUS BW-16D1HT: the tray closes when MPF starts with /dev/sg0 selected, when /dev/sr0 is selected and when the label is updated.
  • 5b9ceb8, Plextor PX-760A: reading /dev/sr2 the way MPF does when the drive is selected closes the tray, waits 9.7 s for the drive and finds no file system yet.
  • d823f15, ASUS BW-16D1HT: the tray stays open when /dev/sg0 or /dev/sr0 is selected and when the label is updated.
  • d823f15, Plextor PX-760A: the tray stays open in 3 cycles of 5 reads each of /dev/sr2 and /dev/sg5.

After the tray is closed, the disc is read again once udev has seen it, on both drives. A disc that was just inserted is therefore read a little later than before: on the Plextor, udev saw the disc 2.5 s after the tray had closed in 3 of 3 cycles. In 3 other cycles, my test program also asked the drive for its status every 100 ms, which opens the device. There the drive reported the disc as ready after 0.8 s, and udev saw it after 2.5 s twice, but after 65 s once, so a program that keeps opening the drive can delay it.

Generated with Claude Opus 5.5.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
DriveInfo does not report the file system and size of a disc that is
not mounted, so on Linux the media type could not be detected from
them and the size check of the Xbox 360 detection always passed. They
are now read from the disc in an optical drive when the drives are
listed and when a drive is refreshed, with the readers used for its
files, and named and sized as Windows reports them for a mounted disc:
CDFS with the size of the ISO 9660 volume, or UDF with the size up to
the end of the UDF partition.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@gmipf

gmipf commented Oct 20, 2026

Copy link
Copy Markdown
Contributor Author

Added 7c255c8: on Linux, DriveFormat and TotalSize of an optical drive are now read from the disc when the drives are listed and when a drive is refreshed, and are named and sized as DriveInfo reports them on Windows, so the media type is detected the same way. I added the measurements to the description.

Generated with Claude Opus 5.5.

Opening the device of a drive with an open tray makes the kernel close
the tray. udev notices an opened tray up to two seconds later, so
reading the disc in that moment still closed the tray. The device is
now opened with O_NONBLOCK, which leaves the tray as it is, and reads
fail while there is no disc. It is still read in random order, as
before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@gmipf

gmipf commented Oct 20, 2026

Copy link
Copy Markdown
Contributor Author

Added 2bd0d6d: opening the device of a drive with an open tray makes the kernel close the tray, and udev notices an opened tray up to two seconds later, so reading the disc in that moment still closed the tray. The device is now opened with O_NONBLOCK, which leaves the tray as it is. FileStream cannot open a file with O_NONBLOCK, so the device is opened with open from libc, and posix_fadvise keeps the random access that FileOptions.RandomAccess set before.

Measured on Linux, reading the disc right after the tray was opened while udev still reported the disc: before this commit, the tray was closed again 3 of 3 times and the read took 9.7–11.2 s; now the tray stayed open 3 of 3 times and the read returned after 7–23 ms without a file system. With the Commandos - Hinter feindlichen Linien (Germany) (Rerelease) disc in the drive, reading its whole directory tree takes the same 102400 bytes from the drive as before, and a stopped disc is spun up and read as before.

Generated with Claude Opus 5.5.

On macOS, the file system of a disc was left empty and its size was the
size of the whole disc that diskutil reports, in raw 2352-byte sectors
for a CD, so the media type was not detected. They are now read from the
disc in an optical drive when the drives are listed, like on Linux, from
the raw device of the whole disc, which belongs to the user logged in at
the console. The devices of the single tracks belong to root, and the
block device of the whole disc cannot be opened when the disc has audio
tracks, as macOS mounts them on it. The raw device can only be read in
whole blocks, so VolumeStream can now read whole blocks and keeps the
ones it read, as reading the file system reads some sectors more than
once and the raw device does not cache them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@gmipf

gmipf commented Oct 20, 2026

Copy link
Copy Markdown
Contributor Author

Added 07c2a15: the same on macOS. DriveFormat and TotalSize of an optical drive are now read from the disc when the drives are listed, and named and sized as on Windows and Linux. The disc is read from the raw device of the whole disc (/dev/rdiskN), which belongs to the user logged in at the console and can be read while macOS has the disc mounted. The devices of the single tracks belong to root, and the block device of the whole disc (/dev/diskN) cannot be opened when the disc has audio tracks, as macOS mounts them on it as the "Audio CD" volume. The raw device only reads whole blocks, raw 2352-byte sectors on a CD, so VolumeStream now reads whole blocks when it is given a block size and keeps up to 64 of them, since the volume descriptors are read more than once and the raw device does not cache them.

Measured on macOS 26.5 in a VM, with the drive passed through by USB and the Commandos - Hinter feindlichen Linien (Germany) (Rerelease) disc in it: CDFS and 495921152 bytes, detected as a CD, the same as on Windows. The current code gives no file system and 806512560 bytes, the size of the whole disc in raw sectors, and detects no media type. The five disc images from the description, attached with hdiutil and read the same way, give the same file system and size as on Windows. One of the DVD images, inserted into the virtual SATA drive of the VM, which macOS lists as an optical drive with a DVD of 2048-byte blocks, gives UDF and 1869281280 bytes and is detected as a DVD, the same as on Windows; the current code gives no file system and 1869873152 bytes and detects no media type. Reading the Commandos disc takes 5 reads from the drive and 253–283 ms, and listing the drives took 3.1–3.5 s instead of 2.5–2.9 s; diskutil info alone takes about a second per call in the VM. The Commandos disc stays mounted, and RefreshDrive leaves the values as they were listed, as before.

Generated with Claude Opus 5.5.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant