How do I know if a SCSI device (such as / etc / sda) is a disk or not through ioctl calls or something else?

How do I know if a SCSI device (such as / dev / sda) is a disk or not through ioctl calls or something else? I tried the following, but the ioctl call failed. My / dev / sda is a USB flash drive.

 #include <stdlib.h> #include <stdio.h> #include <string.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> #include <scsi/scsi.h> #include <scsi/sg.h> #include <sys/ioctl.h> int main(int argc, char** argv) { char *dev = "/dev/sda"; struct sg_scsi_id m_id; int rc; int fd; fd = open(dev, O_RDONLY | O_NONBLOCK); if (fd < 0) { perror(dev); } memset(&m_id, 0, sizeof (m_id)); rc = ioctl(fd, SG_GET_SCSI_ID, &m_id); if (rc < 0) { close(fd); printf("FAIL: ioctl SG_GET_SCSI_ID, rc=%d, errno=%d\n", rc, errno); } else { if (m_id.scsi_type == TYPE_DISK || m_id.scsi_type == 14) { printf("OK: is disk\n"); } else { printf("OK: is NOT disk\n"); } } close(fd); return (EXIT_SUCCESS); } // result is: FAIL: ioctl SG_GET_SCSI_ID, rc=-1, errno=22 
+6
c linux driver ioctl scsi
source share
3 answers

I solved this with SG_IO and interpreted the binary data directly according to the specification of the INQUIRY command (field: type of peripheral device) and interpreting it according to the Types of peripheral devices SCSI (this is the type of disk if each of them has the value 00h or 0Eh)

 int is_disk_sd(char *dev) { unsigned char sense[32]; struct sg_io_hdr io_hdr; char scsi_data[SCSI_LEN]; struct hd_geometry geo; // request for "standard inquiry data" unsigned char inq_cmd[] = {INQUIRY, 0, 0, 0, SCSI_LEN, 0}; int fd; fd = open(dev, O_RDONLY | O_NONBLOCK); if (fd < 0) { perror(dev); } memset(&io_hdr, 0, sizeof (io_hdr)); io_hdr.interface_id = 'S'; io_hdr.cmdp = inq_cmd; io_hdr.cmd_len = sizeof (inq_cmd); io_hdr.dxferp = scsi_data; io_hdr.dxfer_len = sizeof (scsi_data); io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; io_hdr.sbp = sense; io_hdr.mx_sb_len = sizeof (sense); io_hdr.timeout = 5000; if (ioctl(fd, SG_IO, &io_hdr) < 0) { close(fd); return 0; } else { close(fd); if (scsi_data[1] & 0x80) { return 0; // support is removable } if ((scsi_data[0] & 0x1f) || ((scsi_data[0] & 0x1f) != 0xe)) { // 0 or 14 (00h or 0Eh) return 0; // not direct access neither simplified direct access device } return 1; } } 
+5
source share

Perhaps you can get useful information from / sys / bus / scsi / devices / * / filesystem.

+1
source share

HDIO_GET_IDENTITY seems to work for me on disks, but not on flash drives. I think this is what hdparm -i uses.

+1
source share