2010-04-23 26 views
6

Làm thế nào để tìm hiểu xem thiết bị SCSI (nói/dev/sda) là một đĩa hay không thông qua các cuộc gọi ioctl hoặc khác? Tôi đã thử cách sau nhưng cuộc gọi ioctl không thành công. My/dev/sda là một ổ đĩa flash USB.Làm thế nào để tìm hiểu xem thiết bị SCSI (nói/etc/sda) là một đĩa hay không thông qua các cuộc gọi ioctl hoặc khác?

#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 

Trả lời

5

Tôi đã giải quyết điều này bằng SG_IO và giải thích các dữ liệu nhị phân trực tiếp theo đặc điểm kỹ thuật của INQUIRY command (lĩnh vực: ngoại vi loại thiết bị) và giải thích chúng theo SCSI Peripheral Device Types (là đĩa nếu mỗi dev loại hoặc là 00h hoặc 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; 
    } 
} 
1

Có thể bạn có thể nhận thông tin hữu ích từ/sys/bus/scsi/devices/*/filesystem.

+0

ty, nó sẽ giúp ích, tôi sẽ tìm hiểu thêm để làm điều đó thông qua ioctl khó khăn. [root @ localhost ~] # cat/proc/scsi/scsi các thiết bị kèm theo: Host: Kênh scsi1: 00 Mã sản phẩm: 00 Lun: 00 Vendor: SanDisk mẫu: Cruzer Rev: 8.01 ** Loại: trực tiếp- Truy cập ** Sửa đổi ANSI SCSI: 02 – clyfe

1

HDIO_GET_IDENTITY dường như hoạt động với tôi trên đĩa nhưng không hoạt động trên ổ đĩa flash. Tôi nghĩ rằng đây là những gì sử dụng hdparm -i.

+0

Nó hoạt động trên một đĩa SCSI (/ dev/sd *)? – clyfe

+0

Nó hoạt động trên đĩa SATA sử dụng libata để xuất hiện dưới dạng '/ dev/sda'. Tôi không có một đĩa SCSI xung quanh để kiểm tra. –