点击(此处)折叠或打开
- #ifndef HARDDISK_H
- #define HARDDISK_H
- #include <string>
- #define SCSI_TIMEOUT 5000 /* ms */
- class HardDiskInfo
- {
- public:
- HardDiskInfo(std::string name);
- ~HardDiskInfo();
- std::string serial_number();
- private:
- void initialize();
- int device_fd;
- std::string device_name;
- };
- #endif /*HARDDISK_H*/
点击(此处)折叠或打开
- #include "harddiskinfo.h"
- #include <string.h>
- #include <cstdio>
- #include <cstdlib>
- #include <cerrno>
- #include <fcntl.h>
- #include <unistd.h>
- #include <linux/types.h>
- #include <linux/hdreg.h>
- #include <sys/ioctl.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <sys/ioctl.h>
- #include <scsi/sg.h>
- #include <iostream>
- using std::cerr;
- using std::endl;
- using std::hex;
- HardDiskInfo::HardDiskInfo(std::string name) :
- device_name(name)
- {
- initialize();
- }
- HardDiskInfo::~HardDiskInfo()
- {
- close(device_fd);
- }
- static 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';
- 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 error");
- 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)
- {
- cerr << "status: 0x" << hex << io_hdr.status << endl;
- cerr << "masked_status: 0x" << hex << io_hdr.masked_status << endl;
- return -2;
- }
- if(io_hdr.host_status)
- {
- cerr << "host_status: 0x" << hex << io_hdr.host_status << endl;
- return -3;
- }
- if(io_hdr.driver_status)
- {
- cerr << "driver_status: 0x" << hex << io_hdr.driver_status << endl;
- return -4;
- }
- return 0;
- }
- static void device_serial_num(int device_fd, std::string *serial_number)
- {
- 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];
- char result[32] = {0};
- int res, pl, i;
- cdb[3] = (data_size >>8) & 0xff;
- cdb[4] = data_size & 0xff;
- res=scsi_io(device_fd, cdb, sizeof(cdb), SG_DXFER_FROM_DEV, data, &data_size, sense, &sense_len);
- if(res)
- {
- perror("ioctl(SG_DXFER_FROM_DEV) error");
- }
- if(sense_len)
- {
- ;
- }
- /* Page Length */
- pl=data[3];
- int m = 0;
- for(i = 4;i < (pl + 4); i++)
- result[m++] = data[i] & 0xff;
- serial_number->assign(result);
- }
- std::string HardDiskInfo::serial_number()
- {
- std::string hd_serno;
- device_serial_num(device_fd, &hd_serno);
- return hd_serno;
- }
- void HardDiskInfo::initialize()
- {
- int vers;
- device_fd = open(device_name.c_str(), O_RDONLY);
- if (device_fd == -1)
- {
- perror("Can not open the specified device");
- exit(EXIT_FAILURE);
- }
- if ((ioctl(device_fd, SG_GET_VERSION_NUM, &vers) < 0) || (vers < 30000))
- {
- perror("The specified device is not a sg device, or old sg device");
- close(device_fd);
- exit(EXIT_FAILURE);
- }
- }