Primusio
07-12-2005, 22:41
Hallo Community,
ich möchte einmal ein kleines Programm vorstellen, dass vielleicht auch anderen Anfängern, so wie ich einer bin, hilfreich sein könnte.
Gleichzeitig würde ich gerne Verbesserungsvorschläge von "nicht-Anfängern" hören um es noch zu verbessern, kürzen oder übersichtlicher zu gestalten.
Programm zum Auslesen der angeschlossenen Festplatten mit deren Größe und Partitionen !
Da gerade für Anfänger der Zugriff auf Hardware und/oder Kernel-Funktionen wohl zu schwierig ist, habe ich eine andere Lösung für mein Problem gesucht.
Zum Glück stellt uns Linux im "/proc" Verzeichnis alle relevanten Daten zur Verfügung.
Mit folgendem Befehl schauen wir uns einmal die Datei "/proc/partitions" an.
% cat /proc/partitions
Bei mir erscheint folgende Tabelle
major minor #blocks name
3 0 8388608 hda
3 1 1 hda1
3 2 6434977 hda2
3 5 1953252 hda5
3 64 1048576 hdb
3 65 1 hdb1
3 69 97744 hdb5
240 0 1942016 cloop0
8 0 524288 sda
8 1 195568 sda1
8 2 1 sda2
8 5 328688 sda5
Wie man sehen kann, enthält diese Datei alle Daten die wir brauchen, die dritte Spalte gibt die Größe in kB an und die vierte den Devicenamen.
Darauf basierend habe ich folgendes Programm geschrieben.
#include <iostream> // Header für Input (cin) und Output (cout)
#include <fstream> // Header für das arbeiten mit Dateien
#include <string> // Header zum bearbeiten von strings
#include <vector> // Header zum arbeiten mit Vectoren
// Vorteil die dynamische Speicherverwaltung
using namespace std;
struct device // struct device anlegen
{ // in diesem wird das das
string deviceName; // Device als String
int deviceCapacity; // die Größe als Int
vector<string> partitions; // und die Partitionen als String Vector
}; // gespeichert.
// Vectoren sind kurz gesagt Arrays mit dynamischer Speicherverwaltung
// Hier erstellen wir im Grunde ein mehrdimensionales Array
vector<device> deviceArray;
int main (int argc, char *argv[])
{
// Da man nicht direkt in ein mehrdimensionalen Vector speichern können
// legen wir uns einmal temporär unser struct an
struct device deviceStruct;
// Datei öffnen
ifstream file("/proc/partitions");
// Dient zum speichern jeder Datei-Zeile
string line;
// Gibt den Status von unserem "deviceStruct" an
// 0 = "deviceStruct" wurde noch nicht verwendet
// 1 = "deviceStruct" wurde noch nicht an "deviceArray" übergeben
// 2 = "deviceStruct" wurde an "deviceArray" übergeben
int i = 0;
// Die Schleife wird für jede Zeile durchlaufen,
// die aktuelle Zeile wird in "line" gespeichert
while(getline(file,line))
{
// In "loc" wird festgehalten ab welchen Zeichen der Zeile, der Begriff
// "hd" vorkommt. IDE Festplatten beginnen mit "hd" und enden mit a-z
unsigned int loc = line.find( "hd", 0);
// Wenn der Begriff "hd" nicht gefunden wurde suche nach "sd"
// SCSI Festplatten beginnen immer mit "sd" und enden mit a-z
if( loc == string::npos )
loc = line.find( "sd", 0);
// Wenn eine Stelle mit "hd" oder "sd" gefunden wurde dann ...
if( loc != string::npos )
{
// "line.substr" können wir etwas aus einem String ausschneiden
// Start ist bei Zeichen Nummer "loc" und enden nach 5 Zeichen
// Sollte der ausgeschnittene String aber nur 3 Zeichen haben handelt
// es sich nicht um eine Partition sondern um eine Festplatte.
// Partitionen enden immer mit einer Nummer hätten also min. 4 Zeichen
if( line.substr( loc, 5 ).size() == 3 )
{
// Wenn "deviceStruct" schon verwendet wurde dann..
if( i != 0 )
{
// "deviceStruct" and "deviceArray" übergeben
deviceArray.push_back(deviceStruct);
// löschen der Partitionen in "deviceStruct"
deviceStruct.partitions.erase( deviceStruct.partitions.begin(), deviceStruct.partitions.end() );
// Status wird auf 2 geändert
i = 2;
}
// ermitteln an welcher Stelle die Festplattengröße beginnt
// "line.find_last_of("1234567890", loc)" sucht die erste Zahl
// in dieser Zeile beginnend ab "loc", allerdings rückwärts
// indiziert also die letzte Zahl von der Festplattengröße
// von diesem Punkt ausgehend sucht er nun wieder rückwärts, nach dem
// ersten Vorkommen von " " und addiert diesen Wert um 1
// Dies ergibt dann den index der ersten Zahl der Festplattengröße
int capacityIndex = line.find_last_of(" ", line.find_last_of("1234567890", loc)) + 1;
// Zum ausschneiden brauchen wir den Startpunkt "capacityIndex"
// Und die Anzahl der Zeichen (Zahlen) also
// line.find_last_of("1234567890", loc) = Index der letzten Zahl
// minus dem Index der ersten Zahl "capacityIndex" plus 1
int capacityNum = (line.find_last_of("1234567890", loc) - capacityIndex) + 1;
// Mit "line.substr" schneiden wir nun die Festplattengröße aus
// dann wandeln wir mit ".c_str()" denn C++ String in einen C String
// um und konvertieren ihn mit "atoi()" von einem String zu einem Int
deviceStruct.deviceCapacity =atoi( line.substr( capacityIndex, capacityNum ).c_str() );
// Nun speichern wir in "deviceStruct" den Namen des devices
// auschneiden tun wir wieder mit dem Anfangswert "loc" und der
// Anzahl der auszuschneidenden Zeichen (3)
deviceStruct.deviceName = line.substr( loc, 3 );
// Nun setzen wir noch den Status auf "in Bearbeitung"
// sodass unser Programm weiß, dass noch Daten im "deviceStruct" sind
i = 1;
// sollte der oben ausgeschnittene String länger als 3 Zeichen sein
// handelt es sich um eine Partition
} else {
// mit ".push_back()" können wir einem Vector ein neues
// Element hinzufügen, in dem Fall den Partitionsnamen
deviceStruct.partitions.push_back( line.substr( loc, 5 ) );
}
}
};
// Wenn die Datei durchgelaufen ist aber das "deviceStruct" immer noch
// "i = 1" ist z.B. wenn die letzte Zeile eine Partition war
if( i == 1 )
{
// "deviceStruct" an "deviceArray" übergeben
deviceArray.push_back(deviceStruct);
// "Partitionen in "deviceStruct" löschen"
deviceStruct.partitions.erase( deviceStruct.partitions.begin(), deviceStruct.partitions.end() );
}
return 0;
}
Dies sieht auf dem ersten Blick viel aus aber über die Hälfte sind nur kommentare zum besseren Verständnis.
Einiges wird etwas schwer verständlich geschrieben sein, da bitte ich um Nachsicht, dies ist das erste mal, dass ich was veröffentliche. ;)
Wenn jemand eine Idee hat, manche Abschnitte verständlicher zu machen, nur zu, schickt mir eure Ideen und ich werde es nachträglich editieren.
Manche funktionen wird man vielleicht erst verstehen, wenn man sich alles einmal angeschaut hat, z.B. die Status Variable "i", da sieht man erst zum Schluss für was diese gut ist.
Übrigens dieses Programm gibt noch nichts aus, da dies bei mir nur eine Funktion in einem Header ist, deswegen ist "deviceArray" auch global, um in anderen Funktionen darauf zugreifen zu können.
So kann man auf "deviceArray" zugreifen und gibt laut meiner "/proc/partitions" wie oben gesehen, dann folgendes mit aus
cout << deviceArray[0].deviceName << endl;
// hda
cout << deviceArray[1].deviceName << endl;
// hdb
cout << deviceArray[2].deviceCapacity << endl;
// 524288
cout << deviceArray[0].partitions[0] << endl;
// hda1
cout << deviceArray[0].partitions[2] << endl;
// hda5
// Für schleifen interessant
cout << deviceArray.size(); << endl;
// 3
cout << deviceArray[1].partitions.size(); << endl;
// 2
Ich hoffe ich konnte manchen von euch helfen und muss nochmal dringen dazu sagen
Ich bin Anfänger !!! :D
Also nun ran, Ideen, Meinungen, Verbesserungen ... immer her damit, ich würd mich freuen.
MfG
Primusio
ich möchte einmal ein kleines Programm vorstellen, dass vielleicht auch anderen Anfängern, so wie ich einer bin, hilfreich sein könnte.
Gleichzeitig würde ich gerne Verbesserungsvorschläge von "nicht-Anfängern" hören um es noch zu verbessern, kürzen oder übersichtlicher zu gestalten.
Programm zum Auslesen der angeschlossenen Festplatten mit deren Größe und Partitionen !
Da gerade für Anfänger der Zugriff auf Hardware und/oder Kernel-Funktionen wohl zu schwierig ist, habe ich eine andere Lösung für mein Problem gesucht.
Zum Glück stellt uns Linux im "/proc" Verzeichnis alle relevanten Daten zur Verfügung.
Mit folgendem Befehl schauen wir uns einmal die Datei "/proc/partitions" an.
% cat /proc/partitions
Bei mir erscheint folgende Tabelle
major minor #blocks name
3 0 8388608 hda
3 1 1 hda1
3 2 6434977 hda2
3 5 1953252 hda5
3 64 1048576 hdb
3 65 1 hdb1
3 69 97744 hdb5
240 0 1942016 cloop0
8 0 524288 sda
8 1 195568 sda1
8 2 1 sda2
8 5 328688 sda5
Wie man sehen kann, enthält diese Datei alle Daten die wir brauchen, die dritte Spalte gibt die Größe in kB an und die vierte den Devicenamen.
Darauf basierend habe ich folgendes Programm geschrieben.
#include <iostream> // Header für Input (cin) und Output (cout)
#include <fstream> // Header für das arbeiten mit Dateien
#include <string> // Header zum bearbeiten von strings
#include <vector> // Header zum arbeiten mit Vectoren
// Vorteil die dynamische Speicherverwaltung
using namespace std;
struct device // struct device anlegen
{ // in diesem wird das das
string deviceName; // Device als String
int deviceCapacity; // die Größe als Int
vector<string> partitions; // und die Partitionen als String Vector
}; // gespeichert.
// Vectoren sind kurz gesagt Arrays mit dynamischer Speicherverwaltung
// Hier erstellen wir im Grunde ein mehrdimensionales Array
vector<device> deviceArray;
int main (int argc, char *argv[])
{
// Da man nicht direkt in ein mehrdimensionalen Vector speichern können
// legen wir uns einmal temporär unser struct an
struct device deviceStruct;
// Datei öffnen
ifstream file("/proc/partitions");
// Dient zum speichern jeder Datei-Zeile
string line;
// Gibt den Status von unserem "deviceStruct" an
// 0 = "deviceStruct" wurde noch nicht verwendet
// 1 = "deviceStruct" wurde noch nicht an "deviceArray" übergeben
// 2 = "deviceStruct" wurde an "deviceArray" übergeben
int i = 0;
// Die Schleife wird für jede Zeile durchlaufen,
// die aktuelle Zeile wird in "line" gespeichert
while(getline(file,line))
{
// In "loc" wird festgehalten ab welchen Zeichen der Zeile, der Begriff
// "hd" vorkommt. IDE Festplatten beginnen mit "hd" und enden mit a-z
unsigned int loc = line.find( "hd", 0);
// Wenn der Begriff "hd" nicht gefunden wurde suche nach "sd"
// SCSI Festplatten beginnen immer mit "sd" und enden mit a-z
if( loc == string::npos )
loc = line.find( "sd", 0);
// Wenn eine Stelle mit "hd" oder "sd" gefunden wurde dann ...
if( loc != string::npos )
{
// "line.substr" können wir etwas aus einem String ausschneiden
// Start ist bei Zeichen Nummer "loc" und enden nach 5 Zeichen
// Sollte der ausgeschnittene String aber nur 3 Zeichen haben handelt
// es sich nicht um eine Partition sondern um eine Festplatte.
// Partitionen enden immer mit einer Nummer hätten also min. 4 Zeichen
if( line.substr( loc, 5 ).size() == 3 )
{
// Wenn "deviceStruct" schon verwendet wurde dann..
if( i != 0 )
{
// "deviceStruct" and "deviceArray" übergeben
deviceArray.push_back(deviceStruct);
// löschen der Partitionen in "deviceStruct"
deviceStruct.partitions.erase( deviceStruct.partitions.begin(), deviceStruct.partitions.end() );
// Status wird auf 2 geändert
i = 2;
}
// ermitteln an welcher Stelle die Festplattengröße beginnt
// "line.find_last_of("1234567890", loc)" sucht die erste Zahl
// in dieser Zeile beginnend ab "loc", allerdings rückwärts
// indiziert also die letzte Zahl von der Festplattengröße
// von diesem Punkt ausgehend sucht er nun wieder rückwärts, nach dem
// ersten Vorkommen von " " und addiert diesen Wert um 1
// Dies ergibt dann den index der ersten Zahl der Festplattengröße
int capacityIndex = line.find_last_of(" ", line.find_last_of("1234567890", loc)) + 1;
// Zum ausschneiden brauchen wir den Startpunkt "capacityIndex"
// Und die Anzahl der Zeichen (Zahlen) also
// line.find_last_of("1234567890", loc) = Index der letzten Zahl
// minus dem Index der ersten Zahl "capacityIndex" plus 1
int capacityNum = (line.find_last_of("1234567890", loc) - capacityIndex) + 1;
// Mit "line.substr" schneiden wir nun die Festplattengröße aus
// dann wandeln wir mit ".c_str()" denn C++ String in einen C String
// um und konvertieren ihn mit "atoi()" von einem String zu einem Int
deviceStruct.deviceCapacity =atoi( line.substr( capacityIndex, capacityNum ).c_str() );
// Nun speichern wir in "deviceStruct" den Namen des devices
// auschneiden tun wir wieder mit dem Anfangswert "loc" und der
// Anzahl der auszuschneidenden Zeichen (3)
deviceStruct.deviceName = line.substr( loc, 3 );
// Nun setzen wir noch den Status auf "in Bearbeitung"
// sodass unser Programm weiß, dass noch Daten im "deviceStruct" sind
i = 1;
// sollte der oben ausgeschnittene String länger als 3 Zeichen sein
// handelt es sich um eine Partition
} else {
// mit ".push_back()" können wir einem Vector ein neues
// Element hinzufügen, in dem Fall den Partitionsnamen
deviceStruct.partitions.push_back( line.substr( loc, 5 ) );
}
}
};
// Wenn die Datei durchgelaufen ist aber das "deviceStruct" immer noch
// "i = 1" ist z.B. wenn die letzte Zeile eine Partition war
if( i == 1 )
{
// "deviceStruct" an "deviceArray" übergeben
deviceArray.push_back(deviceStruct);
// "Partitionen in "deviceStruct" löschen"
deviceStruct.partitions.erase( deviceStruct.partitions.begin(), deviceStruct.partitions.end() );
}
return 0;
}
Dies sieht auf dem ersten Blick viel aus aber über die Hälfte sind nur kommentare zum besseren Verständnis.
Einiges wird etwas schwer verständlich geschrieben sein, da bitte ich um Nachsicht, dies ist das erste mal, dass ich was veröffentliche. ;)
Wenn jemand eine Idee hat, manche Abschnitte verständlicher zu machen, nur zu, schickt mir eure Ideen und ich werde es nachträglich editieren.
Manche funktionen wird man vielleicht erst verstehen, wenn man sich alles einmal angeschaut hat, z.B. die Status Variable "i", da sieht man erst zum Schluss für was diese gut ist.
Übrigens dieses Programm gibt noch nichts aus, da dies bei mir nur eine Funktion in einem Header ist, deswegen ist "deviceArray" auch global, um in anderen Funktionen darauf zugreifen zu können.
So kann man auf "deviceArray" zugreifen und gibt laut meiner "/proc/partitions" wie oben gesehen, dann folgendes mit aus
cout << deviceArray[0].deviceName << endl;
// hda
cout << deviceArray[1].deviceName << endl;
// hdb
cout << deviceArray[2].deviceCapacity << endl;
// 524288
cout << deviceArray[0].partitions[0] << endl;
// hda1
cout << deviceArray[0].partitions[2] << endl;
// hda5
// Für schleifen interessant
cout << deviceArray.size(); << endl;
// 3
cout << deviceArray[1].partitions.size(); << endl;
// 2
Ich hoffe ich konnte manchen von euch helfen und muss nochmal dringen dazu sagen
Ich bin Anfänger !!! :D
Also nun ran, Ideen, Meinungen, Verbesserungen ... immer her damit, ich würd mich freuen.
MfG
Primusio