Linux系統擷取sata硬碟序號

來源:互聯網
上載者:User

在網上找了擷取SCSI硬碟的序號都沒有很好的解決辦法,網上大多數都是關於IDE硬碟的介紹;經過大量的搜尋現在終於找到一種有效地方法,貼出來給大家分享一下:

代碼如下:

#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <scsi/sg.h>

#define SCSI_TIMEOUT 5000 /* ms */
static char *device = "/dev/sda";

int scsi_io(int fd, unsigned char *cdb, unsigned char cdb_size, int xfer_dir,
            unsigned char *data, unsigned int *data_size,
            unsigned char *sense, unsigned int *sense_len)
{
    sg_io_hdr_t io_hdr;

    memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
    io_hdr.interface_id = 'S';
    /* CDB */
    io_hdr.cmdp = cdb;
    io_hdr.cmd_len = cdb_size;

    /* Where to store the sense_data, if there was an error */
    io_hdr.sbp = sense;
    io_hdr.mx_sb_len = *sense_len;
    *sense_len=0;

    /* Transfer direction, either in or out. Linux does not yet
       support bidirectional SCSI transfers ?
     */
    io_hdr.dxfer_direction = xfer_dir;

    /* Where to store the DATA IN/OUT from the device and how big the
       buffer is
     */
    io_hdr.dxferp = data;
    io_hdr.dxfer_len = *data_size;

    /* SCSI timeout in ms */
    io_hdr.timeout = SCSI_TIMEOUT;

    if(ioctl(fd, SG_IO, &io_hdr) < 0){
        perror("SG_IO ioctl failed");
        return -1;
    }
    /* now for the error processing */
    if((io_hdr.info & SG_INFO_OK_MASK) != SG_INFO_OK){
        if(io_hdr.sb_len_wr > 0){
            *sense_len=io_hdr.sb_len_wr;
            return 0;
        }
    }
    if(io_hdr.masked_status){
        printf("status=0x%x\n", io_hdr.status);
        printf("masked_status=0x%x\n", io_hdr.masked_status);
        return -2;
    }
    if(io_hdr.host_status){
        printf("host_status=0x%x\n", io_hdr.host_status);
        return -3;
    }
    if(io_hdr.driver_status){
        printf("driver_status=0x%x\n", io_hdr.driver_status);
        return -4;
    }
    return 0;
}

int scsi_inquiry_unit_serial_number(int fd)
{
    unsigned char cdb[]={0x12,0x01,0x80,0,0,0};
    unsigned int data_size=0x00ff;
    unsigned char data[data_size];
    unsigned int sense_len=32;
    unsigned char sense[sense_len];
    int res, pl, i;

    cdb[3]=(data_size>>8)&0xff;
    cdb[4]=data_size&0xff;
    printf("INQUIRY Unit Serial Number:\n");

    res=scsi_io(fd, cdb, sizeof(cdb), SG_DXFER_FROM_DEV, data, &data_size, sense, &sense_len);
    if(res){
        printf("SCSI_IO failed\n");
        return -1;
    }
    if(sense_len){
        return -1;
    }

    /* Page Length */
    pl=data[3];

    /* Unit Serial Number */
    printf("Unit Serial Number:");
    for(i=4;i<(pl+4);i++)printf("%c",data[i]&0xff);printf("\n");
    return 0;
}

int open_scsi_device(const char *dev)
{
    int fd, vers;
    if((fd=open(dev, O_RDWR))<0){
        printf("ERROR could not open device %s\n", dev);
        return -1;
    }
    if ((ioctl(fd, SG_GET_VERSION_NUM, &vers) < 0) || (vers < 30000)) {
        printf("/dev is not an sg device, or old sg driver\n");
        close(fd);
        return -1;
    }

    return fd;
}

int main(int argc, const char *argv[])
{
    int fd;
    fd=open_scsi_device(device);
    if(fd<0){
        printf("Could not open SCSI device %s\n",device);
        _exit(10);
    }
   scsi_inquiry_unit_serial_number(fd);
    return 0;
}

註:此方法在虛擬機器下無法擷取到硬碟序號

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.