]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
eject: use CDROM_DRIVE_STATUS if available for tray toggling
authorMike Frysinger <vapier@gentoo.org>
Thu, 5 Apr 2012 15:50:46 +0000 (11:50 -0400)
committerKarel Zak <kzak@redhat.com>
Tue, 10 Apr 2012 10:21:27 +0000 (12:21 +0200)
One some platforms, the -T option can be unreliable (see reference bug
report for some examples).  Instead, if the kernel supports the cdrom
status ioctl, use that to ask explicitly for the current tray status
and then open/close accordingly.

The eject_cdrom() func was reworked slightly, but none of the existing
callers care about the explicit normalization to [0,1] values, so have
it return the raw value so we can convert toggle_tray() over to using
that.

Finally, now that toggle_tray() uses a lot of helper functions, drop
the check on CDROMCLOSETRAY.  The sub-functions take care of that.

Reference: https://bugs.gentoo.org/261880
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
sys-utils/eject.c

index 68d5e9c7a7d66e935ac3f8c46c6479d86e084312..245c02836518c7daf8aeec591d7d1a2102372883 100644 (file)
@@ -385,6 +385,22 @@ static void close_tray(int fd)
 #endif
 }
 
+/*
+ * Eject using CDROMEJECT ioctl.
+ */
+static int eject_cdrom(int fd)
+{
+#if defined(CDROMEJECT)
+       return ioctl(fd, CDROMEJECT);
+#elif defined(CDIOCEJECT)
+       return ioctl(fd, CDIOCEJECT);
+#else
+       warnx(_("CD-ROM eject unsupported"));
+       errno = ENOSYS;
+       return -1;
+#endif
+}
+
 /*
  * Toggle tray.
  *
@@ -400,7 +416,21 @@ static void toggle_tray(int fd)
        struct timeval time_start, time_stop;
        int time_elapsed;
 
-#ifdef CDROMCLOSETRAY
+#ifdef CDROM_DRIVE_STATUS
+       /* First ask the CDROM for info, otherwise fall back to manual.  */
+       switch (ioctl(fd, CDROM_DRIVE_STATUS)) {
+       case CDS_TRAY_OPEN:
+               close_tray(fd);
+               return;
+
+       case CDS_NO_DISC:
+       case CDS_DISC_OK:
+               if (eject_cdrom(fd))
+                       err(EXIT_FAILURE, _("CD-ROM eject command failed"));
+               return;
+       }
+#endif
+
        /* Try to open the CDROM tray and measure the time therefor
         * needed.  In my experience the function needs less than 0.05
         * seconds if the tray was already open, and at least 1.5 seconds
@@ -408,7 +438,7 @@ static void toggle_tray(int fd)
        gettimeofday(&time_start, NULL);
 
        /* Send the CDROMEJECT command to the device. */
-       if (ioctl(fd, CDROMEJECT, 0) < 0)
+       if (eject_cdrom(fd) < 0)
                err(EXIT_FAILURE, _("CD-ROM eject command failed"));
 
        /* Get the second timestamp, to measure the time needed to open
@@ -423,10 +453,6 @@ static void toggle_tray(int fd)
         * closed before. This would mean that we are done.  */
        if (time_elapsed < TRAY_WAS_ALREADY_OPEN_USECS)
                close_tray(fd);
-#else
-       warnx(_("CD-ROM tray toggle command not supported by this kernel"));
-#endif
-
 }
 
 /*
@@ -530,20 +556,6 @@ static void list_speeds(const char *name, int fd)
 #endif
 }
 
-/*
- * Eject using CDROMEJECT ioctl. Return 1 if successful, 0 otherwise.
- */
-static int eject_cdrom(int fd)
-{
-#if defined(CDROMEJECT)
-       return ioctl(fd, CDROMEJECT) == 0;
-#elif defined(CDIOCEJECT)
-       return ioctl(fd, CDIOCEJECT) == 0;
-#else
-       warnx(_("CD-ROM eject unsupported"));
-#endif
-}
-
 /*
  * Eject using SCSI SG_IO commands. Return 1 if successful, 0 otherwise.
  */