LinuxでDiskの情報を取得する

久しぶりに日記の更新です。


前回Windows系の情報収集等のプログラミングをやって来ていたんですが、先週はLinux系の情報収集に翻弄されていました。
その第一弾はDisk情報の取得で、WindowsだとWMIを使って比較的簡単に取得できたんですが、Linuxの方は取得するのに苦労してしまいました。


次のプログラムは、/proc/partitions情報からLinuxが認識している区画情報を取得して、その区画情報を元にDisk情報の入っているsuper_blockを探し出して取得する手順を撮って取っています。
Diskの情報としては、ext2以外にext3、FAT、NTFSなどがありますが、今回はext2(JDB,ext3ext2として)の情報を取得することだけを念頭においてプログラミングしています。

#include <uuid/uuid.h>
#include <linux/ext2_fs.h>
#include <fcntl.h>
#define _SUPERBLOCK_BUFF_SIZE   65536

char uuid_buf[64];
char line[1024];
char devid[128];
char devname[128];
unsigned char *io_buf = (unsigned char *)malloc(_SUPERBLOCK_BUFF_SIZE);
int ma, mi;

FILE *proc = fopen("/proc/partitions", "r");
unsigned long long sz;
if (proc != 0) {
    while (fgets(line, sizeof(line), proc)) {
        if (sscanf(line, " %d %d %llu %127[^\n ]", &ma, &mi, &sz, devid) == 4) {
            if (sz <= 1)
                continue;
            if (!isdigit(devid[strlen(devid)-1]))
                continue;
            sprintf(devname, "/dev/%s", devid);
            int fd = open(devname, O_RDONLY | O_NONBLOCK);
            if (fd) {
                unsigned loc = lseek(fd, 0, SEEK_SET);
                if (loc >= 0) {
                    read(fd, io_buf, _SUPERBLOCK_BUFF_SIZE);
                    size_t off = 0;
                    while (off+sizeof(ext2_super_block) < _SUPERBLOCK_BUFF_SIZE) {
                        ext2_super_block *sb = (ext2_super_block*)&io_buf[off];
                        if (sb->s_magic == EXT2_SUPER_MAGIC) {
                            memset(uuid_buf, 0, 64);
                            uuid_unparse(sb->s_uuid, uuid_buf);
                            printf("Device %s : LABEL=%s : %s", devname, sb->s_volume_name, uuid_buf);
                            if (strncmp(devid, "md", 2) == 0) {
                                printf(" : DriveRaidDisk.\n");
                            }
                            else {
                                printf(" : DriveLocalDisk.\n");
                            }
                            break;
                        }
                        off += 1024;
                    }
                }
                close(fd);
            }
        }
    }
    fclose(proc);
}