PDA

View Full Version : lettura hd a basso livello


Furla
22-05-2006, 15:43
vorrei poter leggere byte per byte un hard disk e recuperare alcuni dati andati persi e irrecuperabili con altri mezzi.

spiego di preciso la situazione: ho perso 2 files di testo, partizione illeggibile neanche da programmi appositi; ma ho in un altro hard disk le vecchie versioni dei files. vorrei poter cercare all'interno dell'hard disk i due files facendo riferimento alle parti rimaste invariate rispetto alle versioni vecchie, ovvero cercare nell'hard disk queste parti invariate e salvarmi i settori vicini (sperando che i files non siano frammentati).


l'algoritmo è semplice e ce l'ho già in mente, basta poter leggere il byte all'indirizzo X del disco.

se non è possibile agire direttamente sul disco, pensavo che potrei anche salvare sul mio attuale sistema un'immagine dell'hard disk; ma non deve essere compressaq o modoficata in alcun modo, deve essere proprio la copia byte per byte dellhard disk in questione.


qualcuno mi sa aiutare? almeno è chiaro ciò che chiedo :D ?

grazie

Mark0
22-05-2006, 16:48
Chiarissimo.
Ma l'approccio più semplice è proprio quello che illustri tu alla fine: creare un'immagine "fisica" dell'HD, e operare quindi direttamente sul file cosi ottenuto; cosa quindi banale con qualsiasi linguaggio tu scelga di utilizzare.
Un tool free per creare il file potrebbe essere DriveImage XML (http://www.runtime.org/dixml.htm).

Bye!

Furla
22-05-2006, 18:56
DriveImage XML runs under Windows XP Home, XP Professional and Windows Server 2003 only.
The program will backup, image and restore drives formatted with FAT 12, 16, 32 and NTFS.

ci sono 2 problemi: uso windows 2000 e la partizione non esiste più.

dici che funziona lo stesso? faccio qualche prova...
esistono altri programmi simili a questo?

Mark0
22-05-2006, 19:27
Direi proprio di si, non dovresti aver problemi a trovarne diversi con Google. Questo è solo il primo che mi è venuto in mente.

Bye!

Furla
06-06-2006, 22:23
niente da fare, non ne trovo nessuno che fa quello che serve a me! tutti i programmi che provo fanno un'immagine che contiene solo la parte utilizzata della partizione, la parte vuota viene ignorata... e i miei files sono proprio nella parte che per il file system è vuota :cry:

idee? consigli?

71104
06-06-2006, 22:57
su Windows la fopen dovrebbe aprirti uno pseudofile corrispondente ad un volume logico se come file name specifichi "\\\\.\\X:", ovvero:
- doppio slash (in C diventano 4 slash)
- punto
- slash (in C diventano 2)
- lettera del volume logico
- due punti

per esempio

FILE *f = fopen("\\\\.\\D:", "r");

ti apre un ipotetico volume D: come uno pseudofile in sola lettura.

la cosa penso che funzioni solo sui kernel NT-based però, perché è strettamente legata all'architettura del sistema (doppio slash punto slash rimanda ad un branch del namespace globale degli oggetti del kernel, che si chiama "\DosDevices" ed è il branch usato da Win32).

di conseguenza tutto questo funziona solo su Windows NT/2000/XP e futuri (se mai arriveranno... :asd: )

spero di esserti stato utile

ciao

Furla
07-06-2006, 14:02
aspetta fammi capire, questo comando in che ambiente lo uso?
funziona se la partizione è ntfs o anche se attacco il disco in slave ad un sistema con win2000?

Furla
02-07-2006, 12:05
ciao a tutti, ho continuato per un po' via PM con 71104, mi ha detto che il codice che ha postato è in C.

io conosco abbastanza vb6 e vb.net, mi sono procurato una guida e visual studio 6, con visual c++ posso fare un programma sfruttando il codice postato da 71104? non capisco però come usare quel codice, FILE cosa sarebbe? e quel *f?

grazie a chi mi aiuta

Xalexalex
02-07-2006, 13:45
su Windows la fopen dovrebbe aprirti uno pseudofile corrispondente ad un volume logico se come file name specifichi "\\\\.\\X:", ovvero:
- doppio slash (in C diventano 4 slash)
- punto
- slash (in C diventano 2)
- lettera del volume logico
- due punti

per esempio

FILE *f = fopen("\\\\.\\D:", "r");

ti apre un ipotetico volume D: come uno pseudofile in sola lettura.

la cosa penso che funzioni solo sui kernel NT-based però, perché è strettamente legata all'architettura del sistema (doppio slash punto slash rimanda ad un branch del namespace globale degli oggetti del kernel, che si chiama "\DosDevices" ed è il branch usato da Win32).

di conseguenza tutto questo funziona solo su Windows NT/2000/XP e futuri (se mai arriveranno... :asd: )

spero di esserti stato utile

ciao
:eek:
:ave:

Furla
02-07-2006, 14:05
alex mi sai aiutare? con quanto illustrato da 71104, sapresti fare un programma che copia un'intera partizione in un file?

andbin
02-07-2006, 14:48
Io tempo fa avevo scritto delle funzioni per leggere dei settori specifici sul disco (MBR, Boot Sector).

Ad esempio per leggere il Boot Sector da un volume logico:
DWORD ReadBootSector (TCHAR cVolume, LPVOID lpOutputBuffer)
{
DWORD dwRet = ERROR_SUCCESS;
BYTE bBufSector[1024];
LPVOID lpBuffer;
TCHAR szDevName[32];
HANDLE hDevice;
DWORD dwPos, dwRead;

lpBuffer = (LPVOID) ((DWORD_PTR) bBufSector + 511 & ~0x1FF);

wsprintf (szDevName, _T("\\\\.\\%c:"), cVolume);

hDevice = CreateFile (szDevName, GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, 0, NULL);

if (hDevice != INVALID_HANDLE_VALUE)
{
dwPos = SetFilePointer (hDevice, 0, NULL, FILE_BEGIN);

if (dwPos != INVALID_SET_FILE_POINTER)
{
if (ReadFile (hDevice, lpBuffer, 512, &dwRead, NULL))
CopyMemory (lpOutputBuffer, lpBuffer, 512);
else
dwRet = GetLastError ();
}
else
dwRet = GetLastError ();

CloseHandle (hDevice);
}
else
dwRet = GetLastError ();

return dwRet;
}Puoi usare questo codice, se vuoi, estendendolo per leggere tutti i settori del volume e scriverli su un file.

71104
02-07-2006, 15:52
:eek:
:ave: :wtf:

71104
02-07-2006, 15:55
ciao a tutti, ho continuato per un po' via PM con 71104, mi ha detto che il codice che ha postato è in C.

io conosco abbastanza vb6 e vb.net, mi sono procurato una guida e visual studio 6, con visual c++ posso fare un programma sfruttando il codice postato da 71104? non capisco però come usare quel codice, FILE cosa sarebbe? e quel *f?

grazie a chi mi aiuta FILE *f serve a dichiarare una variabile f che rappresenta un file descriptor della libreria standard del C; in pratica, la funzione fopen apre un file, e il file descriptor che viene ritornato è ciò che rappresenta quel file e tramite il quale puoi effettuare operazioni su di esso (per esempio letture tramite fread e scritture tramite fwrite). oltre a qualche guida sulla sintassi del C (come ad esempio quella che trovi pure su MSDN) ti consiglio di leggerti anche la guida di queste funzioni: fopen, fread, fwrite, fclose. tutto su MSDN ^^

ciao

71104
02-07-2006, 16:01
to':
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang98/HTML/clanghm.asp?frame=true
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore98/html/_crt_fopen.2c_._wfopen.asp
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore98/HTML/_crt_fread.asp
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore98/HTML/_crt_fwrite.asp?frame=true
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore98/HTML/_crt_fclose.2c_._fcloseall.asp

andbin
02-07-2006, 16:26
per 71104:
ma sei sicuro che le funzioni standard del "C" possano operare a quel livello??? Io per curiosità ho fatto una prova: ho aperto il volume con fopen("\\\\.\\c:", "r"); e in effetti l'apertura va a buon fine. Quando cerco di leggere 512 bytes con la fread, invece me ne legge solo 304. :confused: :stordita:

71104
02-07-2006, 23:15
boh... GetLastError ritorna qualcosa?
non credo cambi nulla se usi CreateFile anziché fopen, non esiste implementazione delle librerie standard del C che non passi il primo parametro di fopen al primo di CreateFile :)

Furla
03-07-2006, 14:06
continuo col metodo di 71104, se dovessi avere problemi come andbin seguo l'altra strada. mi metto subito all'opera!

grazie a entrambi, siete gentilissimi!

trallallero
03-07-2006, 14:36
per 71104:
ma sei sicuro che le funzioni standard del "C" possano operare a quel livello??? Io per curiosità ho fatto una prova: ho aperto il volume con fopen("\\\\.\\c:", "r"); e in effetti l'apertura va a buon fine. Quando cerco di leggere 512 bytes con la fread, invece me ne legge solo 304. :confused: :stordita:


... fread() stops reading bytes if an end-of-file or error condition is encountered while reading
stream, or if nitems items have been read. ...
non puó essere che la fread incontri un EOF leggendo in binario ?

71104
03-07-2006, 15:23
non puó essere che la fread incontri un EOF leggendo in binario ? -_-'

i file veri e propri mica finiscono con un vero EOF...

trallallero
03-07-2006, 15:35
-_-'
... cos'é sta roba ?

i file veri e propri mica finiscono con un vero EOF...
cioé ?

71104
03-07-2006, 20:32
cioé ? i file veri e propri mica finiscono con un vero EOF

andbin
03-07-2006, 20:46
Diciamo, per essere precisi, che il EOF si può intendere in 2 modi: Il end-of-file fisico oppure il marcatore di end-of-file (solo per i file di testo) che è il carattere ASCII con codice 26 (0x1A).

Se ad esempio con una fread cerco di leggere 1000 bytes e ne ottengo solo 800, posso stabilire se c'è stato EOF con la funzione feof oppure un errore con la funzione ferror.
Il carattere di EOF invece è più che altro una convenzione per i file di testo ma non uno "standard".

trallallero
04-07-2006, 07:33
i file veri e propri mica finiscono con un vero EOF
cioé ?

a chi si stanca prima ? :D

trallallero
04-07-2006, 07:45
Diciamo, per essere precisi, che il EOF si può intendere in 2 modi: Il end-of-file fisico oppure il marcatore di end-of-file (solo per i file di testo) che è il carattere ASCII con codice 26 (0x1A).

Se ad esempio con una fread cerco di leggere 1000 bytes e ne ottengo solo 800, posso stabilire se c'è stato EOF con la funzione feof oppure un errore con la funzione ferror.
Il carattere di EOF invece è più che altro una convenzione per i file di testo ma non uno "standard".

Come la so anch'io, ma se mi sento dire che
"i file veri e propri mica finiscono con un vero EOF"
mi viene qualche dubbio ... devo modificare tutti i
miei programmi in C ??? :D

Non puoi leggere con getc in ciclo e vedere il carattere numero 304 ?
per capire perché si interrompe la fread.

Furla
04-07-2006, 07:46
io pensavo che all'inizio della partizione ci fosse una tabella con tutti i nomi dei file, la loro dimensione, il percorso e altre proprietà, e il loro indirizzo sull'hd (o più di uno se sono frammentati)

andbin
04-07-2006, 10:29
Non puoi leggere con getc in ciclo e vedere il carattere numero 304 ?Non è un problema legato al valore del carattere! Se nella mia prova che ho fatto, leggendo 512 bytes me ne sono stati restituiti solo 304, non vuol dire che è perché nel 304° carattere c'è il EOF 26 (0x1A)!!!
In un file binario qualsiasi, il codice 26 (0x1A) non ha un significato di EOF ... vale esattamente come qualunque altro codice.

andbin
04-07-2006, 10:37
io pensavo che all'inizio della partizione ci fosse una tabella con tutti i nomi dei file, la loro dimensione, il percorso e altre proprietà, e il loro indirizzo sull'hd (o più di uno se sono frammentati)Sì, è più o meno così ma è più complesso. Dipende comunque dal tipo di file-system. Se si tratta di una partizione FAT, è abbastanza semplice dal punto di vista concettuale: il primo settore è il boot-sector, poi seguono un certo numero di settori "riservati", poi seguono 2 tabelle FAT (File Allocation Table) in cui sono marcati i cluster usati nel file-system e poi c'è tutta l'area dei dati, che inizia con uno spazio dedicato alla root-directory.
Comunque le informazioni precise sul formato FAT le trovi ovviamente nelle specifiche ufficiali della FAT. ;) Vedi <qui> (http://en.wikipedia.org/wiki/File_Allocation_Table).

71104
04-07-2006, 16:03
le specifiche ufficiali sono incomplete (io e DanieleC88 ne sappiamo qualcosa -.-' )

repne scasb
05-07-2006, 18:31
Comunque le informazioni precise sul formato FAT le trovi ovviamente nelle specifiche ufficiali della FAT. Vedi <qui> (http://en.wikipedia.org/wiki/File_Allocation_Table).

Le specifiche ufficiali "purtroppo" differiscono" pe un certo numero di sottigliezze rispetto ai volumi FAT/12/16/32 esistenti. Una guida ad alcune "differenze" puo' essere trovata nel testo: "Undocumented DOS" ISBN 0-201-57064-557064 alle pagine: 155-164

Furla
08-07-2006, 18:14
ho iniziato ad avvicinarmi al C.

volendo realizzare un programma esattamente come quello nell'esempio della fopen (qui (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore98/html/_crt_fopen.2c_._wfopen.asp)) mi sono accorto che occorre un file header.

i programmi vengono inizializzati dal programma con un riferimento al file stdafx.h, mentre per la funzione serve stdio.h. dove lo trovo? si scarica?

andbin
08-07-2006, 18:29
i programmi vengono inizializzati dal programma con un riferimento al file stdafx.h, mentre per la funzione serve stdio.h. dove lo trovo? si scarica?Giusto per chiarire: stdafx.h è una "roba" del VC++. La documentazione del VC++ dice: "File di inclusione per i file di inclusione di sistema standard e per i file di inclusione specifici del progetto che vengono utilizzati frequentemente ma modificati raramente.". Se non stai usando VC++ o se lo usi e lui non ti ha creato questo file, credo che te ne puoi anche fregare di questo stdafx.h. ;)

stdio.h è un include standard che fa parte della libreria del "C". Naturalmente è disponibile con qualunque compilatore "C".

71104
08-07-2006, 18:38
esatto; il file stdio.h ce l'hai già, mentre stdafx.h lo devi scrivere tu ma non è necessario, per il programma che vuoi fare ti basta semplicemente un singolo file .c

Furla
11-07-2006, 08:03
non riesco a far andare il programma :cry: :cry: :cry:

appena lo faccio partire mi appare quest'errore:
"l'istruzione a "0x004011e9" ha fatto riferimento alla memoria a 0x0000000c". la memoria non poteva essere "read"

la finestra tipo DOS riporta

the file 'data' was not opened
the file 'data2' was opened
press any key to continue

ma io data2 non l'ho mai creato, dovrebbe essere un file nella stessa cartella dell'exe?

andbin
11-07-2006, 08:22
non riesco a far andare il programma :cry: :cry: :cry: Se posti il sorgente, abbiamo sicuramente maggiore possibilità di capire dov'è l'errore. ;)

Furla
11-07-2006, 10:41
è quello di esempio della fopen, nella pagina linkata poco sopra da 711:

#include <stdio.h>

FILE *stream, *stream2;

void main( void )
{
int numclosed;

/* Open for read (will fail if file "data" does not exist) */
if( (stream = fopen( "data", "r" )) == NULL )
printf( "The file 'data' was not opened\n" );
else
printf( "The file 'data' was opened\n" );

/* Open for write */
if( (stream2 = fopen( "data2", "w+" )) == NULL )
printf( "The file 'data2' was not opened\n" );
else
printf( "The file 'data2' was opened\n" );

/* Close stream */
if( fclose( stream ) )
printf( "The file 'data' was not closed\n" );

/* All other files are closed: */
numclosed = _fcloseall( );
printf( "Number of files closed by _fcloseall: %u\n", numclosed );
}

andbin
11-07-2006, 10:53
#include <stdio.h>

FILE *stream, *stream2;

void main( void )
{
int numclosed;

/* Open for read (will fail if file "data" does not exist) */
if( (stream = fopen( "data", "r" )) == NULL )
printf( "The file 'data' was not opened\n" );
else
printf( "The file 'data' was opened\n" );

/* Open for write */
if( (stream2 = fopen( "data2", "w+" )) == NULL )
printf( "The file 'data2' was not opened\n" );
else
printf( "The file 'data2' was opened\n" );

/* Close stream */
if( fclose( stream ) )
printf( "The file 'data' was not closed\n" );

/* All other files are closed: */
numclosed = _fcloseall( );
printf( "Number of files closed by _fcloseall: %u\n", numclosed );
}Se il file "data" non esiste, allora stream sarà NULL. Fare successivamente una fclose(stream) passandogli quindi NULL, causa un segmentation fault. Il file "data2" invece viene creato se non esiste oppure troncato se esiste (vedi "w+").

AngeL)
11-07-2006, 11:32
ma l'assembly vi fa proprio schifo?

Furla
11-07-2006, 11:57
non so nulla di assembly, se ti va di insegnarmelo ben venga :D

ok grazie della spiegazione, è tutta colpa del fclose... ora ho capito ;)

sto capendo un po' come funziona, intanto ho creato il mio bel file prova.asd da programma :D

unica cosa che non mi torna è la seguente:
ho cambiato il punto in cui si usa fclose (tutto il resto l'ho lasciato uguale), facendogli chiudere stream2 al posto di stream:

if( fclose( stream2 ) )
printf( "The file 'data2' was not closed\n" );


e infatti quando poi va ad usare fcloseall, la finestra tipo DOS (ma ha un nome specifico? :D) dice che il numero di file chiusi da fcloseall è zero; ma non compare il messaggio che dovrebbe apparire alla chiusura di stream2: "The file 'data2' was not closed". qualcuno mi sa dire perché?

grazie ancora per l'aiuto :)

Furla
12-07-2006, 15:01
up, vorrei capire il problema...

poi su msdn ho cercato un po', ma il sito non è molto intuitivo e non ho trovato nulla che mi aiuti a gestire un a variabile di tipo FILE, ad esempio compiere ricerche al suo interno... immagino che da qualche parte ne parli, qualcuno mi sa dare una mano?

andbin
12-07-2006, 15:07
ma non compare il messaggio che dovrebbe apparire alla chiusura di stream2: "The file 'data2' was not closed". qualcuno mi sa dire perché?Il file 'data2' viene sempre creato ed aperto per la lettura/scrittura e quindi (a meno di casini strani), facendo fclose(stream2) chiude correttamente lo stream2.

71104
12-07-2006, 16:35
ma l'assembly vi fa proprio schifo? e ma certo perché tu vorresti realizzare un programma simile in assembly... :asd:

dai su, vediamo cosa sai fare :D

AngeL)
12-07-2006, 16:55
non lo voglio creare :mc: perche di assembly non so tanto, ma visto che opera sull hd e lo puo leggere con D(credo) si potrebbe fare qualcosa :mc:

71104
12-07-2006, 18:24
non lo voglio creare :mc: perche di assembly non so tanto, ma visto che opera sull hd e lo puo leggere con D(credo) si potrebbe fare qualcosa :mc: certo che si: si può fare qualcosa di molto simile (se non addirittura identico, ma solo se si è veramente bravi) a ciò che produrrebbe il compilatore C.

Furla
12-07-2006, 18:28
uhm, vedo ora che fclose restituisce un int... che succede mettendo come condizione di un if un intero? è per questo che non capisco...

if( fclose( stream ) )


azz sono proprio incapace, non trovo nulla sul tipo FILE su msdn... 711 mi sai linkare qualcosa? :D

71104
12-07-2006, 18:42
uhm, vedo ora che fclose restituisce un int... che succede mettendo come condizione di un if un intero? è per questo che non capisco...

if( fclose( stream ) ) puoi anche trascurare il valore di ritorno di fclose, è piuttosto al di là dei tuoi scopi; controlla solo fopen, fread e fwrite; e penso che potresti addirittura tralasciare anche fwrite, ma giusto per scrupolosità...


azz sono proprio incapace, assolutamente no, anzi, hai voglia di imparare e di realizzare questo programmetto che comunque per uno che parte completamente da zero implica concetti non banali...

c'è gente da me all'università che veramente non capisco perché si è iscritta... :O
ma ti giuro che non lo capisco... gli piace l'informatica? mavàààààà, non ci credo...


non trovo nulla sul tipo FILE su msdn... 711 mi sai linkare qualcosa? :D il fatto è che il motore di ricerca di MSN è scrauso (mica come Google :O), e se cerchi FILE non considera che è tutto maiuscolo e trova un sacco di roba non pertinente. comunque il tipo FILE è quello che in terminologia microsoftiana si usa definire un tipo opaco: tu non sai come è definito e come viene usato internamente, sai solo che una variabile che punta a FILE (cioè una variabile FILE*) è un descrittore di un file, ovvero quella variabile rappresenta per te un file aperto in memoria. le principali funzione per la manipolazione di questo tipo sono:
- fopen, che apre un file col nome/percorso specificato e restituisce il corrispondente file descriptor di tipo FILE*
- fread, che legge dati dal file rappresentato dal file descriptor
- fwrite, che scrive
- fclose, che invalida il file descriptor "chiudendo" il file associato; dopo una fclose eseguita con successo quel file descriptor non è più valido

Furla
15-07-2006, 08:21
il fatto è che il motore di ricerca di MSN è scrauso

ah ecco, di solito riesco a districarmi abbastanza bene in questo genere di garbugli... stavo iniziando a dubitare delle mie facoltà mentali :D

allora devo farmi la funzione di ricerca da solo...

dunque, leggendomi un po' il fread vedo che in pratica permette di prendere i bytes del file e di portarli in un array-buffer, giusto?

ma se il mio file è una partizione di 18 GB dite che si arrabbia? :D?
c'è la possibilità (oltre alla necessità) di aprire il file "un pezzo alla volta"?

71104
15-07-2006, 11:34
lol :p
chiaramente prima di leggere 18 GB con la fread dovrai allocare il buffer con la malloc, e la malloc figurati che ti risponde se gli chiedi 18 GB :asd: tantopiù che non glieli puoi nemmeno chiedere perché la dimensione espressa da un intero unsigned da 4 bytes arriva al massimo a 4 GB :p

quindi è ovvio che si, devi allocare un buffer molto più piccolo (dimensioni che ti pare: da 1 byte a 1 GB, ma le dimensioni estreme sono sconsigliate; facciamo 4 KB, che è la dimensione di una pagina) e fare il tuo lavoro un pezzetto alla volta.

adesso quindi non ti rimane che introdurre il concetto di file pointer :)
ovvero: se prima leggi con fread 4 kb, e successivamente ne leggi altri 4, i 4 che leggi non sono sempre gli stessi; il file pointer ad ogni lettura si sposta in avanti del numero di bytes che hai letto, perciò i 4 kb che leggi la seconda volta sono quelli successivi ai 4 di prima.

The3DProgrammer
15-07-2006, 12:38
lol :p
chiaramente prima di leggere 18 GB con la fread dovrai allocare il buffer con la malloc, e la malloc figurati che ti risponde se gli chiedi 18 GB :asd: tantopiù che non glieli puoi nemmeno chiedere perché la dimensione espressa da un intero unsigned da 4 bytes arriva al massimo a 4 GB :p




+ o - quello ke ha detto materazzi a zidane...:asd:


ciauz

Furla
19-07-2006, 08:48
mi sono letto la malloc su msdn, mi sono fatto un'idea di cosa fa, ma non ho capito bene come usarla...

andbin
19-07-2006, 09:14
mi sono letto la malloc su msdn, mi sono fatto un'idea di cosa fa, ma non ho capito bene come usarla...malloc serve per allocare dello spazio in memoria. Tu gli passi il numero di bytes che vuoi allocare e la malloc ti restituisce un puntatore a quel blocco di memoria (che dovrai poi liberare con la funzione free).

Vuoi per esempio allocare spazio per 10 valori interi??
int *valori;
valori = (int*) malloc (10 * sizeof (int));

valori[0] = 1;
...
valori[9] = 10;Ah, naturalmente il valore restituito da malloc sarebbe da testare ... vale NULL se la allocazione è fallita per qualche motivo!

Anomaly Rulez
19-07-2006, 09:36
azz, leggendo questo 3d mi vergogno di aver creato il mio un po piu sotto :eek:

Furla
19-07-2006, 09:54
ok, fin qui ci siamo, ma non capisco la sintassi, specialmente gli asterischi... vedo che si usano spesso nelle dichiarazioni di variabili, nelle guide che ho consultato non ho trovato nulla. perché a volte vedo un asterisco dopo il tipo o prima del nome???

andbin
19-07-2006, 10:10
ok, fin qui ci siamo, ma non capisco la sintassi, specialmente gli asterischi... vedo che si usano spesso nelle dichiarazioni di variabili, nelle guide che ho consultato non ho trovato nulla. perché a volte vedo un asterisco dopo il tipo o prima del nome???Ah beh ... questo è "un altro paio di maniche" come si suol dire! L'asterisco nelle dichiarazioni denota un puntatore.
Quindi dovresti prima apprendere bene tutta la teoria riguardante i puntatori. Senza una ottima conoscenza di questo argomento, non credo che possa fare molto in "C". E lo dico non per metterti in difficoltà o altro ma perché i puntatori sono uno degli argomenti più importanti nel C/C++. ;)

Furla
19-07-2006, 10:55
farò qualche ricerca, non so come ringraziarti!

Anomaly Rulez
19-07-2006, 13:41
* e &, passaggio di parametri per valore, passaggio di parametri per riferimento, etc. etc...

71104
19-07-2006, 17:51
detto molto sinteticamente e molto alla pecionara :p : un puntatore è una variabile che anziché contenere qualcosa, contiene un indirizzo di memoria al quale si trova quel qualcosa. esempio pratico:

int a;
int *b;

la prima dichiarazione dichiara una variabile a che contiene un numero intero; la seconda invece è non un intero ma un puntatore a un numero intero. però tieni presente che la variabile b non è inizializzata, percui (anche a seconda di dove e come la dichiari) contiene valori ignoti arbitrari e indefiniti; ciò implica che se tu usi b prima di averla inizializzata (e se lo fai il compilatore ti darà un warning) nella più probabile delle ipotesi manderai in crash il programma a runtime, che tenterà di accedere ad un indirizzo arbitrario e indefinito dove probabilmente non è stato allocato nulla.

ora dunque vediamo una versione con inizializzazioni del precedente codice:

int a = 0;
int *b = &a;

a viene chiaramente inizializzata a 0; l'operatore & serve a restituire l'indirizzo di memoria a cui si trova il valore dell'operando, perciò abbiamo che b contiene l'indirizzo di memoria di a: b punta ad a; all'indirizzo di memoria memorizzato in b io ci trovo lo zero di a.

ovviamente per inizializzare b non era necessario inizializzare anche a: se avessi inizializzato b semplicemente avresti avuto che il valore contenuto all'inidirzzo specificato da b (il valore puntato da b quindi) sarebbe stato arbitrario e indefinito; in una situazione simile di certo non manderesti in crash il programma, semplicemente useresti valori ignoti.

per concludere, nulla toglie che in C tu possa realizzare situazioni più complesse e raffinate: se davanti al nome della variabile metti due asterischi anziché uno hai realizzato un puntatore doppio, cioè una variabile che contiene l'indirizzo di memoria dove troverò l'indirizzo di memoria a cui troverò il valore finale :D

ovviamente un affare del genere va inizializzato due volte

ora non ti resta che imparare la gestione di array in C e come essa vada a conciliarsi con la gestione dei puntatori, ma qui te la cavi da solo :Prrr:

sirus
19-07-2006, 18:54
Furla l'immagine della voglia di imparare :eek: hai imparato del C quello che solitamente si impara in un intero anno di scuole superiori...
ora però ho anche io una domanda:
per usare i sistemi di apertura proposti da 71104 e da andbin è necessario che la partizione esista (e che non sia stata cancellata altrimenti suppongo che non si possa più fare nulla) e che sia ancora referenziata da una lettera di volume giusto?
in più se quella partizione non è più dotata di un file systema come può una funzione delle librerie standard del C (che comunque si appoggia alle API del sistema) oppure la funzione di sistema andare a leggere da quel volume se non può interrogare il driver del file system (non essendo presente)?
Conoscendo (seppur superficialmente) la struttura di un file system e come opera su una partizione mi verrebbe da dire che è impossibile leggerla se la partizione ne è priva.
:mbe:

71104
19-07-2006, 20:44
Furla l'immagine della voglia di imparare :eek: hai imparato del C quello che solitamente si impara in un intero anno di scuole superiori... infatti glielo volevo pure scrivere nel precedente messaggio ma me ne sono scordato: Furla, nonostante tutto non molli e continui a voler imparare il C con una costanza veramente lodevole; che c'avevi di così tanto importante su quella partizione??? :D:D:D:D

per usare i sistemi di apertura proposti da 71104 e da andbin è necessario che la partizione esista (e che non sia stata cancellata altrimenti suppongo che non si possa più fare nulla) e che sia ancora referenziata da una lettera di volume giusto? ovviamente; infatti nel nome del file che specifichi usi la lettera.

per essere più precisi diciamo questo: ciò che stai andando ad aprire con quel sistema è lo pseudofile associato alla periferica (anche detto Device Object), sia essa una periferica virtuale (come un volume logico che rappresenta una partizione, ma non è il nostro caso) o una periferica realmente presente (come un volume logico che rappresenta un intero hard disk, che è il nostro caso).

una volta ottenuto un handle (che diventa poi un file descriptor nel layer di compatibilità ANSI di Visual C++) al Device Object, è possibile interagire con esso con le funzioni essenziali di Win32: ReadFile, WriteFile, DeviceIoControl, CloseHandle. tutte queste funzioni (dopo che le rispettive richieste sono arrivate al microkernel tramite interfacce native di NT) vanno a consultare la struct (parzialmente documentata) che costituisce il corpo del Device Object e trovano in essa un campo DriverObject, che punta al corpo di un altro oggetto del namespace, il Driver Object appunto; esso rappresenta il kernel driver contenente le routines di callback (dette Dispatch Routines) che gestiscono le richieste (IRP, IO Request Packets) indirizzate a quella periferica, o meglio a quel Device Object; da notare che un driver può gestire più periferiche, cioè più Device Object possono puntare allo stesso Driver Object. dopo che è stato individuato il Driver Object naturalmente viene inviato ad esso per conto del Device Object un IRP che chieda al driver di rispondere alla richiesta del particolare servizio proveniente da user mode:
- ReadFile invia un IRP con codice IRP_MJ_READ
- WriteFile invia IRP_MJ_WRITE
- DeviceIoControl invia IRP_MJ_DEVICE_CONTROL
- CloseHandle invia IRP_MJ_CLOSE

e abbiamo omesso in questa spiegazione un'altra importante funzione Win32, la CreateFile, che altro non sarebbe quella che il layer di compatibilità ANSI di VC++ traduce in fopen e che ovviamente si occupa di chiedere al kernel di creare un HANDLE (poi eventualmente castato a fd) associato all'oggetto del namespace globale che ha quel nome. e come avrete intuito, il codice dell'IRP di cui CreateFile causa l'invio è IRP_MJ_CREATE ^^

riassumendo, nel nostro caso specifico accade ciò:
- fopen -> CreateFile -> NtCreateFile -> IRP_MJ_CREATE; il kernel incrementa il reference count del Device Object e il driver fa quello che deve fare per tenere presente che da user mode qualcuno ha richiesto l'accesso alla periferica
- fread -> ReadFile -> NtReadFile -> IRP_MJ_READ; il driver (che è uno Storage Class) risponde alla richiesta con tutti i mestieri suoi (frammenta in più richieste se è troppo grande, passa ai drivers di livello inferiore, cioè eventuali filtri ed infine lo Storage Port, che invia la richiesta all'hardware materialmente con istruzioni assembly IN e OUT); la richiesta di lettura (come quella di scrittura) è gestita in maniera asincrona per ovvi motivi, tuttavia il thread che ha originariamente effettuato la richiesta rimane bloccato perché la ReadFile iniziale asincrona non era; o meglio, la fread non lo è :Prrr:
- fclose -> CloseHandle -> NtClose -> IRP_MJ_CLOSE; il kernel decrementa il reference count del Device Object e il driver tiene presente che un'istanza della sua periferica in user mode è morta.

dov'è il file system in tutto ciò? l'abbiamo bypassato: il titolo del topic infatti era "lettura HD a basso livello" :)
l'abbiamo bypassato fin dalla chiamata a fopen, perché non abbiamo aperto un file (operazione che richiederebbe l'intervento del file system per trovare il file e per operarci sopra), ma un oggetto del namespace globale, anzi per essere più precisi un oggetto di un particolare branch del namespace che è l'unico branch visibile da Win32 (si chiama "\DosDevices" o anche "\??"). abbiamo potuto fare ciò (ovvero aprire un oggetto di Windows NT anziché un file) perché la CreateFile non serve ad aprire files, serve ad aprire oggetti di svariato genere tra cui anche files. per chiedere alla CreateFile di aprire un generico oggetto nel branch di Win32 (che può essere un oggetto di sincronizzazione (evento, semaforo, mutex, timer...), una pipe, una mailslot, una Communication Resource, un Device Object...) dobbiamo specificare nel parametro del nome del "file" il prefisso "\\.\" (in C diventa "\\\\.\\"), quindi specificando "\\.\X:" (con X lettera della nostra partizione) chiediamo di aprire quello che il kernel scopre essere un symlink che punta ad un Device Object che sta in un branch non visibile a Win32 e che si chiama "\Device" (al singolare, non so perché). il Device Object di per se' si chiamerà invece "\Device\Volume{GUID incomprensibile}".

da notare come gli oggetti di Windows NT siano Securable Objects, ovvero possano essere associati ad un descrittore di sicurezza; ciò permette tra le altre cose di proteggere l'accesso all'hardware con la stessa immane flessibilità che caratterizza tutto il sistema di sicurezza di Windows. come al solito di default è tutto aperto :D :stordita: :mc:


Conoscendo (seppur superficialmente) la struttura di un file system e come opera su una partizione mi verrebbe da dire che è impossibile leggerla se la partizione ne è priva.
:mbe: è impossibile leggere la struttura dei files e il loro contenuto, ma il contenuto raw della partizione si, lo puoi leggere (andando così a leggere anche i dati del file system, che rientra nelle intenzioni iniziali di Furla).

sirus
20-07-2006, 08:22
...
da notare come gli oggetti di Windows NT siano Securable Objects, ovvero possano essere associati ad un descrittore di sicurezza; ciò permette tra le altre cose di proteggere l'accesso all'hardware con la stessa immane flessibilità che caratterizza tutto il sistema di sicurezza di Windows. come al solito di default è tutto aperto :D :stordita: :mc:
...
Non dirlo a tutti :ops:

Per il resto (che non ho quotato per non appesantire il thread) :eek:
:ave: 71104

Furla
20-07-2006, 08:57
dunque, il problema era questo:

niente da fare, non ne trovo nessuno che fa quello che serve a me! tutti i programmi che provo fanno un'immagine che contiene solo la parte utilizzata della partizione, la parte vuota viene ignorata... e i miei files sono proprio nella parte che per il file system è vuota


bypassando il fs, come spiegato da 711 :D, dovrei essere in grado di accedere alla parte "vuota" del volume logico/fisico, ovvero quella che per il fs non contiene dati.


i files erano abbastanza importanti, sicuramente se fossi ripartito dai backup li avrei già come se non li avessi mai persi :D
comunque non ho molta fretta, e ormai voglio imparare... "la meta è solo una scusa per affrontare il viaggio".


oggi pomeriggio vedo di buttare giù qualcosa sulla base di tutte le preziose nozioni che mi avete dato ;)

Furla
20-07-2006, 16:33
:ave: 71104
mi associo, spero fra qualche anno di arrivare ai tuoi livelli :eek:

Furla
20-07-2006, 17:45
dunque, vediamo se vado bene:

FILE *stream;
char list[4096];


if( (stream = fopen( "\\\\.\\D:", "r+t" )) != NULL )
{
numread = fread( list, sizeof( char ), 4096, stream );
printf( "Contents of buffer = %.4096s\n", list );
else
printf( "File could not be opened\n" );

così dovrei leggere i primi 4 kb della partizione, giusto?

e per leggere i successivi 4 kb devo fare la stessa cosa aumentando di 4096 il puntatore stream...


troppo facile per essere così... cosa non ho capito? :D

71104
20-07-2006, 18:36
ok, allora per prima cosa 4 kb non fa 4192 ma 4096 :p
io per semplicità lo scrivo sempre in esadecimale, che è 0x1000 e fa cifra tonda ^^ (non è un caso ovviamente, fa cifra tonda sia in binario che in base 16 perché è una potenza di due)

poi, in generale nella programmazione è buona pratica deallocare risorse di qualsiasi tipo non appena smetti di usarle; in altre parole, hai scordato la fclose ;)

poi ho visto che hai usato a un certo punto un sizeof(char), ma è inutile perché sizeof per definizione ritorna la dimensione di ciò che sta tra parentesi espressa in char, non in bytes :)
quindi aldilà del fatto che un char occupa un solo byte sulla maggioranza delle architetture, l'espressione sizeof(char) ritornerà sempre 1 anche su una ipotetica architettura dove char occupa 2 bytes

per il resto tutto ok: il programma legge i primi 4192 raw bytes (o char, che dir si voglia :p) dell'unità D: e li stampa sulla console. ovviamente se qualcuno di questi 4192 bytes è uno zero i bytes non verranno stampati tutti perché la printf vuol stringhe NULL-terminated, cioè si ferma quando trova uno 0; tutti i caratteri successivi perciò non andranno sulla console.

71104
20-07-2006, 18:38
ah una cosa: non ricordo come funzionasse il secondo parametro della fopen, ma come mai usi "r+t" anziché solo "r"?

Furla
20-07-2006, 20:32
lol vedi che succede a fare a mente 'sti calcoli? ora correggo^^

sì con binario, esadecimale, potenze di 2, ecc mi ci ritrovo, come si fa a fargli accettare un valore in hex? basta scrivere prima del valore "0x"?

secondo msdn, "t" serve ad avere la lettura in formato testo, scambia i CRLF con dei LF semplici in lettura, e viceversa in scrittura. non so a cosa serva, ho parzialmente fatto copia e incolla dagli esempi nelle pagine msdn :D

per il sizeof(char) non ho capito bene, in pratica mi dici che avendo sempre 1 come ritorno (visto che le variabili char occupano un carattere) posso metterci uno e tagliare la testa al toro? comunque anche questa l'ho presa pari pari dall'esempio su msdn, visto che non sapevo bene cosa fosse l'ho lasciata com'è :D

EDIT: comunque msdn dice "The sizeof operator gives the amount of storage, in bytes, required to store an object of the type of the operand."

comunque con il codice che ho postato non ho bisogno di malloc, vero?

andbin
20-07-2006, 21:55
poi ho visto che hai usato a un certo punto un sizeof(char), ma è inutile perché sizeof per definizione ritorna la dimensione di ciò che sta tra parentesi espressa in char, non in bytes :)
quindi aldilà del fatto che un char occupa un solo byte sulla maggioranza delle architetture, l'espressione sizeof(char) ritornerà sempre 1 anche su una ipotetica architettura dove char occupa 2 bytesMa ... LOL. No, sizeof ritorna la dimensione in bytes!! Se per ipotesi su un sistema il char fosse di 16 bit, ritornerebbe 2!!!

sirus
20-07-2006, 21:58
lol vedi che succede a fare a mente 'sti calcoli? ora correggo^^

sì con binario, esadecimale, potenze di 2, ecc mi ci ritrovo, come si fa a fargli accettare un valore in hex? basta scrivere prima del valore "0x"?
Se volessi assegnare il carattere con valore ASCII 0 alla variabile C usando hex farei:
char c = '\x0' ;

secondo msdn, "t" serve ad avere la lettura in formato testo, scambia i CRLF con dei LF semplici in lettura, e viceversa in scrittura. non so a cosa serva, ho parzialmente fatto copia e incolla dagli esempi nelle pagine msdn :D
Se non erro t è implicito ma IMHO per una lettura di basso livello meglio usare r+b che implica formato binario.

per il sizeof(char) non ho capito bene, in pratica mi dici che avendo sempre 1 come ritorno (visto che le variabili char occupano un carattere) posso metterci uno e tagliare la testa al toro? comunque anche questa l'ho presa pari pari dall'esempio su msdn, visto che non sapevo bene cosa fosse l'ho lasciata com'è :D
la funzione sizeof() ritorna la quantità di byte che occupa il tipo di dato passato come parametro (funziona anche con tipi di dato definiti dal programmatore) oppure se il programmatore ha definito ed usato una union ritorna la dimensione della variabile a seconda del valore usato della union (che è una struttura dati multi tipo).

EDIT: comunque msdn dice "The sizeof operator gives the amount of storage, in bytes, required to store an object of the type of the operand."

comunque con il codice che ho postato non ho bisogno di malloc, vero?
Non ti serve perché hai definito un array da 4k cosa che comunque eviterei, è preferibile usare la heap per queste cose IMHO quindi malloc non va proprio scartata.
Io correggerei così:
FILE *stream;
char *data;
int _read;

if((stream = fopen("\\\\.\\D:","r+b")) != NULL) {
data = (char)malloc(4096 * sizeof(char));
_read = fread(data,sizeof(char),4096, stream);
if(_read != 4096)
printf("\n%d != 4096\n",_read);
printf("Contents of buffer = %.4096s\n",data);
} else
printf("\nFile could not be opened\n");
al termine chiudi il file e libera la memoria allocata con free(data)! :) :)

71104
21-07-2006, 00:24
ehm :huh:

perdonatemi la cazzata della sizeof(char) :huh:

mi pareva di averla letta proprio qui su HWU... :mbe:

sirus
21-07-2006, 09:34
ehm :huh:

perdonatemi la cazzata della sizeof(char) :huh:

mi pareva di averla letta proprio qui su HWU... :mbe:
:nonsifa:



:Perfido:



gli errori capitano anche ai migliori :cool:

Furla
21-07-2006, 11:38
FILE *stream;
char *data;
int _read;

if((stream = fopen("\\\\.\\D:","r+b")) != NULL) {
data = (char)malloc(4096 * sizeof(char));
_read = fread(data,sizeof(char),4096, stream);
if(_read != 4096)
printf("\n%d != 4096\n",_read);
printf("Contents of buffer = %.4096s\n",data);
} else
printf("\nFile could not be opened\n");

ok, non capisco bene a cosa serva la variabile _read (l'underscore vuol dire qualcosa di particolare?), anche perché non riesco a trovare nulla sul printf e su tutti quegli strani simboli che ci hai messo... qualcuno mi sa linkare qualcosa? msdn dice addirittura che non trova nulla :eek:

andbin
21-07-2006, 13:05
ok, non capisco bene a cosa serva la variabile _read (l'underscore vuol dire qualcosa di particolare?)No, non vuol dire nulla di particolare.

anche perché non riesco a trovare nulla sul printf e su tutti quegli strani simboli che ci hai messo... qualcuno mi sa linkare qualcosa? msdn dice addirittura che non trova nulla :eek:Non usare printf per stampare un blocco di dati binari!!! Rischieresti: a) di stampare caratteri e simboli incomprensibili b) se nel blocco di dati c'è il carattere nullo '\0', la stringa ... termina lì.

Quando fai la malloc devi mettere il cast (char*) e non (char).

Furla
21-07-2006, 14:35
Non usare printf per stampare un blocco di dati binari!!! Rischieresti: a) di stampare caratteri e simboli incomprensibili b) se nel blocco di dati c'è il carattere nullo '\0', la stringa ... termina lì.
certo che non lo uso, io i bytes li devo solo comparare con quelli di una stringa in input... volevo solo capire cosa stamperebbe di preciso questo:

if(_read != 4096)
printf("\n%d != 4096\n",_read);
printf("Contents of buffer = %.4096s\n",data);

in particolare a cosa servono all'interno di printf "\n%d != 4096\n" (una comparazione? stampa il numero di bytes letti se non sono 4k?) e "%.4096s\n" (dopo il punto non si indica il numero di cifre decimali?).

se qualcuno mi linkasse una paginetta esaustiva su printf e codici vari da usare al suo interno gliene sarei estremamente grato (per ora ho trovato solo la guida di html.it ma è un po' approssimativa su questa parte) :D


Quando fai la malloc devi mettere il cast (char*) e non (char).

cast?!? :mbe:

cos'è?^^

andbin
21-07-2006, 16:27
volevo solo capire cosa stamperebbe di preciso questo:

if(_read != 4096)
printf("\n%d != 4096\n",_read);
printf("Contents of buffer = %.4096s\n",data);

in particolare a cosa servono all'interno di printf "\n%d != 4096\n" (una comparazione? stampa il numero di bytes letti se non sono 4k?) e "%.4096s\n" (dopo il punto non si indica il numero di cifre decimali?).Se _read fosse diverso da 4096 (es. 1000), la prima printf stamperebbe semplicemente 1000 != 4096. Tutto qua.

Il '.' con lo specificator 's' in effetti è la prima volta che lo vedo. :eek: Lo si usa in genere con i valori numerici floating-point es. %4.2f.
Per le stringhe non credo che serva a qualcosa, anche se non ne sono completamente sicuro. ;)


cast?!? :mbe:

cos'è?^^L'operazione di casting consente di effettuare una conversione esplicita, in modo forzato, da un tipo ad un altro.
Quando si usa il casting esplicito, è il programmatore che si deve assumere la responsabilità di quello che sta facendo con quel cast. ;)

sirus
21-07-2006, 17:41
Per il cast ha ragione andbin va castato a (char*) non a (char), per la printf che ho inserito ha già spiegato tutto andbin.
La struttura %s.4096 come gli altri non so per cosa possa stare, l'ho copiata ed incollata dal tuo codice.

Furla
22-07-2006, 09:32
ah, allora il cast è il tipo di variabile che leggo nello spazio allocato con malloc, indipendentemente dalla sua provenienza...

vediamo se ho capito bene come funziona la malloc: il ritorno (la variabile data, nel nostro caso) ora è un puntatore che uso per muovermi all'interno dello spazio allocato con malloc (ma cosa punta? il primo byte/la prima variabile dello spazio allocato?).



per il %.4096s\n io l'ho trovato qui (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/_crt_fread.asp)


if( (stream = fopen( "fread.out", "r+t" )) != NULL )
{
/* Attempt to read in 25 characters */
numread = fread( list, sizeof( char ), 25, stream );
printf( "Number of items read = %d\n", numread );
printf( "Contents of buffer = %.25s\n", list );
fclose( stream );
}


Output
Number of items read = 25
Contents of buffer = zyxwvutsrqponmlkjihgfedcb

71104
22-07-2006, 17:10
La struttura %s.4096 come gli altri non so per cosa possa stare, l'ho copiata ed incollata dal tuo codice. determina la precisione; nel caso delle stringhe vuol dire che la printf si ferma al 4096esimo carattere se ancora non ha trovato il NULL

andbin
22-07-2006, 17:30
determina la precisione; nel caso delle stringhe vuol dire che la printf si ferma al 4096esimo carattere se ancora non ha trovato il NULLÈ vero. :doh:
Bastava pensarci ... altrimenti se in quel buffer di 4096 bytes non ci fossero dei '\0', continuerebbe a stampare chissà cosa ...

sirus
05-08-2006, 18:28
determina la precisione; nel caso delle stringhe vuol dire che la printf si ferma al 4096esimo carattere se ancora non ha trovato il NULL
Grazie! :p

Furla
20-09-2006, 14:10
Ciao a tutti!!!

scusate, ma tra vacanze, lavoro, iscrizione all'uni, problemi alla macchina, ecc... stavo per dimenticare di dirvi che ho finito il programma e recuperato i files di cui avevo bisogno!

mille grazie a tutti coloro che mi hanno aiutato partecipando al thread, in particolare a sirius, andbin e sopra tutti 71104, è stato un onore seguire i vostri consigli (e non lo dico tanto per dire)!

71104
20-09-2006, 15:07
l'hai finito?? :eek:
vogliamo assolutamente vedere i sorgenti prodotti dal nostro allievo preferito!!! :D :D :D

posta posta su!! :D

a proposito: ma alla fine ha funzionato effettivamente aprire il "raw disk" col mio sistema? perché una volta anche io ho avuto il problema descritto da andbin, solo che poi miracolosamente non l'ho più avuto... :confused:

mannaggia che non ho controllato GetLastError quando l'ho avuto :muro:

Furla
20-09-2006, 20:04
ecco il sorgente:

#include <iostream>
#include <stdlib.h>
#include <stdio.h>

using namespace std;

FILE *stream;

int main()
{
if( (stream = fopen( "\\\\.\\H:", "r+b" )) == NULL )
//if( (stream = fopen( "C:\Clienti.txt", "r+b" )) == NULL )
printf( "The file 'data' was not opened\n" );
else {
printf( "The file 'data' was opened\n" );


char *string;
int numread;

char sequence[4][11]={"frmClienti", "cmdAzione", "txtcampo", "RSClienti"};
//int back[4][11] = {{0,0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0,0},}; <- algoritmo di ricerca avanzato
int pointer[4] = {0,0,0,0};

string = (char *)malloc(0x800*sizeof(char));
if (string == NULL)
printf("null");
else {

FILE *stream2;

if( (stream2 = fopen( "c:\data2.txt", "a+" )) != NULL ){
printf( "The file 'data2' was opened\n" );

char found = 'f';

do {
numread = fread(string, sizeof( char ), 0x800, stream );

for (int i = 0; i < numread; i++) {
for (int qwe = 0; qwe < 1; qwe++) {

if (*(string+i) == sequence[qwe][pointer[qwe]]) {
pointer[qwe]++;
if (sequence[qwe][pointer[qwe]] == '\0') {
printf("%d ", qwe);
printf("%d\n", i);
found ='t';
pointer[qwe] = 0;
}
} else
//pointer[qwe] = back[qwe][pointer[qwe]]; <- algoritmo di ricerca avanzato
pointer[qwe] = 0;

}
}
if (found == 't'){
int numwritten = fwrite( string, sizeof( char ), numread, stream2 );
numwritten = fwrite( "\n\n\n", sizeof( char ), 3, stream2 );
found = 'f';
}
} while (numread == 0x800);

}
}
fclose( stream );
free( string );

}
system("PAUSE");
return 0;
}


spiego brevemente cosa fa, per approfondimenti sul funzionamento rimando a dopo cena, se vi interessa :D

il programma prende uno spezzone da 2kB della partizione alla volta e lo mette nello spazio allocato con la malloc (ho scelto questa dimensione perché su msdn dice che viene allocato più spazio di quello richiesto, che serve al sistema... metà pagina l'ho lasciata a lui, tanto non avevo fretta :)).

poi inizia la ricerca di alcune parole, quelle più ricorrenti nel codice che cerco, e che contemporaneamente si possono presentare con poca probabilità da altre parti dell'hd (i nomi degli oggetti, in pratica... era un sorgente in vb6).

se nello spezzone è presente almeno una delle stringhe che cerco, lo salva tutto in un file e aggiunge un po' di spazio per far capire dove finisce e dove inizia quello dopo.

alla fine entro in gioco io: apro comodamente il file, prendo gli spezzoni "interessanti" salvativi dal programma e faccio un bel collage, qualche secondo di esultanza, infine copio i files recuperati su tutte le partizioni di tutti gli hd che ho in casa :p


nel sorgente che ho postato c'è anche un parte di codice commentata, sono righe da sostituire a quelle appena sottostanti per fare un algoritmo un po' migliore che cerca l'inizio della stringa da cercare all'interno di se stessa, in modo da non saltare proprio nulla. in questo caso non serviva, ma ho in mente un progettino in cui devo cercare una sequenza binaria all'interno di un file, e direi che a quel punto diventa indispensabile...

ripeto, se interessa spiego tutto poi perché ora ho fame :D

thebol
20-09-2006, 20:55
veramente complimenti, sia a te, sia a chi ti ha aiutato :)

71104
20-09-2006, 22:09
questo sì che sarebbe un thread da mettere in rilievo, è qualcosa di esemplare IMHO...

cmq, Furla, c'è una cosa che non mi torna: come mai nel sorgente i nomi dei files hanno un solo slash dopo la lettera dell'unità? tipo "c:\data2.txt"... scritto così non può funzionare...

Furla
20-09-2006, 23:00
:mc: :muro:

ora ho capito perché mi funzionava solo usando nomi di files con percorso "C:\nomefile" :muro:

:muro: :doh:

ora ho capito perché devc++ mi diceva ad ogni compilazione "unknown escape sequence" :muro:


probabilmente il compilatore si rendeva conto dell'errore, lasciava uno "Warning" nel log di compilazione e tirava a dritto :D
vabbè dai, la prox volta me lo ricorderò :D

71104
21-09-2006, 00:39
lol, cioè tu praticamente facevi andare il programma e poi andavi ad aprire il file C:\ata2.txt ? :D

ma lol ^^

babbuò, sappilo per il futuro: lo slash nelle stringhe in C serve a fare le escape sequences, perciò se quello che vuoi scrivere nella stringa non è una escape sequence ma proprio uno slash, devi metterlo doppio. e vale solo per il backslash, non per gli slash in avanti. ;)

Furla
21-09-2006, 07:43
nono, il file si chiamava proprio data2.txt, è per quello che non mi sono reso conto dell'errore (che poi 'sta cosa del doppio slash nelle stringhe in c me l'avevi accennata anche nella prima pagina, mi pare). solo che non potevo scegliere di metterlo in una cartella diversa in c:, né in un'altra partizione.

tra l'altro, prima di applicarlo alla partizione "maledetta" ho usato, per provare l'algoritmo, i sorgenti di backup, e funzionava tutto benissimo con uno slash solo, a patto che li spostassi in c:\ per farglieli leggere.

boh, secondo me è il compilatore che, non riconoscendola come escape sequence "capiva" che era un path e lo usava come tale, dicendomi di correggere ma continuando a compilare... ho usato l'ultima versione di DevC++, essendo una beta (lo so che non si dovrebbe... ormai avevo quella) ho pensato che fosse un bug a generare quegli avvisi, visto che alla fine il programma partiva tranquillamente :D