libblkid: detect CD/DVD discs in packet writing mode

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>
This commit is contained in:
Pali Rohár 2020-11-05 19:16:27 +01:00
parent b7bca24476
commit 6b88a410ae
1 changed files with 32 additions and 10 deletions

View 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;
cdrom_size_correction(pr);
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
if (pr->flags & BLKID_FL_CDROM_DEV) {
cdrom_size_correction(pr);
}
}
#endif
free(dm_uuid);