Recentemente sono stato chiesto come programmatically richiamare il numero di serie di un disco rigido usando C++ su una piattaforma di GNU/Linux. Dopo una piccola quantità di ricerca, ho scritto un breve programma dimostrativo e quello era quello o così ho pensato. Tuttavia la mia curiosità picqued ed ho deciso di esaminare come estrarre altri meta dati da un disco rigido. Per soddisfare questa curiosità ho scritto un piccolo programma di utilità che le uscite hanno selezionato i meta dati a partire dal disco rigido in un certo numero di disposizioni, cioè XML, il TESTO e CSV (virgola ha separato i valori).
Qui è l'esempio dell'uscita nel modo di TESTO:
# ./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
#
Potete domandarti che cosa questo disc è usato per. Sembra essere il disc di caricamento del sistema per la piattaforma di Fedora 13 che ho usato per scrivere a questo articolo. Usa
Qui è il XML prodotto nel modo di nuova linea per lo stesso disc:
[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]#
Qui è il XML normale prodotto per lo stesso disc:
# ./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>
#
E, per concludere, qui è l'uscita per lo stesso disc nel modo di 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] #
Ho deciso di usare le procedure dentro
Per informazioni dei fissaggi quali il numero di serie e la revisione dei firmware, è necessario da usare e ioctl per richiamare le informazioni. GNU/Linux fornisce un certo numero di ioctls e di strutture per i meta dati di scrittura e della lettura ed i disc di controllo. Questi sono dettagliati in /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 */
Gli ioctls che ho utilizzato nel programma di utilità sono HDIO_DRIVE_CMD, HDIO_GETGEO e HDIO_GET_IDENTITY. Gli ultimi due ioctls sono relativamente semplici usare. HDIO_DRIVE_CMD, sull'altro duro, è una procedura complicata come molti altri ioctls per tutti gli usi. Legga il nocciolo/documentazione/ioctl/hdio.txt per informazioni dettagliate ed esamini il codice in driver/ido/ide.c ed in driver/blocco/scsi_ioctl.c per i dispositivi d'avviamento ed esamini le varie specifiche di interfaccia pubblicate del disco rigido. Completamente sono d'accordo con l'avvertimento nella sezione sullo ioctl di HDIO_DRIVE_CMD, quello “se non avete una copia della specifica ATA dell'ANSI pratica, voi dovrei probabilmente ignorare questo ioctl.„
Qui sono gli input e le uscite per 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.
Quando un azionamento è trasmesso all'ordine di IDENTIFY_DRIVE (0xEC), restituisce 256 parole (512 byte) di informazioni. Le parole sono numerate 0-255. La parola 255 è il totale di controllo e la firma (0xA5). Per le stringhe di ASCII ogni parola contiene due caratteri, il byte di ordine alto il primo, il byte di ordine ridotto il secondo. Per i valori a 32 bits la parola di ordine ridotto è prima. Ecco perché ho usato la procedura del nocciolo __le16_to_cpus () allo scambio di byte le parole.
Esamini la procedura di get_diskinfo () per un esempio di funzionamento di HDIO_DRIVE_CMD, principale () per HDIO_GET_IDENTITY e get_geometry () per HDIO_GETGEO. Si noti che
Qui è il codice sorgente per il programma di utilità:
/*
* 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);
}
Per compilare questo codice, dovete includere libparted. Se libparted non è disponibile sulla vostra piattaforma, non caricano programmi oggetto il codice sorgente per il programma di utilità separato
Ritenga prego libero di usare il codice sorgente incluso in questo alberino per che cosa scopo volete usarli per - fornito voi comprenda il testo dell'autorizzazione. Se lo usate sulle piattaforme che contengono PATA, azionamenti di SCSI o di SRS dovrete ovviamente che estendere il codice per comprendere quei tipi di azionamento ma quello non è difficile da fare con le giuste informazioni. Uno di migliori posti per trovare questa specie di informazioni è nei vari campioni e nei gruppi di lavoro di INCITS (comitato internazionale per i campioni di tecnologia dell'informazione). Per esempio, il comitato tecnico T10 di INCITS è un buon posto da imparare circa le interfacce di immagazzinaggio di SCSI.
Goda di!






















Articolo interessante. Grazie.
[...] Questo qualcosa che scriva qualche tempo fa per un blog. Dovrebbe aiutarlo a richiamare quelle informazioni e più da un disco rigido:http://blog.fpmurphy.com/2010/05/har… - metadata.html [...]
I sostegni di Linux non dovrebbero dovere essere un lavoretto. Un cron di sostegno rispettabile andrà per sempre.