2010/06/01

HDDのシリアルNoを調べる

以下で表示できる

$ hdparm -i /dev/sda


今回はどうやってシリアルNoを取得しているか調べたかったのでソースを見てみた
ちなみにソースのダウンロードはyumdownloaderを使う

# yum install yum-utils
$ yumdownloader --source hdparm


取得したRPMの展開はこうする

$ rpm2cpio hdparm-9.16-3.fc12.src.rpm | cpio -idv


で、tarが出てくるので展開してhdparm.cを覗いてみた
SerialNo=~を表示している関数は402行目のdump_identityで
その関数を呼び出しているのは1906行目だけ
すぐ上の1900行目でで呼び出されているioctl(fd, HDIO_GET_IDENTITY, id2)で取得してるらしい
__u16 *fdはopen(devname, open_flags) (1297行目)、__u16 id2[256]は空 (1898行目)
int open_flagsは多分O_RDONLY|O_NONBLOCK (141行目)
シリアルNoはid2[10]から20文字分の領域に格納されてる (408行目)

なんかif文だらけで疲れた、、
てことで、ここまでわかれば自分でも作れるかな
ちなみにWindowsではGetVolumeInformationを使うと取得できるみたい

と言う訳で作ってみた


調べてみたらhd_driveidっていう構造体が
ちゃんと用意されていたのでそっちを使う方がいいですね
gcc foo.cでコンパイルして./a.out /dev/sdaでシリアルNoを表示します


#include <stdio.h>
#include <errno.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include <sys/ioctl.h>
#include <linux/hdreg.h>

int main(int argc, char* argv[])
{
int fd, err = 0;
struct hd_driveid id;

if(argc != 2)
{
return 1;
}

fd = open(argv[1], O_RDONLY | O_NONBLOCK);
if(fd != -1)
{
if(ioctl(fd, HDIO_GET_IDENTITY, &id) != -1)
{
printf("%s\n", id.serial_no);
}
else
{
err = errno;
perror("ioctl");
}

if(close(fd) == -1)
{
err = errno;
perror("close");
}
}
else
{
err = errno;
perror(argv[1]);
}

return err;
}

0 件のコメント:

コメントを投稿