翻訳しなさい

Translate to EnglishÜbersetzen Sie zum Deutsch/GermanΜεταφράστε στα ελληνικά/GreekПереведите к русскому/RussianOversetter til Norsk/NorwegianÖversätta till Svensk/Swedishहिन्दी अनुवाद करने के लिए/Hindi
Tradueix al català/CatalanTulkot uz latviešu/LatvianPreložiť do slovenčiny/SlovakVertaal aan het Nederlands/Dutchترجمة الى العربية/ArabicTraduzca al Español/SpanishTraduisez au Français/French
Traduca ad Italiano/ItalianTraduza ao Português/Portuguese日本語に翻訳しなさい /Japanese한국어에게 번역하십시오/Korean中文翻译/Chinese Simplified中文翻译/Chinese TraditionalПереклад на українську/Ukrainian
Linuxの穀粒の開発(第3版)のイメージ
人間の特徴をもつ無線アプリケーション開発のイメージ
現代オペレーティングシステム(第3版)のイメージ
オペレーティングシステムの概念のイメージ

ハードディスクのメタデータ

最近私は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, &sectors))) {            // bytes
          sectors /= sector_bytes;
    } else if (!(ioctl(fd, BLKGETSIZE, &sector32))) {      // 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貯蔵インターフェイスについて学ぶべき適切な場所である。

楽しみなさい!
 

ハードディスクのメタデータへの3つのコメント