Newsgroup: it.comp.programmare.win32
Titolo: Cancellare un file

Ciao a tutti...
mi servirebbe un aiutino...
utilizzando le api in c++, dovrei cancellare un file. Fin qui niente
di difficile, il file riesco a cancellarlo. Ma se poi sottopongo il
dischetto che conteneva il file ad un programma di recupero files, il
file mi viene trovato, per cui mi č anche possibile ripristinarlo.
Esiste qualche api che me lo cancella definitivamente, in modo che non
possa essere piů ritrovato?
Grazie per l'eventuale risposta...

possa essere più ritrovato?
Sovrascrivilo e poi cancellalo.  Farai in modo che possa essere
ritrovato, ma che sia comunque illeggibile.  C'è solo una remota
possibilità che si possa ancora leggere il suo contenuto, affidandosi
a costosissimi macchinari che rilevano le tracce analogiche delle
scritture sul disco, ma quanto sei realmente preoccupato di questo ?
;-)

 
Per evitare che sia rileggibile basta sovrascriverlo un bel po' di 
volte, meglio se con pattern che assicurino che tutti i bit siano 
variati un buon numero di volte (evitando, ad esempio, di scrivere 
tutti 0 o tutti 1), magari non in modo ripetibile (sto proponendo la 
generazione di fuffa randomica non troppo randomica, me ne rendo 
conto!). 
Mi pare che gli standard militari richiedano qualche decina di 
sovrascritture e i macchinari di cui parli, AFAIK, riescono a 
recuperare dati fino a 26 riscritture (però vado a memoria e una 
buona parte della mia memoria è ancora in ferie).
Però devi essere sicuro che riscrivendo il file il sistema operativo 
vada effettivamente a riscrivere quello specifico pezzo di disco. 
Questo potrebbe non essere vero se il filesystem riorganizza 
dinamicamente il disco (magari si tratta di un file piccolo tra due 
grandi blocchi contigui di spazio vuoto e il S.O. potrebbe spostarlo 
per avere più spazio per un eventuale file di grosse dimensioni 
oppure, al contrario, se si tratta di un file grosso, potrebbe 
spostarlo in un area consecutiva deframmentandolo durante la 
riscrittura). O, peggio, potrebbe averlo spostato _prima_ della tua 
cancellazione (in questo caso potrebbe essere possibile recuperarne 
una versione vecchia).
Per essere sicuro puoi solo provare a sovrascrivere tutto lo spazio 
su disco una volta cancellato il file (ovviamente questa soluzione 
può portare a tempi di cancellazione biblici!).
E'inoltre indispensabile che il file venga chiuso e riaperto tra due 
sovrascritture per evitare che la cache in scrittura del S.O. o un 
controller particolarmente furbo possano in qualche modo evitare le 
scritture fisiche.
Inoltre potrebbe essere necessario ripulire allo stesso modo lo 
swapfile se il file (o parti di esso) è stato caricato in memoria.
E, tra l'altro, se il file deve essere scritto e non solo cancellato 
da un programma del nostro amico, devi essere sicuro di aver 
memorizzato davvero il file su un disco magnetico e non su qualche 
marchingegno (flash, network storage o simili) che potrebbe gestire 
le scritture in modo completamente diverso.
-- 
Valter Minute
vmi...@inwind.it
 (the reply address of this message is invalid)

 vada effettivamente a riscrivere quello specifico pezzo di disco
il che si può cercare di risolvere riempendo completamente il disco :-) 
un po' di codice che scrissi allo scopo, tempo fa:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define TRASHSIZE (8192)
int main(int argc, char * argv[])
{
 time_t tNow;
 FILE * pfTemp;
 static char a_cTrash[TRASHSIZE];
 register int i;
 (void)argc;
 /* seed the random number generator */
 time(&tNow);
 srand((unsigned)tNow);
 /* create the temporary file */
 pfTemp = tmpfile();
 if(!pfTemp)
 {
  perror(argv[0]);
  return 1;
 }
 /* unbuffered - write directly */
 setvbuf(pfTemp, NULL, _IONBF, 0);
 /* overwrite the file 3 times */
 for(i = 0; i < 3; i ++)
 {
  size_t nBufSize = TRASHSIZE;
  errno = 0;
  do
  {
   /* fill the file with garbage */
   do
   {
    register size_t j;
    /* create a buffer of pseudo-random garbage... */
    for(j = 0; j < nBufSize; j ++)
     a_cTrash[j] = (char)rand();
    /* ... and write it on the file */
    fwrite(a_cTrash, sizeof(a_cTrash[0]), nBufSize, pfTemp);
   }
   /* repeat until an error occurs */
   while(!errno);
   /* unexpected error */
   if(errno != ENOSPC)
   {
    perror(argv[0]);
    return 1;
   }
   /* device out of space - try halfing the buffer */
   nBufSize /= 2;
  }
  while(nBufSize >= 1);
  /* reset the file pointer and start over */
  if(fseek(pfTemp, 0, SEEK_SET))
  {
   /* unexpected error */
   perror(argv[0]);
   return 1;
  }
 }
 /* success */
 fclose(pfTemp);
 return 0;
}
-- 
  < 
http://www.reactos.com/
 >  Open source clone of Windows NT. Current
      Don't stand, REACT!      version 0.1.3. C, C++ and ASM developers
                               and beta testers are welcome!

 (void)argc;
Huh ??

 puň portare a tempi di cancellazione biblici!).
Tra l'altro, non č detto che il metodo funzioni con filesystem che 
assegnano una quota all'utente e, IMHO, potrebbe essere piů utile 
riempire il disco di tanti files di fuffa (ovviamente in modo da 
riempire a puntino i blocchi del filesystem) piuttosto che creare un 
solo file. Questo potrebbe permettere di evitare limitazioni sulla 
dimensione del file (se il pesce ha funzionato meglio del sidro, su 
9X non si puň andare oltre i 4GB) e confonderebbe anche le 
informazioni sui nomi file, cancellando cosě anche le tracce di 
un'esistenza passata del file (anche con contenuto irrecuperabile).
Se non č un problema comprare un disco nuovo, suggerirei soluzioni 
hardware basate su acidi e/o infiammabili e dispersione dei residui 
nel gange.


 Huh ??
Forse per non avere il warning "Unreferenced local variable" (o qualcosa
del genere)?
Non bastava argc; senza (void)?
Paolo.
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it

del genere)?
Ma chi insegna queste orribili tecniche ? E` orribile almeno quanto
leggere ancora "register".

 Ma chi insegna queste orribili tecniche ?
il mio codice è in C. Non è tanto orribile quanto *necessaria*. Il cast 
a void, comunque, secondo te perchè è permesso? sai, vero, cosa diventa 
un assert() quando la macro _NDEBUG è definita?


 Huh ??
sistema rapido, indolore, portabile, standard, compatibile all'indietro 
e soprattutto funzionante per evitare warning


e soprattutto funzionante per evitare warning
E` orribile ugualmente.  I warning non andrebbero messi a tacere.

il mio codice è in C. Non è tanto orribile quanto *necessaria*. 
Necessaria ? non è affatto indispensabile per il funzionamento del
codice ed è una tecnica orribile di annientamento dei warning (che
andrebbero sempre lasciati attivi).

 
Perche' dovrei tenermi i warning? Non bisogna sopprimere i warning
con switch al compilatore ma se il compilatore mi da un warning su
una riga di codice, la controllo, vedo che va bene cosi' com'e',
perche' non devo applicare alla stessa riga una tecnica per eliminare
il warning?
Anzi, nel momento in cui ti trovi qualche decina o qualche centinaio
di warning mi dici come ti accorgi se il compilatore te ne da' uno
nuovo? Direi che e' proprio l'opposto. Lasciare i warning e' sbagliato!
Ciao.
  -Ema-

 
IMHO i warning andrebbero sempre controllati. Però se si capisce che 
sono warning inutili (sempre IMHO) è meglio metterli a tacere, 
dicendo in modo più o meno esplicito al compilatore che abbiamo 
capito il suo avvertimento, ma che non ci possiamo/vogliamo fare 
nulla. 
Per evitare che si accumulino e vadano a rendere meno evidenti nuovi 
warning che magari sono più significativi o costringano qualche altro  
"manutentore" del codice a ripassarsi tutti i warning arrivando alla 
nostra stessa conclusione.
Quello dell'argomento non utilizzato all'interno di una funzione è un 
classico problema che può capitare quando ti trovi ad implementare 
una funzione che deve avere uno specifico header (perchè è definita 
in una classe base, perchè è parte di un'interfaccia COM, perchè deve 
essere esportata da un driver etc...), ma non usa uno o più dei dati 
che gli sono passati.


il warning?
Non ci siamo capiti.  Non sto dicendo che i warning non vadano
*controllati*, altrimenti che esistono a fare in quanto "warning" ?  
Sto dicendo che non bisogna inventarsi tecniche orribili per evitarli.
Il fatto che il compilatore indichi che non hai utilizzato argc non ti
deve portare a scrivere da qualche parte "(void)argc;", sai perché il
warning viene scatenato e lo tieni.

uno o più dei dati che gli sono passati.
Lo stai spiegando a me ?

 
Diciamo che mi rivolgevo ai miei tre lettori... :)
Ti facevo solo tre esempi di casi in cui ti trovi quel warning 
inutile. 
Tu come ti comporti in questi casi?
Sinceramente mi balza più all'occhio un warning in un programma che 
compilava "liscio" che trenta nuovi waning in un programma che ne 
segnalava già centodue (soprattutto se è un po' che non lo 
ricompilo).
Credo sia una questione di preferenze e di abitudini, però 
personalmente preferisco l'approccio adottato da Juliet. 
Magari con un commento che evidenzi che la riga "balzana" serve solo 
a evitare il warning.


Stiamo dicendo le stesse cose in due rami del thread. Seguo quello 
partito da Valter Minute che tra l'altro pare essere del mio stesso avviso.
Ciao.
  -Ema-

 warning viene scatenato e lo tieni.
ma ragazzi perche' in queste funzioni non lasciate solo il tipo definito
senza nome ??? e' standard e non da piu' quei warning e non dovete trovare
vie derivate per farli tacere ... no ??? tanto se quell'elemento non lo
usate lo definite solo anonimo ...
ciao

 Tra l'altro, raramente capita che un warning sia davvero inutile.
il massimo che avrei fatto con argc sarebbe stato un assert(argc >= 1), 
ma era un programma piccolo e richiedeva una soluzione piccola. Quindi, 
per piacere, piantala. Stai montando un caso su una cazzata, per di piů 
con argomentazioni discutibili


 andrebbero sempre lasciati attivi).
ma *sono* attivi. E' per questo che ho scritto (void)argc. Per vedere i 
*veri* warning


 fa alcun danno ed è perfettamente standard
Fare altrimenti sarebbe ben piu` sbagliato. Il risultato di un
assegnamento e` dello stesso tipo dell'l-value, mentre le condizioni
dovrebbero sempre essere espresse tramite booleani. Nei linguaggi piu`
tipizzati del C (ossia quasi tutti), una forma del tipo if(a = b)
darebbe semplicemente errore.
-- 
Lorenzo

darebbe semplicemente errore.
Perche'?
Sul vc7 questo compila e funziona correttamente:
int main(void)
{
	int a = 2;
	int b = 3;
 
	if (a = b)
		std::cout << a;
	return 0;
}
Viene stampato 3, come e' giusto che sia.
-- 
ciao, hal

 Sul vc7 questo compila e funziona correttamente:
Perche` il C++ e` un pochino piu` tipizzato del C, ma ancora mooolto
poco. Se ad esempio compili la stessa cosa sotto Java, ti sara`
segnalato un errore.
In ogni caso mi sembra che il Visual C++ almeno ti dia un warning... o
no?
-- 
Lorenzo

no?
Premesso che nella vita reale non ci penso neanche lontanamente a
scrivere codice in quel modo (quando lo riprendi dopo qualche mese non
ci capisci piu' un accidente), il vc7 ha compilato senza fare una
piega:
------ Rebuild All started: Project: Test, Configuration: Debug Win32
------
Deleting intermediate files and output files for project 'Test',
configuration 'Debug|Win32'.
Compiling...
Test.cpp
Linking...
Build log was saved at "file://d:\Prj\C++\Test\Debug\BuildLog.htm"
Test - 0 error(s), 0 warning(s)
---------------------- Done ----------------------
    Rebuild All: 1 succeeded, 0 failed, 0 skipped
-- 
ciao, hal