summaryrefslogtreecommitdiffstats
path: root/sys-utils/eject.c
diff options
context:
space:
mode:
authorMike Frysinger2012-04-05 17:50:46 +0200
committerKarel Zak2012-04-10 12:21:27 +0200
commitdf3449d541701b9e41ed5fb33e9dbf2bd601094c (patch)
tree6d09fc98d865080a27dbe42fb395e33156a54542 /sys-utils/eject.c
parenteject(1): fix typo in mount(1) reference (diff)
downloadkernel-qcow2-util-linux-df3449d541701b9e41ed5fb33e9dbf2bd601094c.tar.gz
kernel-qcow2-util-linux-df3449d541701b9e41ed5fb33e9dbf2bd601094c.tar.xz
kernel-qcow2-util-linux-df3449d541701b9e41ed5fb33e9dbf2bd601094c.zip
eject: use CDROM_DRIVE_STATUS if available for tray toggling
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>
Diffstat (limited to 'sys-utils/eject.c')
-rw-r--r--sys-utils/eject.c52
1 files changed, 32 insertions, 20 deletions
diff --git a/sys-utils/eject.c b/sys-utils/eject.c
index 68d5e9c7a..245c02836 100644
--- a/sys-utils/eject.c
+++ b/sys-utils/eject.c
@@ -386,6 +386,22 @@ static void close_tray(int fd)
}
/*
+ * 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.
*
* Written by Benjamin Schwenk <benjaminschwenk@yahoo.de> and
@@ -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
-
}
/*
@@ -531,20 +557,6 @@ static void list_speeds(const char *name, int fd)
}
/*
- * 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.
*/
static int eject_scsi(int fd)