]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
eject: Check host_status and driver_status when using SG_IO.
authorKarel Zak <kzak@redhat.com>
Tue, 18 Jun 2013 10:24:28 +0000 (12:24 +0200)
committerKarel Zak <kzak@redhat.com>
Tue, 18 Jun 2013 10:24:28 +0000 (12:24 +0200)
Based on Suse patch, originally from
Anna Bernathova <anicka@suse.cz>, May 2008

  SG_IO completion status is weird but still well defined. You'll need
  to check both host_status, driver_status and status to determine that
  a command actually succeeded. -- Tejun Heo, May 2008

Note that we also need to check driver_status and sense_buffer to
detect situation when there is no medium. It's valid request to call
eject(8) for device with no medium.

References: https://bugzilla.novell.com/show_bug.cgi?id=358033
Signed-off-by: Anna Bernathova <anicka@suse.cz>
Signed-off-by: Karel Zak <kzak@redhat.com>
sys-utils/eject.c

index 4ec69e72992db938ac1ff83874ff44331cbe3a84..f98f2277545d1fba5e00a59d89c300b63ff073e4 100644 (file)
 #include "pathnames.h"
 #include "sysfs.h"
 
+/*
+ * sg_io_hdr_t driver_status -- see kernel include/scsi/scsi.h
+ */
+#ifndef DRIVER_SENSE
+# define DRIVER_SENSE  0x08
+#endif
+
+
 #define EJECT_DEFAULT_DEVICE "/dev/cdrom"
 
 
@@ -604,17 +612,27 @@ static int eject_scsi(int fd)
 
        io_hdr.cmdp = allowRmBlk;
        status = ioctl(fd, SG_IO, (void *)&io_hdr);
-       if (status < 0)
+       if (status < 0 || io_hdr.host_status || io_hdr.driver_status)
                return 0;
 
        io_hdr.cmdp = startStop1Blk;
        status = ioctl(fd, SG_IO, (void *)&io_hdr);
-       if (status < 0)
+       if (status < 0 || io_hdr.host_status)
+               return 0;
+
+       /* Ignore errors when there is not medium -- in this case driver sense
+        * buffer sets MEDIUM NOT PRESENT (3a) bit. For more details see:
+        * http://www.tldp.org/HOWTO/archived/SCSI-Programming-HOWTO/SCSI-Programming-HOWTO-22.html#sec-sensecodes
+        * -- kzak Jun 2013
+        */
+       if (io_hdr.driver_status != 0 &&
+           !(io_hdr.driver_status == DRIVER_SENSE && io_hdr.sbp &&
+                                                     io_hdr.sbp[12] == 0x3a))
                return 0;
 
        io_hdr.cmdp = startStop2Blk;
        status = ioctl(fd, SG_IO, (void *)&io_hdr);
-       if (status < 0)
+       if (status < 0 || io_hdr.host_status || io_hdr.driver_status)
                return 0;
 
        /* force kernel to reread partition table when new disc inserted */