一个简单的磁盘序列号获取类

3890阅读 0评论2014-06-05 zealoussnow
分类:C/C++

之前写的一个用于获取磁盘序列号的一个类,封装的不太好,莫见笑...
harddiskinfo.h

点击(此处)折叠或打开

  1. #ifndef HARDDISK_H
  2. #define HARDDISK_H

  3. #include <string>

  4. #define SCSI_TIMEOUT 5000 /* ms */

  5. class HardDiskInfo
  6. {
  7. public:
  8.     HardDiskInfo(std::string name);
  9.     ~HardDiskInfo();
  10.     std::string serial_number();

  11. private:
  12.     void initialize();
  13.     int device_fd;
  14.     std::string device_name;
  15. };

  16. #endif /*HARDDISK_H*/
harddiskinfo.cpp

点击(此处)折叠或打开

  1. #include "harddiskinfo.h"

  2. #include <string.h>
  3. #include <cstdio>
  4. #include <cstdlib>
  5. #include <cerrno>

  6. #include <fcntl.h>
  7. #include <unistd.h>
  8. #include <linux/types.h>
  9. #include <linux/hdreg.h>
  10. #include <sys/ioctl.h>
  11. #include <sys/types.h>
  12. #include <sys/stat.h>
  13. #include <sys/ioctl.h>
  14. #include <scsi/sg.h>

  15. #include <iostream>

  16. using std::cerr;
  17. using std::endl;
  18. using std::hex;

  19. HardDiskInfo::HardDiskInfo(std::string name) :
  20.     device_name(name)
  21. {
  22.     initialize();
  23. }

  24. HardDiskInfo::~HardDiskInfo()
  25. {
  26.     close(device_fd);
  27. }
  28. static int scsi_io(int fd, unsigned char *cdb, unsigned char cdb_size, int xfer_dir,
  29.         unsigned char *data, unsigned int *data_size,
  30.         unsigned char *sense, unsigned int *sense_len)
  31. {
  32.     sg_io_hdr_t io_hdr;

  33.     memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
  34.     io_hdr.interface_id = 'S';

  35.     io_hdr.cmdp = cdb;
  36.     io_hdr.cmd_len = cdb_size;

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

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

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

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

  54.     if(ioctl(fd, SG_IO, &io_hdr) < 0)
  55.     {
  56.         perror("SG_IO ioctl error");
  57.         return -1;
  58.     }

  59.     /* now for the error processing */
  60.     if((io_hdr.info & SG_INFO_OK_MASK) != SG_INFO_OK)
  61.     {
  62.         if(io_hdr.sb_len_wr > 0)
  63.         {
  64.             *sense_len=io_hdr.sb_len_wr;
  65.             return 0;
  66.         }
  67.     }
  68.     if(io_hdr.masked_status)
  69.     {
  70.         cerr << "status: 0x" << hex << io_hdr.status << endl;
  71.         cerr << "masked_status: 0x" << hex << io_hdr.masked_status << endl;
  72.         return -2;
  73.     }
  74.     if(io_hdr.host_status)
  75.     {
  76.         cerr << "host_status: 0x" << hex << io_hdr.host_status << endl;
  77.         return -3;
  78.     }
  79.     if(io_hdr.driver_status)
  80.     {
  81.         cerr << "driver_status: 0x" << hex << io_hdr.driver_status << endl;
  82.         return -4;
  83.     }
  84.     return 0;
  85. }

  86. static void device_serial_num(int device_fd, std::string *serial_number)
  87. {
  88.     unsigned char cdb[] = {0x12,0x01,0x80,0,0,0};
  89.     unsigned int data_size = 0x00ff;
  90.     unsigned char data[data_size];
  91.     unsigned int sense_len = 32;
  92.     unsigned char sense[sense_len];
  93.     char result[32] = {0};
  94.     int res, pl, i;

  95.     cdb[3] = (data_size >>8) & 0xff;
  96.     cdb[4] = data_size & 0xff;

  97.     res=scsi_io(device_fd, cdb, sizeof(cdb), SG_DXFER_FROM_DEV, data, &data_size, sense, &sense_len);
  98.     if(res)
  99.     {
  100.         perror("ioctl(SG_DXFER_FROM_DEV) error");
  101.     }
  102.     if(sense_len)
  103.     {
  104.         ;
  105.     }

  106.     /* Page Length */
  107.     pl=data[3];
  108.     int m = 0;
  109.     for(i = 4;i < (pl + 4); i++)
  110.         result[m++] = data[i] & 0xff;
  111.     serial_number->assign(result);
  112. }

  113. std::string HardDiskInfo::serial_number()
  114. {
  115.     std::string hd_serno;
  116.     device_serial_num(device_fd, &hd_serno);

  117.     return hd_serno;
  118. }

  119. void HardDiskInfo::initialize()
  120. {
  121.     int vers;
  122.     device_fd = open(device_name.c_str(), O_RDONLY);
  123.     if (device_fd == -1)
  124.     {
  125.         perror("Can not open the specified device");
  126.         exit(EXIT_FAILURE);
  127.     }
  128.     if ((ioctl(device_fd, SG_GET_VERSION_NUM, &vers) < 0) || (vers < 30000))
  129.     {
  130.         perror("The specified device is not a sg device, or old sg device");
  131.         close(device_fd);
  132.         exit(EXIT_FAILURE);
  133.     }
  134. }

上一篇:多个进程操作同一个文件的问题
下一篇:编写shell脚本服务