-
Notifications
You must be signed in to change notification settings - Fork 2
Description
LinuxIoctlCommandExecuter _os_send() is dropping the return from fcntl.ioctl(). It appears the code is expecting the "mutable" nature (https://docs.python.org/2/library/fcntl.html) of the buffer to allow ioctl to update the original buffer. However, it seems that is not the case when using source_buffer.to_raw(). The net result of this is the lack of CheckCondition exceptions raised on failing commands, as _os_receive() is returning the original buffer but it does not have status or the other data filled in by the host.
Link to code in question:
infi.asi/src/infi/asi/linux.py
Line 282 in db2ad7b
| class LinuxIoctlCommandExecuter(LinuxCommandExecuter): |
Two possible fixes are here in the test code as well. I prefer the capturing of the ioctl return & keeping the input and output SGIO separate, as that makes some logging and debugging easier. It does come at the cost of more memory & processing.
In the test here, status should be 2, along with the other data indicating the error. In this particular case, the command should be generating a SCSI Check Condition with 'MEDIUM NOT PRESENT'.
Test code:
import fcntl
import os
from infi.asi import SCSIReadCommand
from infi.asi.linux import SGIO
SG_IO = 0x2285
TUR = b"\x00" * 6
command = SCSIReadCommand(TUR, 0)
sgio = SGIO.create(1, command, 30)
print "ORIG COMMAND:", sgio
drive_fd = os.open('/dev/nst1', os.O_RDWR|os.O_NONBLOCK)
print "="*8, "ALL NOPES", "="*8
foo = fcntl.ioctl(drive_fd, SG_IO, sgio.to_raw())
print "retdata type, len:", type(foo), len(foo)
resp_sgio = sgio.from_string(foo)
print resp_sgio
# this works, buffer is seen as mutable by fcntl.ioctl()
print "="*8, "RAINBOWS", "="*8
foo = fcntl.ioctl(drive_fd, SG_IO, ctypes.addressof(sgio.source_buffer))
print "retdata type, value:", type(foo), foo
print sgio
Code output, using a TUR command to a tape drive that doesn't have media (it was handy).
ORIG COMMAND: SGIO(interface_id=83, dxfer_direction=-1, cmd_len=6, mx_sb_len=255, iovec_count=0, dxfer_len=0, dxferp=None, cmdp=35466208, sbp=33181424, timeout=30, flags=1, pack_id=1, usr_ptr=None, status=0, masked_status=0, msg_status=0, sb_len_wr=0, host_status=0, driver_status=0, resid=0, duration=0, info=0)
======== ALL NOPES ========
retdata type, len: <type 'str'> 88
BUG!! original status == 0 (should be 2): 0
Processed return SGIO: SGIO(interface_id=83, dxfer_direction=-1, cmd_len=6, mx_sb_len=255, iovec_count=0, dxfer_len=0, dxferp=None, cmdp=18422752, sbp=16949824, timeout=30, flags=1, pack_id=1, usr_ptr=None, status=2, masked_status=1, msg_status=0, sb_len_wr=96, host_status=0, driver_status=8, resid=0, duration=0, info=1)
======== RAINBOWS ========
retdata type, value: <type 'int'> 0
SGIO(interface_id=83, dxfer_direction=-1, cmd_len=6, mx_sb_len=255, iovec_count=0, dxfer_len=0, dxferp=None, cmdp=18422752, sbp=16949824, timeout=30, flags=1, pack_id=1, usr_ptr=None, status=2, masked_status=1, msg_status=0, sb_len_wr=96, host_status=0, driver_status=8, resid=0, duration=1, info=1)```