]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libblkid: detect CD/DVD discs in packet writing mode
authorPali Rohár <pali.rohar@gmail.com>
Thu, 5 Nov 2020 18:16:27 +0000 (19:16 +0100)
committerPali Rohár <pali.rohar@gmail.com>
Tue, 10 Nov 2020 22:21:13 +0000 (23:21 +0100)
Packet writing mode for CD and DVD discs is provided by kernel module
pktcdvd.ko which exports block devices /dev/pktcdvd/pktcdvd*.

These block devices do not accept CDROM_DRIVE_STATUS ioctl, therefore
current blkid code does not detect them as BLKID_FL_CDROM_DEV and also
does not do necessary size correction.

Extend detection of CD/DVD discs by additional CDROM_LAST_WRITTEN ioctl
which is accepted also by pktcdvd.ko.

Signed-off-by: Pali Rohár <pali.rohar@gmail.com>
libblkid/src/probe.c

index 093fad1b64f4a799787c429bb1576c99d357db7f..ab88efc7249c04fdda7e1e196b6da58e06009bd8 100644 (file)
@@ -864,6 +864,9 @@ int blkid_probe_set_device(blkid_probe pr, int fd,
        struct stat sb;
        uint64_t devsiz = 0;
        char *dm_uuid = NULL;
+#ifdef CDROM_GET_CAPABILITY
+       long last_written = 0;
+#endif
 
        blkid_reset_probe(pr);
        blkid_probe_reset_buffers(pr);
@@ -945,19 +948,38 @@ int blkid_probe_set_device(blkid_probe pr, int fd,
        else if (S_ISBLK(sb.st_mode) &&
            !blkid_probe_is_tiny(pr) &&
            !dm_uuid &&
-           blkid_probe_is_wholedisk(pr) &&
-           ioctl(fd, CDROM_GET_CAPABILITY, NULL) >= 0) {
+           blkid_probe_is_wholedisk(pr)) {
+
+               /**
+                * pktcdvd.ko accepts only these ioctls:
+                *   CDROMEJECT CDROMMULTISESSION CDROMREADTOCENTRY
+                *   CDROM_LAST_WRITTEN CDROM_SEND_PACKET SCSI_IOCTL_SEND_COMMAND
+                * So CDROM_GET_CAPABILITY cannot be used for detecting pktcdvd
+                * devices. But CDROM_GET_CAPABILITY and CDROM_DRIVE_STATUS are
+                * fast so use them for detecting if medium is present. In any
+                * case use last written block form CDROM_LAST_WRITTEN.
+                */
 
+               if (ioctl(fd, CDROM_GET_CAPABILITY, NULL) >= 0) {
 # ifdef CDROM_DRIVE_STATUS
-               switch (ioctl(fd, CDROM_DRIVE_STATUS, CDSL_CURRENT)) {
-               case CDS_TRAY_OPEN:
-               case CDS_NO_DISC:
-                       errno = ENOMEDIUM;
-                       goto err;
+                       switch (ioctl(fd, CDROM_DRIVE_STATUS, CDSL_CURRENT)) {
+                       case CDS_TRAY_OPEN:
+                       case CDS_NO_DISC:
+                               errno = ENOMEDIUM;
+                               goto err;
+                       }
+# endif
+                       pr->flags |= BLKID_FL_CDROM_DEV;
                }
+
+# ifdef CDROM_LAST_WRITTEN
+               if (ioctl(fd, CDROM_LAST_WRITTEN, &last_written) == 0)
+                       pr->flags |= BLKID_FL_CDROM_DEV;
 # endif
-               pr->flags |= BLKID_FL_CDROM_DEV;
-               cdrom_size_correction(pr);
+
+               if (pr->flags & BLKID_FL_CDROM_DEV) {
+                       cdrom_size_correction(pr);
+               }
        }
 #endif
        free(dm_uuid);