最近私はprogrammatically GNU/LinuxのプラットホームのC++を使用してハードディスクの通し番号を取り出す方法を尋ねられた。 わずかの後で研究、私は短いデモンストレーションプログラムを書き、それはそれだったまたはそう私は考えた。 但し私の興味はpicqued、ハードディスクから他のメタデータを得る方法を私は見ることにした。 この興味を満たすためには私は出力がいくつかのフォーマットのハードディスク、すなわちXML、テキストおよびCSV (コンマは価値を分けた)からメタデータを選んだ小さい実用性を書いた。
テキストモードの出力の例はここにある:
# ./hdm /dev/sda
DEVICE: /dev/sda
----------------
Manufacturer Model: Hitachi HDP725050GLA360
Serial Number: GEA534RF1MUN5A
Firmware Revision: GM4OA52A
Transport Type: SATA Rev 2.6
Maximum RPM: 7200
Capacity: 500GB
Number Cylinders: 60801
Partition Type: gpt
No. Start End Size Type Filesystem Name Flags
01 17.9kB 210MB 210MB primary fat16 boot
02 210MB 419MB 210MB primary ext4
03 419MB 500GB 500GB primary lvm
#
このディスクが使用されるものをのために疑問に思うかもしれない。 それは私がこの記事に書くのが常であったソフト帽13のプラットホームのための起動ディスクであることを起こる。 それは機構を 仕切る 共通MBRよりもむしろGPT (GUIDの仕切りの テーブル )を使用する。 私は 従来の BIOS および 遺産の地虫の代りにオペレーティングシステムを追い出すのにEFIおよびGRUB2を-のためのそれ故にFAT16仕切り特別に使用する(EFIのシステム分割)。 傍白として、私はかなりより速いブーツの時間のためにこのarrangmentを好む。 ソフト帽13のinitrdおよび穀粒のイメージおよび関連ファイルは第2仕切りにあり、第3仕切りはいくつかのファイルシステムに裂ける論理的な容積である。 上記の出力をよく見れば、hdparmsのような実用性からの出力かgdiskのようなlshwおよび仕切り実用性両方含んでいるか、または分けたことを見る。
同じディスクのための改行モードで出力されるXMLはここにある:
[root@ultra hdparm]# ./hdm -x /dev/sda <disk dev="/dev/sda"><model>Hitachi HDP725050GLA360</model><serialno>GEA534RF1MUN5A</serialno><firmware>GM4OA52A</firmware><transport>SATA Rev 2.6</transport><rpm>7200</rpm><capacity>500GB</capacity><geometry><cylinders>60801</cylinders><heads>255</heads><sectors>63</sectors></geometry><partitiontype>gpt<paritiontype><partitions><partition number="1"><start>17.9kB</start><end>210MB</end><size>210MB</size><type>primary</type><filesystem>fat16</filesystem><label></label><flags>boot</flags></partition><partition number="2"><start>210MB</start><end>419MB</end><size>210MB</size><type>primary</type><filesystem>ext4</filesystem><label></label><flags></flags></partition><partition number="3"><start>419MB</start><end>500GB</end><size>500GB</size><type>primary</type><filesystem></filesystem><label></label><flags>lvm</flags></partition></partitions></disk>[root@ultra hdparm]#
同じディスクのために出力される規則的なXMLはここにある:
# ./hdm -x -n /dev/sda
<disk dev="/dev/sda">
<model>Hitachi HDP725050GLA360</model>
<serialno>GEA534RF1MUN5A</serialno>
<firmware>GM4OA52A</firmware>
<transport>SATA Rev 2.6</transport>
<rpm>7200</rpm>
<capacity>500GB</capacity>
<geometry>
<cylinders>60801</cylinders>
<heads>255</heads>
<sectors>63</sectors>
</geometry>
<partitiontype>gpt<paritiontype>
<partitions>
<partition number="1">
<start>17.9kB</start>
<end>210MB</end>
<size>210MB</size>
<type>primary</type>
<filesystem>fat16</filesystem>
<label></label>
<flags>boot</flags>
</partition>
<partition number="2">
<start>210MB</start>
<end>419MB</end>
<size>210MB</size>
<type>primary</type>
<filesystem>ext4</filesystem>
<label></label>
<flags></flags>
</partition>
<partition number="3">
<start>419MB</start>
<end>500GB</end>
<size>500GB</size>
<type>primary</type>
<filesystem></filesystem>
<label></label>
<flags>lvm</flags>
</partition>
</partitions>
</disk>
#
そして、CSVモードの同じディスクのための出力はここに最終的にある:
# ./hdm -c /dev/sda "Hitachi HDP725050GLA360","GEA534RF1MUN5A","GM4OA52A","SATA Rev 2.6","7200","500GB","60801","255","63"","gpt","01","17.9kB","210MB","210MB","primary","fat16","","boot","02","210MB","419MB","210MB","primary","ext4","","","03","419MB","500GB","500GB","primary","","","lvm"[root@ultra hdparm] #
私は仕切り情報を取り出し 、 処理するためにlibpartedルーチンを使用することにした。 これらのルーチンはすべてped_から始まり、dump_partition ()ルーチンの内で含まれている。 従って(ASCIIのひもを含んでいる)へのped_ルーチン帰りのポインターの多数割振られた記憶使用の後でこのスペースを自由に使えるようにする必要があり。
通し番号およびファームウェア修正のようなハードウェア情報のために、使用することは必要および情報を取り出すioctlである。 GNU/Linuxは読書および執筆メタデータおよび制御ディスクにいくつかのioctlsおよび構造提供する。 これらは/usr/include/linux/hdreg.hで詳しく述べられる。
#define HDIO_GETGEO 0x0301 /* get device geometry */ #define HDIO_GET_UNMASKINTR 0x0302 /* get current unmask setting */ #define HDIO_GET_MULTCOUNT 0x0304 /* get current IDE blockmode setting */ #define HDIO_GET_QDMA 0x0305 /* get use-qdma flag */ #define HDIO_SET_XFER 0x0306 /* set transfer rate via proc */ #define HDIO_OBSOLETE_IDENTITY 0x0307 /* OBSOLETE, DO NOT USE: returns 142 bytes */ #define HDIO_GET_KEEPSETTINGS 0x0308 /* get keep-settings-on-reset flag */ #define HDIO_GET_32BIT 0x0309 /* get current io_32bit setting */ #define HDIO_GET_NOWERR 0x030a /* get ignore-write-error flag */ #define HDIO_GET_DMA 0x030b /* get use-dma flag */ #define HDIO_GET_NICE 0x030c /* get nice flags */ #define HDIO_GET_IDENTITY 0x030d /* get IDE identification info */ #define HDIO_GET_WCACHE 0x030e /* get write cache mode on|off */ #define HDIO_GET_ACOUSTIC 0x030f /* get acoustic value */ #define HDIO_GET_ADDRESS 0x0310 /* */ #define HDIO_GET_BUSSTATE 0x031a /* get the bus state of the hwif */ #define HDIO_TRISTATE_HWIF 0x031b /* execute a channel tristate */ #define HDIO_DRIVE_RESET 0x031c /* execute a device reset */ #define HDIO_DRIVE_TASKFILE 0x031d /* execute raw taskfile */ #define HDIO_DRIVE_TASK 0x031e /* execute task and special drive command */ #define HDIO_DRIVE_CMD 0x031f /* execute a special drive command */ #define HDIO_DRIVE_CMD_AEB HDIO_DRIVE_TASK /* hd/ide ctl's that pass (arg) non-ptr values are numbered 0x032n/0x033n */ #define HDIO_SET_MULTCOUNT 0x0321 /* change IDE blockmode */ #define HDIO_SET_UNMASKINTR 0x0322 /* permit other irqs during I/O */ #define HDIO_SET_KEEPSETTINGS 0x0323 /* keep ioctl settings on reset */ #define HDIO_SET_32BIT 0x0324 /* change io_32bit flags */ #define HDIO_SET_NOWERR 0x0325 /* change ignore-write-error flag */ #define HDIO_SET_DMA 0x0326 /* change use-dma flag */ #define HDIO_SET_PIO_MODE 0x0327 /* reconfig interface to new speed */ #define HDIO_SCAN_HWIF 0x0328 /* register and (re)scan interface */ #define HDIO_UNREGISTER_HWIF 0x032a /* unregister interface */ #define HDIO_SET_NICE 0x0329 /* set nice flags */ #define HDIO_SET_WCACHE 0x032b /* change write cache enable-disable */ #define HDIO_SET_ACOUSTIC 0x032c /* change acoustic behavior */ #define HDIO_SET_BUSSTATE 0x032d /* set the bus state of the hwif */ #define HDIO_SET_QDMA 0x032e /* change use-qdma flag */ #define HDIO_SET_ADDRESS 0x032f /* change lba addressing modes */
私が実用性で使用したioctlsはHDIO_DRIVE_CMD、HDIO_GETGEOおよびHDIO_GET_IDENTITYである。 最後の2つのioctlsは使用し比較的やすい。 HDIO_DRIVE_CMDは、他の堅いので、他の多くの一般目的のioctlsのような複雑なルーチンである。 詳細情報のための穀粒かドキュメンテーションまたはioctl/hdio.txt読み、運転者のコードをかideまたはide.cおよび運転者検査しか、またはまたはscsi_ioctl.cまず最初に妨げか、そしてさまざまな出版されたハードディスクのインターフェイス指定を見なさい。 私はHDIO_DRIVE_CMDのioctl、それにセクションの警告と十分に便利なANSIのATA指定のコピーを持たなければ同意する「おそらくこのioctlを無視するべきである」。
HDIO_DRIVE_CMDのための入出力はここにある:
__u8[4+512}
ioctl(fd, HDIO_DRIVE_CMD, args);
INPUTS:
args[0] COMMAND
args[1] NSECTOR
args[2] FEATURE
args[3] NSECTOR
OUTPUTS:
args[0] status
args[1] error
args[2] NSECTOR
args[3] undefined
args[4+] NSECTOR * 512 bytes of data returned by the command.
ドライブはIDENTIFY_DRIVE (0xEC)命令に送られるとき、情報の256ワード(512バイト)を戻す。 単語は0-255番号が付いている。 単語255は検査合計および署名(0xA5)である。 ASCIIのひものために各単語は2つの特性、高位バイトを第1、下位バイト第2含んでいる。 32ビット価値のために最低位単語は第1である。 そういうわけで私はバイトの交換に穀粒__le16_to_cpus ()ルーチンを単語使用した。
HDIO_GET_IDENTITYを主要なHDIO_DRIVE_CMDの実施例をget_diskinfo ()ルーチンを() HDIO_GETGEOをget_geometry ()見れば。 HDIO_GETGEOによって戻る CHS (シリンダーヘッドのセクター)の価値が正確かもしれないしまたはそうではないかもしれないことに注目しなさい。 それはまたハードディスクの仕切りの相殺される開始のセクターのための2TB限界を有する。 よりよい方法は巧妙なHDIO_DRIVE_CMD IDENTIFY_DRIVE 命令 の後でLBA48 (単語100-103)で、戻る最大キャパシティ戻る単語でデフォルトLBA (演説する論理ブロック)容量の価値57-58か単語で60-61、またはよりよいまだ戻る現在のLBA容量の価値を使用することである。 現在のアドレッシング・モードを把握するのにHDIO_GET_ADDRESSを使用できる。 私はget_capacity ()ルーチンで容量を定める2つの方法を示す。
実用性のためのソースコードはここにある:
/*
* hdm.c - Hard Disk Metadata
*
* Copyright (C) Finnbarr P. Murphy 2010 <fpm[AT]fpmurphy.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License Version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <linux/fs.h>
#include <asm/byteorder.h>
#include <sys/ioctl.h>
#include <linux/hdreg.h>
#include <parted/parted.h>
#define DUMPXML 1
#define DUMPTXT 2
#define DUMPCSV 3
#define NONEWLINE 0
#define DI_VERSION "1.0"
#define TRANSPORT_MAJOR 0xDE
#define TRANSPORT_MINOR 0xDF
#define ATA_PIDENTIFY 0xA1
#define ATA_IDENTIFY 0xEC
#define NMRR 0xD9
#define CAPAB 0x31
#define CMDS_SUPP_1 0x53
#define VALID 0xC000
#define VALID_VAL 0x4000
#define SUPPORT_48_BIT 0x0400
#define LBA_SUP 0x0200
#define LBA_LSB 0x64
#define LBA_MID 0x65
#define LBA_48_MSB 0x66
#define LBA_64_MSB 0x67
/* yes - these are shortcuts! */
static __u16 *id = (void *)NULL;
static struct hd_geometry *g;
static int fd = 0;
struct hd_geometry *
get_geometry(int fd)
{
static struct hd_geometry geometry;
if (ioctl(fd, HDIO_GETGEO, &geometry)) {
perror("ERROR: HDIO_GETGEO failed");
}
return &geometry;
}
void *
get_diskinfo(int fd)
{
static __u8 args[4+512];
__u16 *id = (void *)(args + 4);
int i;
memset(args, 0, sizeof(args));
args[0] = ATA_IDENTIFY;
args[3] = 1;
if (ioctl(fd, HDIO_DRIVE_CMD, args)) {
args[0] = ATA_PIDENTIFY;
args[1] = 0;
args[2] = 0;
args[3] = 1;
if (ioctl(fd, HDIO_DRIVE_CMD, args)) {
perror("ERROR: HDIO_DRIVE_CMD failed");
return "";
}
}
/* byte-swap data to match host endianness */
for (i = 0; i < 0x100; ++i)
__le16_to_cpus(&id[i]);
return id;
}
//
// Routine currently only handles SATA drives. Extra code needs to be added to support PATA, SCSI, USB, etc.
//
char *
get_transport(__u16 id[])
{
__u16 major, minor;
unsigned int ttype, stype;
major = id[TRANSPORT_MAJOR];
minor = id[TRANSPORT_MINOR];
if (major == 0x0000 || major == 0xffff)
return "";
ttype = major >> 12; /* transport type */
stype = major & 0xfff; /* subtype */
if (ttype == 1) {
if (stype & 0x2f) {
if (stype & (1<<5))
return "SATA Rev 3.0";
else if (stype & (1<<4))
return "SATA Rev 2.6";
else if (stype & (1<<3))
return "SATA Rev 2.5";
else if (stype & (1<<2))
return "SATA II Extensions";
else if (stype & (1<<1))
return "SATA 1.0a";
}
}
}
char *
get_rpm(__u16 id[])
{
static char str[6];
__u16 i = id[NMRR];
sprintf(str,"%u", i);
return str;
}
char *
ascii_string(__u16 *p,
unsigned int len)
{
__u8 i, c;
char cl;
static char str[60];
char *s = str;
memset(&str, 0, sizeof(str));
/* find first character */
for (i = 0; i < len; i++) {
if (( (char)0x00ff & ((*p) >> 8)) != ' ')
break;
if ((cl = (char) 0x00ff & (*p)) != ' ') {
if (cl != '\0') *s++ = cl;
p++; i++;
break;
}
p++;
}
/* copy from here to end */
for (; i < len; i++) {
c = (*p) >> 8;
if (c) *s++ = c;
c = (*p);
if (c) *s++ = c;
p++;
}
/* remove trailing blanks */
s = str;
while(*s) s++;
while(*--s == ' ') *s= 0;
return str;
}
#define USE_CAPAB
char *
get_capacity(int fd, __u16 id[])
{
unsigned int sector_bytes = 512;
static char str[20];
__u64 sectors = 0;
#ifdef USE_CAPAB
memset(&str, 0, sizeof(str));
if (id[CAPAB] & LBA_SUP) {
if (((id[CMDS_SUPP_1] & VALID) == VALID_VAL) && (id[CMDS_SUPP_1] & SUPPORT_48_BIT) ) {
sectors = (__u64)id[LBA_64_MSB] << 48 | (__u64)id[LBA_48_MSB] << 32 |
(__u64)id[LBA_MID] << 16 | id[LBA_LSB] ;
}
}
#else
unsigned int sector32 = 0;
if (!(ioctl(fd, BLKGETSIZE64, §ors))) { // bytes
sectors /= sector_bytes;
} else if (!(ioctl(fd, BLKGETSIZE, §or32))) { // sectors
sectors = sector32;
} else
return "";
#endif
sectors *= (sector_bytes /512);
sectors = (sectors << 9)/1000000;
if (sectors > 1000)
sprintf(str, "%lluGB", (unsigned long long) sectors/1000);
else
sprintf(str, "%lluMB", (unsigned long long) sectors);
return str;
}
void
dump_partitions(char *device, int dumpmode, int nlmode)
{
PedDevice *dev = (PedDevice *)NULL;
PedDiskType* type;
PedDisk* disk = (PedDisk *)NULL;
PedPartition* part;
PedPartitionFlag flag;
PedUnit default_unit;
int has_free_arg = 0;
char *start;
char *end;
char *size;
char flags[100];
const char *partname;
const char *parttype;
const char *partlabel;
const char *partflags;
int first_flag;
dev = ped_device_get(device);
if (!ped_device_open (dev)) {
fprintf(stderr, "ERROR: ped-device-opem\n");
exit(1);
}
disk = ped_disk_new(dev);
if (!disk) {
fprintf(stderr, "ERROR: ped-disk-new\n");
exit(1);
}
start = ped_unit_format(dev, 0);
default_unit = ped_unit_get_default();
end = ped_unit_format_byte (dev, dev->length * dev->sector_size
- (default_unit == PED_UNIT_CHS || default_unit == PED_UNIT_CYLINDER));
switch (dumpmode) {
case DUMPXML:
if (nlmode) printf("\n ");
printf("<partitiontype>%s<paritiontype>", disk->type->name);
if (nlmode) printf("\n ");
printf("<partitions>");
break;
case DUMPTXT:
printf(" Partition Type: %s\n", disk->type->name);
printf(" No. Start End Size Type Filesystem Name Flags\n");
break;
case DUMPCSV:
putchar('"'); putchar(','); putchar('"');
printf("%s", disk->type->name );
break;
}
free(start);
free(end);
for (part = ped_disk_next_partition (disk, NULL); part;
part = ped_disk_next_partition (disk, part)) {
if ((!has_free_arg && !ped_partition_is_active(part)) ||
part->type & PED_PARTITION_METADATA)
continue;
start = ped_unit_format (dev, part->geom.start);
end = ped_unit_format_byte (dev, (part->geom.end + 1) * (dev)->sector_size - 1);
size = ped_unit_format (dev, part->geom.length);
if (!(part->type & PED_PARTITION_FREESPACE)) {
parttype = ped_partition_type_get_name (part->type);
partlabel = ped_partition_get_name(part);
} else {
parttype = "";
partlabel = "";
}
// flags
memset(&flags, 0, sizeof(flags));
first_flag = 1;
for (flag = ped_partition_flag_next(0); flag;
flag = ped_partition_flag_next(flag)) {
if (ped_partition_get_flag(part, flag)) {
if (first_flag) {
first_flag = 0;
} else {
strcat (flags, ", ");
}
partflags = ped_partition_flag_get_name(flag);
strcat(flags, partflags);
}
}
switch (dumpmode) {
case DUMPXML:
if (nlmode) printf("\n ");
if (part->num >= 0)
printf("<partition number=\"%d\">", part->num);
else
printf("<partition number=\"0\">");
if (nlmode) printf("\n ");
printf("<start>%s</start>", start);
if (nlmode) printf("\n ");
printf("<end>%s</end>", end);
if (nlmode) printf("\n ");
printf("<size>%s</size>", size);
if (nlmode) printf("\n ");
printf("<type>%s</type>", parttype);
if (nlmode) printf("\n ");
printf("<filesystem>%s</filesystem>", part->fs_type ? part->fs_type->name : "");
if (nlmode) printf("\n ");
printf("<label>%s</label>", partlabel);
if (nlmode) printf("\n ");
printf("<flags>%s</flags>", flags);
if (nlmode) printf("\n ");
printf("</partition>");
break;
case DUMPTXT:
if (part->num >= 0)
printf(" %02d", part->num);
else
printf(" ");
printf(" %6s %6s %6s %10s", start, end, size, parttype);
printf(" %6s", part->fs_type ? part->fs_type->name : "");
printf(" %10s %s\n", partlabel, flags);
break;
case DUMPCSV:
putchar('"'); putchar(','); putchar('"');
if (part->num >= 0) printf("%02d", part->num);
putchar('"'); putchar(','); putchar('"');
printf("%s", start);
putchar('"'); putchar(','); putchar('"');
printf("%s", end);
putchar('"'); putchar(','); putchar('"');
printf("%s", size);
putchar('"'); putchar(','); putchar('"');
printf("%s", parttype);
putchar('"'); putchar(','); putchar('"');
if (part->fs_type) printf("%s", part->fs_type->name);
putchar('"'); putchar(','); putchar('"');
printf("%s", partlabel);
putchar('"'); putchar(','); putchar('"');
printf("%s", flags);
break;
}
free(start);
free(end);
free(size);
}
switch (dumpmode) {
case DUMPXML:
if (nlmode) printf("\n ");
printf("</partitions>");
break;
case DUMPTXT:
break;
case DUMPCSV:
putchar('"');
break;
}
}
void
dump(char *device)
{
int len = strlen(device) + 8;
int i = 0;
printf("\nDEVICE: %s\n", device);
while(i++ < len) putchar('-');
putchar('\n');
printf("Manufacturer Model: %s\n", ascii_string(&id[27],20));
printf(" Serial Number: %s\n", ascii_string(&id[10],10));
printf(" Firmware Revision: %s\n", ascii_string(&id[23],4));
printf(" Transport Type: %s\n", get_transport(id));
printf(" Maximum RPM: %s\n", get_rpm(id));
printf(" Capacity: %s\n", get_capacity(fd, id));
printf(" Number Cylinders: %u\n", g->cylinders);
dump_partitions(device, DUMPTXT, NONEWLINE);
}
void
dumpxml(char *device, int nlmode)
{
printf("<disk dev=\"%s\">", device);
if (nlmode) printf("\n ");
printf("<model>%s</model>", ascii_string(&id[27],20));
if (nlmode) printf("\n ");
printf("<serialno>%s</serialno>", ascii_string(&id[10],10));
if (nlmode) printf("\n ");
printf("<firmware>%s</firmware>", ascii_string(&id[23],4));
if (nlmode) printf("\n ");
printf("<transport>%s</transport>", get_transport(id));
if (nlmode) printf("\n ");
printf("<rpm>%s</rpm>", get_rpm(id));
if (nlmode) printf("\n ");
printf("<capacity>%s</capacity>", get_capacity(fd, id));
if (nlmode) printf("\n ");
printf("<geometry>");
if (nlmode) printf("\n ");
printf("<cylinders>%u</cylinders>", (unsigned short) g->cylinders);
if (nlmode) printf("\n ");
printf("<heads>%u</heads>", (unsigned char) g->heads);
if (nlmode) printf("\n ");
printf("<sectors>%u</sectors>", (unsigned char) g->sectors);
if (nlmode) printf("\n ");
printf("</geometry>");
dump_partitions(device, DUMPXML, nlmode);
if (nlmode) putchar('\n');
printf("</disk>");
if (nlmode) putchar('\n');
}
void
dumpcsv(char *device)
{
putchar('"');
printf("%s", ascii_string(&id[27],20));
putchar('"'); putchar(','); putchar('"');
printf("%s", ascii_string(&id[10],10));
putchar('"'); putchar(','); putchar('"');
printf("%s", ascii_string(&id[23],4));
putchar('"'); putchar(','); putchar('"');
printf("%s", get_transport(id));
putchar('"'); putchar(','); putchar('"');
printf("%s", get_rpm(id));
putchar('"'); putchar(','); putchar('"');
printf("%s", get_capacity(fd, id));
putchar('"'); putchar(','); putchar('"');
printf("%u", g->cylinders);
putchar('"'); putchar(','); putchar('"');
printf("%u", g->heads);
putchar('"'); putchar(','); putchar('"');
printf("%u", g->sectors);
putchar('"');
dump_partitions(device, DUMPCSV, NONEWLINE);
}
void
usage()
{
printf("usage: di [-n] [-c|-csv|-x|--xml] devicepath\n");
printf("usage: di [-v |--version ]\n");
}
int
main(int argc,
char *argv[])
{
static struct hd_driveid hd;
int option_index = 0, c;
int xmlmode = 0, nlmode = 0, csvmode = 0;
char *device;
static struct option long_options[] = {
{"csv", no_argument, 0, 'c'},
{"help", no_argument, 0, 'h'},
{"newline", no_argument, 0, 'n'},
{"version", no_argument, 0, 'v'},
{"xml", no_argument, 0, 'x'},
{0, 0, 0, 0}
};
while ((c = getopt_long(argc, argv, "chnvx", long_options, &option_index)) != -1) {
switch (c) {
case 'h':
usage();
exit(EXIT_SUCCESS);
case 'c':
csvmode = 1;
break;
case 'n':
nlmode = 1;
break;
case 'x':
xmlmode = 1;
break;
case 'v':
fprintf(stdout, "version %s\n", DI_VERSION);
exit(EXIT_SUCCESS);
default: /* '?' */
usage();
exit(EXIT_FAILURE);
}
}
if (csvmode && xmlmode) {
fprintf(stderr, "ERROR: Select either XML or CVS for formatted output\n");
exit(EXIT_FAILURE);
}
if (optind >= argc) {
fprintf(stderr, "ERROR: No devicepath provided\n");
exit(EXIT_FAILURE);
}
if (geteuid() > 0) {
fprintf(stderr, "ERROR: Must be root to use\n");
exit(EXIT_FAILURE);
}
device = argv[optind];
if ((fd = open(device, O_RDONLY|O_NONBLOCK)) < 0) {
fprintf(stderr, "ERROR: Cannot open device %s\n", argv[1]);
exit(EXIT_FAILURE);
}
id = get_diskinfo(fd);
g = get_geometry(fd);
if (ioctl(fd, HDIO_GET_IDENTITY, &hd) < 0 ) {
if (errno == -ENOMSG) {
fprintf(stderr, "ERROR: No hard disk identification information available\n");
} else {
perror("ERROR: HDIO_GET_IDENTITY");
exit(1);
}
}
close(fd);
if (csvmode)
dumpcsv(device);
else if (xmlmode)
dumpxml(device, nlmode);
else
dump(device);
exit(EXIT_SUCCESS);
}
このコードを編集するためには、libparted含む必要がある。 libpartedあなたのプラットホームで利用できないがないし、GNUのプロジェクトからの分けられた実用性のための ソースコードをダウンロードしないし、 そして造らない。
どんな目的のためにそれを使用したいと思うこのポストに含まれているソースコードをのために使用すること自由に感じなさい-提供される免許証のテキストを含みなさい。 PATAを含んでいるプラットホームのそれを使用すれば、SASまたはSCSIドライブ明らかにそれらのドライブの種類を含むためにあなたがコードを拡張する必要があるが、それは右の情報としにくくない。 この種類の情報をさまざまなINCITS (情報技術の標準のための国際的な委員会)の 標準およびワーキング・グループに見つける最もよい場所の1つはある。 例えば、INCITSの 技術委員会T10は SCSI貯蔵インターフェイスについて学ぶべき適切な場所である。
楽しみなさい!



























興味深い記事。 ありがとう。
[...]私がしばらく前にブログのために書いたこの何か。 それはハードディスクからその情報および多くを取り出すのを助けるべきである: http://blog.fpmurphy.com/2010/05/har… - metadata.html [...]
Linuxバックアップは雑用でなければならないべきである。 適当なバックアップcronは永久に行く。