[C] low-level | Cluster einer Datei lokalisieren

Cyberm@ster

New member
Hi, ich könnte einen kleinen Anschub gebrauchen.

Im Rahmen eines Projekts für die Uni möchte ich in C ein Programm realisieren, das es ermöglicht alle zu einer Datei gehörenden Cluster auf der Festplatte zu lokalisieren (Adressen) und deren Inhalt anzeigen. Ich möchte das Programm vorzugsweise für Windows (XP) und das FAT32-Filesystem entwickeln, da die Professoren ausschliesslich mit Windows arbeiten und mir NTFS im Vergleich zu FAT32 zu komplex scheint. Ich bin aber flexibel (Ubuntu und Ext3 geht auch).

Ich habe habe versucht mich schlau zu machen, bin aber nicht wirklich weiter gekommen, da ich nicht so richtig weiss wonach ich suchen soll. Ich habe mir unter anderem den Code aus dem aktuellen Linux-Kernel (/fs/FAT) und von Foremost 1.5.3 angeschaut bin aufgrund mangelnder Dokumentation nicht wirklich schlau daraus geworden. Ich würde mich über Anregungen freuen (.h Bibliotheken, Funktionen, Stichwörter...)

Ich weiss, dass es keine leichte Aufgabe ist, aber ich habe 2 Jahre Erfahrung in Delphi, ein Semester in C und bin lernwillig. (Ich möchte auch nicht, dass jemand das Programm an meiner Stelle macht, ich will es wirklich selber erstellen und mich mit der Materie auseinandersetzen). Daher tut das Ganze bitte nicht mit einem "Wenn du nicht weisst wo du suchen musst, wirst du es eh nicht schaffen" ab.

Danke im Voraus für eure Antworten.
 

lorelei

New member
Ich hab auch eine Idee dazu: Ich verwende einen Freeware-HEX-Editor, der Dateien direkt auf der Platte öffnen kann: HxD

http://www.mh-nexus.de

Unter dem Punkt: "Extras-Datenträgerabbild öffnen" wird ein File direkt auf der Platte geöffnet - der Entwickler (deutschsprechend) scheint sehr auskunftbereit zu sein - vielleicht kann er dir irgendwie weiterhelfen - das Ergebnis würde mich auch interessieren.
 

Cyberm@ster

New member
Danke für den Tipp! Ich habe ihm soeben gemailt, mal schauen was dabei rauskommt. Danke auch an BasicAvid für die Links!

Edit:

Hier die Antwort:

Direkter Zugriff auf Festplatten wird je nach Betriebssystem verschieden realisiert. Für Win9X wird das BIOS verwendet (Interrupt 13, etc.) und unter Linux gibt es eine Art virtuelle Datei pro Laufwerk (wie das genau funktioniert weiß ich aber nicht).

Was Windows NT/2000/XP angeht geht dies relativ einfach mit den Win32-API Funktionen CreateFile/ReadFile/WriteFile.

Suchen Sie in der MSDN-Hilfe zu CreateFile nach "\\.\PhysicalDrive0" bzw. "Physical Disks and Volumes". Dort wird erklärt wie das funktioniert.
 

lorelei

New member
Kannst du bitte, nachdem du es ausgetestet hast, deine Ergebnisse berichten?
(Vielleicht könntest du den Code veröffentlichen, oder mailen?
Ich würde es auch wirklich dringend brauchen!
 

Cyberm@ster

New member
Ich werd mir Mühe geben, aber verlass dich nicht drauf. In 3 Wochen hab ichs eventuell fertig, das hängt aber von der Arbeit an der Uni ab und wie gut ich weiterkomme. Probiers einfach selbst aus mit den Funktionen die in der Mail genannt wurden. Ich meld mich wenn ich etwas vorangekommen bin.

Edit:

Ich hab mal testweise folgenden Code geschrieben. Das Programm stürzt aber ab, da fgets einen FILE* erwartet und ich einen HANDLE WINAPI übergebe. Kennt jemand eine Funktion die fgets ähnlich ist und mit einem solchen HANDLE umgehen kann. Ich will nicht unbedingt den HANDLE umbauen müssen...

Antwort: ReadFile() statt fgets() benutzen.

Code:
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <string.h>

int main(int argc, char *argv[])
{
  char linein[100];
  HANDLE WINAPI lefthand;
  lefthand = CreateFile("C:\test.txt",GENERIC_READ,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_READONLY,NULL);
  fgets(linein,100,lefthand);
  CloseHandle(lefthand);
  puts(linein);
  system("PAUSE");	
  return 0;
}
Code:
[Warning] `__stdcall__' attribute only applies to function types
Edit:

Ich hab endlich ein brauchbares Beispiel gefunden http://msdn2.microsoft.com/en-us/library/bb540534(VS.85).aspx Ich konnte es aber nicht kompilieren da main nicht int als Wert zurückgibt. Ich bin gerade dabei M$ Visual C++ Express 2008 downzuloaden, in der Hoffnung, dass es dann klappt. Kann jemand erklären was es mit diesem

Code:
void __cdecl _tmain(int argc, TCHAR *argv[])
auf sich hat?
 

Cyberm@ster

New member
Danke für die Links KlausSchiefer (wie kommst du eigentlich an diesen Nick wenn ich fragen darf?). In den Links wird von Interrupts gesprochen, das ist aber afaik unter NT (aufwärts) nicht mehr nötig da es die Funktionen CreateFile, ReadFile und WriteFile gibt (siehe http://www.codeguru.com/cpp/w-p/system/misc/article.php/c5665/). Ich bin jetzt soweit, dass ich den Beispielcode (leicht verändert) aus meinem letzten Post zum Laufen gebracht habe.

Code:
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <string.h>

#define BUF_SIZE 80

HANDLE hFile; 

int main()
{
    DWORD dwBytesRead;
    char buf[BUF_SIZE];						
    char datei[100];
    strcpy(datei,"C:\\test.txt");
 
    hFile = CreateFile(datei,               // file to open
                       GENERIC_READ,          // open for reading
                       FILE_SHARE_READ,       // share for reading
                       NULL,                  // default security
                       OPEN_EXISTING,         // existing file only
                       FILE_ATTRIBUTE_NORMAL, // normal file
                       NULL);                 // no attr. template
 
    if (hFile == INVALID_HANDLE_VALUE) 
    { 
        printf("Could not open file (error %d)\n", GetLastError());
        return; 
    }

    if(!ReadFile(hFile, buf, BUF_SIZE, &dwBytesRead, NULL))
    {
        printf("Could not read from file (error %d)\n", GetLastError());
        return;
    }
    printf("Bytes read: %d\n\n",dwBytesRead);
    buf[dwBytesRead]='\0';

    printf(TEXT("Text read from %s: "), datei);
    printf("%s\n", buf);

    CloseHandle(hFile);
    system("PAUSE");
    return 0;
}
Mit "\\\\.\\PhysicalDrive0" funktioniert es bis jetzt aber noch nicht. Das ist zwar noch weit von meinem Ziel entfernt, aber direkten Lesezugriff auf die Festplatte wäre ja schon mal ein Anfang ^^
 

KlausSchiefer

New member
Ich bin zwar kein Programmierer, aber der code öffnet doch nur eine Datei zum lesen und gibt dir ein Filehandle und danach liest du ein paar bytes und machst sie wieder zu?
 

Cyberm@ster

New member
Ja... Das war ein erster Test. Ich probiere gerade das ganze so hinzubekommen dass ich das Laufwerk direkt öffnen kann. Ginge es mir nur darum eine Datei zu öffnen würde ich FILE* und fopen() benutzen. Ich weiss selber, dass ich nur in sehr kleinen Schritten vorankommen...

Edit:

Ich weiss jetzt wo der Fehler lag. Zum einen muss man bei ganzen Datenträgern immer FILE_SHARE_WRITE benutzen. Und ausserdem kann man den handle nicht mit ReadFile öffnen, sondern man muss DeviceIoControl benutzen. Dazu gibst einen recht hilfreichen Beispielcode

Edit:

Hab endlich alles zusammen was ich brauche:

CreateFile Function
DeviceIoControl Function

For lists of supported control codes, see the following topics:
  • Communications Control Codes
  • Device Management Control Codes
  • Directory Management Control Codes
  • Disk Management Control Codes
  • File Management Control Codes
  • Power Management Control Codes
  • Volume Management Control Codes
Unter anderem werd ich FSCTL_GET_RETRIEVAL_POINTERS benutzen.

Die Benutzung dieser Funktion ist alles andere intuitiv, nach langer Suche habe ich aber eine gute Beschreibung gefunden: http://www.wd-3.com/archive/luserland.htm
 
Oben