コード例 #1
0
ファイル: Command.cs プロジェクト: KailoKyra/DiscImageChef
        /// <summary>Sends a SCSI command</summary>
        /// <returns>0 if no error occurred, otherwise, errno</returns>
        /// <param name="fd">File handle</param>
        /// <param name="cdb">SCSI CDB</param>
        /// <param name="buffer">Buffer for SCSI command response</param>
        /// <param name="senseBuffer">Buffer with the SCSI sense</param>
        /// <param name="timeout">Timeout in seconds</param>
        /// <param name="direction">SCSI command transfer direction</param>
        /// <param name="duration">Time it took to execute the command in milliseconds</param>
        /// <param name="sense">
        ///     <c>True</c> if SCSI error returned non-OK status and <paramref name="senseBuffer" /> contains SCSI
        ///     sense
        /// </param>
        internal static int SendScsiCommand(int fd, byte[] cdb, ref byte[] buffer, out byte[] senseBuffer, uint timeout,
                                            ScsiIoctlDirection direction, out double duration, out bool sense)
        {
            senseBuffer = null;
            duration    = 0;
            sense       = false;

            if (buffer == null)
            {
                return(-1);
            }

            var ioHdr = new SgIoHdrT();

            senseBuffer = new byte[32];

            ioHdr.interface_id    = 'S';
            ioHdr.cmd_len         = (byte)cdb.Length;
            ioHdr.mx_sb_len       = (byte)senseBuffer.Length;
            ioHdr.dxfer_direction = direction;
            ioHdr.dxfer_len       = (uint)buffer.Length;
            ioHdr.dxferp          = Marshal.AllocHGlobal(buffer.Length);
            ioHdr.cmdp            = Marshal.AllocHGlobal(cdb.Length);
            ioHdr.sbp             = Marshal.AllocHGlobal(senseBuffer.Length);
            ioHdr.timeout         = timeout * 1000;
            ioHdr.flags           = (uint)SgFlags.DirectIo;

            Marshal.Copy(buffer, 0, ioHdr.dxferp, buffer.Length);
            Marshal.Copy(cdb, 0, ioHdr.cmdp, cdb.Length);
            Marshal.Copy(senseBuffer, 0, ioHdr.sbp, senseBuffer.Length);

            DateTime start = DateTime.UtcNow;
            int      error = Extern.ioctlSg(fd, LinuxIoctl.SgIo, ref ioHdr);
            DateTime end   = DateTime.UtcNow;

            if (error < 0)
            {
                error = Marshal.GetLastWin32Error();
            }

            Marshal.Copy(ioHdr.dxferp, buffer, 0, buffer.Length);
            Marshal.Copy(ioHdr.cmdp, cdb, 0, cdb.Length);
            Marshal.Copy(ioHdr.sbp, senseBuffer, 0, senseBuffer.Length);

            sense |= (ioHdr.info & SgInfo.OkMask) != SgInfo.Ok;

            duration = ioHdr.duration > 0 ? ioHdr.duration : (end - start).TotalMilliseconds;

            Marshal.FreeHGlobal(ioHdr.dxferp);
            Marshal.FreeHGlobal(ioHdr.cmdp);
            Marshal.FreeHGlobal(ioHdr.sbp);

            return(error);
        }
コード例 #2
0
 internal static extern int ioctlSg(int fd, LinuxIoctl request, ref SgIoHdrT value);