[C] 'Opschonen' van je hd: problemen met fwrite()

Pagina: 1
Acties:
  • 220 views sinds 30-01-2008
  • Reageer

  • Xorgye
  • Registratie: Maart 2005
  • Laatst online: 05-10-2024
De meeste tweakers kennen het vast wel: gegevens worden op je hd zo achter gelaten dat eigenlijk alleen de verwijzing naar het bestand is gewist maar de gegevens nog gewoon aanwezig zijn.

Omdat ik niet van het idee houd dat gegevens toch zichtbaar blijven had ik in msdos met qbasic een programmatje gemaakt dat de hd 'wiped'. Schoonmaakt dus. Dat deed die door telkens achter elkaar een reeks van 3200 tekens met daarin allemaal 0'llen naar de hd te schrijven tot je een bestand van 4GB had, n nieuw bestand maken en dat doen totdat de hd vol was...

Dat werkte best leuk, alleen nu ben ik me broncode kwijt en wil ik toch een nieuwe maken die namelijk wat vaker over de gegevens heen schrijft. Het blijkt dat men tot 7x terug de bits kan vinden die op de hd hebben gestaan omdat de machnetische velden op de hd zich niet alleen beperken tot de ruimte waar de 'bit' staat maar ook er omheen voor magnetische velden zorgen...

Dus ik vogel ff een programma in elkaar met t volgende principe:

C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
char buffer[8][1];
buffer[0][0] = 13;
//etc etc etc tot buffer[7][0] = 0;
fpos_t bestandsgrootte;
FILE *bestand;

bestand = fopen("bestandsnaam", "wb");
while(!(ferror(bestand)))
{
  for(int hexvalue = 0; hexvalue < 8; hexvalue++)
  {
    fsetpos(bestand, &bestandsgrootte);
    fwrite(&buffer[hexvalue], 1, 32000, bestand);
  }
}


Om een rare reden wil dit niet vlotten en blijkt ie tijdens runtime via perror() een error te geven die zegt dat ergens iets mis is als ie fwrite doet.
Dat was opgelost toen ik de dimensie uit 'buffer' weg haalde... maar toen moest ik dus 8x de lus herhalen.

Daarnaast bedacht ik mij dus ook dat de meeste HD's een behoorlijke cache hebben, tegenwoordig al zo'n 8 tot 16 MB. Ik moet dus wel een mb of 32 schrijven voordat ik opnieuw over dezelfde positie heen schrijf om te voorkomen dat hij in de cache ging herschrijven.
Dit deed ik door om de fwrite() nog een for() te zetten die zich 1000x herhaalde.

Maar wat schetste mijn verbazing toen ik een bestand van 300mb had maar er achter kwam dat er allemaal gegevens in stonden. Nix niet leeg met allemaal 0'llen... r stond een zich telkens herhalende boodschap in...

K zet de code van me 1e versie hier maar neer, t is erg simpel gehouden en was vooral bedoelt als 'beginttest'. De optimalisatie komt wel als t principe werkt...

C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
#define SCHRIJFBLOK                                         4096
#define OMZIJLSCHRIJFBUFFER                                 16000

#define WIPETYPE_SIMPLE                                     1
#define WIPETYPE_GOOD                                       2
#define WIPETYPE_ULTRA                                      3


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

int main()
{
    char reeks[10], wipebestandsnaam[20];
    int wipetype;
    int station;
    bool gadoor = true;
    bool schijferror = false;
    bool schijfvol = false;
    FILE *wipebestand;
    int bestandsnummer = 0;
    time_t begintijd, huidigetijd, haaltijd;
    long schrijfsnelheid;
    int teller;

    //gegevens om file mee vol te schrijven:
    srand(time(NULL));
    char buffer1[2], buffer2[2], buffer3[2], buffer4[2], buffer5[2], buffer6[2], buffer7[2], buffer8[2];
    buffer1[0] = 17;
    buffer2[0] = 133;
    buffer3[0] = 255;
    buffer4[0] = 0;
    buffer5[0] = 238;
    buffer6[0] = 166;
    buffer7[0] = rand()%256;
    buffer8[0] = 0;


    unsigned long int geschreven_mbytes, geschreven_bytes;
    fpos_t bestandsgrootte;

    while(gadoor)
    {
        //vraag om de type 'wipe'
        while(!(reeks[0] == '0'+WIPETYPE_SIMPLE || reeks[0] == '0'+WIPETYPE_GOOD || reeks[0] == '0'+WIPETYPE_ULTRA))
        {
            printf("\n--- Wipe free space ---\n");
            printf("(1) Simple wipe (HEX 00)\n");
            printf("(2) Good wipe (HEX 11 | HEX 85 | HEX FF | HEX 00)\n");
            printf("(3) Ultra wipe (HEX 11 | HEX 85 | HEX FF | HEX 00 | HEX EE | HEX A6 | HEX rand | HEX 00)\n");
            scanf("%1s", &reeks);
        }
        wipetype = reeks[0];

        //lees een stationsnaam in
        while(!((reeks[0] >= 'a' && reeks[0] <= 'z') || (reeks[0] >= 'A' && reeks[0] <= 'Z')))
        {
            printf("\nSpecificeer station: ");
            scanf("%1s", &reeks);
        }

        station = reeks[0];

        geschreven_bytes = 0;
        geschreven_mbytes = 0;
        schijfvol = false;
        schijferror = false;
        //ga in de lus die telkens achter elkaar bestanden van 4gb maakt
        while(schijfvol == false && schijferror == false)
        {
            //construeer de bestandsnaam
            wipebestandsnaam[0] = station;
            wipebestandsnaam[1] = 0;
            strcat(wipebestandsnaam, ":\\wipe");
            sprintf(reeks, "%04i", bestandsnummer);
            strcat(wipebestandsnaam, reeks);
            strcat(wipebestandsnaam, ".big");

            //open het bestand
            wipebestand = fopen(wipebestandsnaam, "wb");
            if(wipebestand == NULL)
            {
                schijferror = true;
                break;
            }

            bestandsgrootte = 0;
            begintijd = time(NULL);
            huidigetijd = begintijd;
            schrijfsnelheid = 0;
            //ga het bestand vol schrijven
            while(bestandsgrootte < 4000000000)
            {
                //schrijf en herschrijf data naar bestand, doe telkens +- 200MB zodat je niet te maken krijgt met de
                //hd buffer die gegevens voor je gaat bufferen...
                for(teller = 0; teller < OMZIJLSCHRIJFBUFFER; teller++)
                {
                    fwrite(&buffer1, 1, SCHRIJFBLOK, wipebestand);
                }
                if(wipetype == WIPETYPE_GOOD || wipetype == WIPETYPE_ULTRA)
                {
                    fsetpos(wipebestand, &bestandsgrootte);
                    for(teller = 0; teller < OMZIJLSCHRIJFBUFFER; teller++)
                    {
                        fwrite(&buffer1, 1, SCHRIJFBLOK, wipebestand);
                    }
                    fsetpos(wipebestand, &bestandsgrootte);
                    for(teller = 0; teller < OMZIJLSCHRIJFBUFFER; teller++)
                    {
                        fwrite(&buffer2, 1, SCHRIJFBLOK, wipebestand);
                    }
                    fsetpos(wipebestand, &bestandsgrootte);
                    for(teller = 0; teller < OMZIJLSCHRIJFBUFFER; teller++)
                    {
                        fwrite(&buffer3, 1, SCHRIJFBLOK, wipebestand);
                    }
                    fsetpos(wipebestand, &bestandsgrootte);
                    for(teller = 0; teller < OMZIJLSCHRIJFBUFFER; teller++)
                    {
                        fwrite(&buffer4, 1, SCHRIJFBLOK, wipebestand);
                    }
                }
                if(wipetype == WIPETYPE_ULTRA)
                {
                    fsetpos(wipebestand, &bestandsgrootte);
                    for(teller = 0; teller < OMZIJLSCHRIJFBUFFER; teller++)
                    {
                        fwrite(&buffer5, 1, SCHRIJFBLOK, wipebestand);
                    }
                    fsetpos(wipebestand, &bestandsgrootte);
                    for(teller = 0; teller < OMZIJLSCHRIJFBUFFER; teller++)
                    {
                        fwrite(&buffer6, 1, SCHRIJFBLOK, wipebestand);
                    }
                    fsetpos(wipebestand, &bestandsgrootte);
                    for(teller = 0; teller < OMZIJLSCHRIJFBUFFER; teller++)
                    {
                        buffer7[0] = rand()%256;
                        fwrite(&buffer7, 1, SCHRIJFBLOK, wipebestand);
                    }
                    srand(time(NULL));
                    fsetpos(wipebestand, &bestandsgrootte);
                    for(teller = 0; teller < OMZIJLSCHRIJFBUFFER; teller++)
                    {
                        fwrite(&buffer8, 1, SCHRIJFBLOK, wipebestand);
                    }
                }

                //hou de tellers bij
                bestandsgrootte += SCHRIJFBLOK * OMZIJLSCHRIJFBUFFER;
                geschreven_bytes += SCHRIJFBLOK * OMZIJLSCHRIJFBUFFER;
                if((geschreven_bytes / 1000000) > 1)
                {
                    geschreven_mbytes += (geschreven_bytes / 1000000);
                    geschreven_bytes = geschreven_bytes - (geschreven_bytes / 1000000) * 1000000;

                    haaltijd = time(NULL);
                    if(haaltijd > huidigetijd)
                    {
                        huidigetijd = haaltijd;
                        schrijfsnelheid = bestandsgrootte / (huidigetijd - begintijd) / 1000000;
                        printf("[%u.%u] [%liMb/s]\n", geschreven_mbytes, geschreven_bytes, schrijfsnelheid);
                    }
                }

                //kijk of schijf vol is
                if(ferror(wipebestand))
                {
                    perror ("This error has occurred");
                    schijfvol = true;
                    break;
                }
            }

            fclose(wipebestand);
        }

        //verwijder alle gemaakte bestanden
        for(int x = 0; x <= bestandsnummer; x++)
        {
            //construeer de bestandsnaam
            wipebestandsnaam[0] = station;
            wipebestandsnaam[1] = 0;
            strcat(wipebestandsnaam, ":\\wipe");
            sprintf(reeks, "%04i", x);
            strcat(wipebestandsnaam, reeks);
            strcat(wipebestandsnaam, ".big");

            //verwijder het bestand
            remove(wipebestandsnaam);
        }

        if(schijfvol == true)
        {
            printf("\n\nDe %c schijf is klaar\n", station);
            gadoor = false;
        }

        if(schijferror == true)
        {
            printf("\n\nDe %c schijf kan niet worden aangesproken\n", station);
        }
    }

    return 0;
}

  • XTerm
  • Registratie: Juli 2001
  • Laatst online: 10-06-2025
Dat van die gegevens terug halen is trouwens niet meer van toepassing op nieuwe schijven. Daar is de
datadensiteit dermate dicht dat er te weinig residu is om de gewiste bit weer op te sporen.

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 19-02 20:38
Behalve de hardware cache van de harde schijf heb je ook te maken met de disk cache van het besturingssysteem en de file buffers die de C library gebruikt. Los daarvan is de methode nogal dubieus omdat je niet direct bij de vrijgegeven data kan, maar er vanuit gaat dat je die 'automatisch' overschrijft simpelweg door de harde schijf te vullen. Zelfs als je daarmee alle 'data' gebieden van de partitie bereikt (wat niet gezegd is) is er een grote kans dat er allerlei metadata (bestandsnamen, etc.) behouden blijft, omdat je daar simpelweg niet overheen kunt schrijven met functies die op bestandssysteemnivo werken.

Maar dat terzijde, de kern van je probleem wordt al duidelijk uit je eerste stuk code. Als je met fwrite een buffer van 32000 bytes wil schrijven, dan moet die buffer ook 32000 bytes groot zijn! Jij gaat er blijkbaar vanuit dat fwrite 32000 keer dezelfde byte schrijft (misschien doordat 'ie twee parameters krijgt: de grootte van een record en het aantal te schrijven records) maar dat is dus niet zo.

Als je 32000 keer een byte wil schrijven zul je dus ofwel 32000 fwrite moeten aanroepen met een 1-byte buffer, of eerst een grotere buffer moeten vullen met de gewenste bytes. (Het eerste is bijzonder traag, dus het tweede is een beter idee.)

Verder kan ik je aanraden om geen fwrite maar write te gebruiken omdat je immers geen prijs stelt op buffering door de C library, en fsync om geschreven buffers ook weg te schrijven aan het einde van de operatie. Dan nog doet je programma nauwelijks wat je er van verwacht; als je het mij vraagt kun je beter het hele idee laten varen.

  • Xorgye
  • Registratie: Maart 2005
  • Laatst online: 05-10-2024
Ik heb geprobeert dynamisch geheugen toe te wijzen en daarin een buffer te bouwen van 32kb. Als ik deze buffer dan met fwrite(*buffer, 32000, 1, bestand) weg schrijf mag dat. Alleen het probleem is weer dat hij raar reageert. Alsof je ergens niet van opaan kunt zodra je het groots aanpakt...

Maar een computer blijft echt een computer hoor! Dat ding voert uit wat je m zegt, vooral als je de HELE hd tot de laatste byte vol schrijft... dan kan je er van opaan dat nix over blijft. Het verbaast me dat ik er opeens niet meer van opaan kan terwijl hij toch echt letterlijk hoort te doen wat je vraagt...

Maar t kan idd met die buffer van C te maken hebben. Ik zat er dan ook aan te denken om iets op te zoeken waarmee je directer de hd aan kunt spreken. De schijfdefragmentatie programma's kunnen het ook, dus waarom ik niet?

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 19-02 20:38
De schijfdefragmentatieprogramma's gebruiken de Windows API en niet (alleen) de C library.

Wat bedoel je met 'raar reageren'? Ik denk dat je het gewoon nog steeds verkeerd doet (NOFI ;)) en dan hoort het ook niet te werken. :P Overigens is een 32 kilobyte buffer 32.768 bytes groot, niet 30.000 bytes.

  • PiepPiep
  • Registratie: Maart 2002
  • Laatst online: 17-11-2025
Als je echt zeker wilt weten dat er geen file buffers van windows ofzo tussen zitten kan je beter naar een dos opstart floppy zoeken en dan zelf via het bios alles wissen.
Hiervoor zou je wel zelf wat lowlevel code moeten schrijven om het bios aan te spreken en wis je de hele schijf ipv de data gebieden die op het moment niet in gebruik zijn.
Maar ik neem aan dat je een harddisk pas echt wilt leegmaken als je hem weg doet, en dan mag het hele filesystem er natuurlijk af.
Je kan met de extended int 13h functies de harddisk makkelijk aanspreken, je kan dan opvragen hoeveel sectoren groot hij is, dat is een 64 bits getal dus je kan tot 8589934592 TeraByte adresseren.
Als je zo de hele harddisk vol zet met 0'en, en eventueel met 1'en en nog een keer 0'en is alles toch zeker wel weg.

486DX2-50 16MB ECC RAM 4x 500MB Drive array 1.44MB FDD MS-Dos 6.22


  • Xorgye
  • Registratie: Maart 2005
  • Laatst online: 05-10-2024
*reactie op Soultaker*
Ik dacht dat een array 32kb max groot was... Of is t 'ouderwets' dat de char reeks max 2^16 (signed) dus 2^15 groot mag zijn?

En ik bedoel met 'raar' doen dat hij toch gegevens in mijn bestand laat staan terwijl er eigenlijk een egale reeks aan tekens in moet staan... geen fragmenten van wat dan ook...

Maar los van dat raden jullie dus aan niet met de standaart C functies dit te doen, maar gespecialiseerdere functies te gebruiken?

*reactie op PiepPiep*
Nou, ik wil er ook zeker van zijn dat me computer NU volledig vrij is van wat er 'vroeger' op stond... en idd kan je vanuit msdos als je de filesystem niet meer nodig hebt gewoon de hele bende van n floppy af gaan wissen... ff in de bios de 'virus warning' uitzetten ivm je bootsector en je kunt bezig :P

Maar mij gaat t r om dat je ook ff tussentijds een actie uit kunt voeren waardoor je zeker weet dat alleen de informatie die nu op je hd staat er nu op staat en nix anders :+

[ Voor 40% gewijzigd door Xorgye op 18-06-2006 22:13 . Reden: *reactie op bovenstaande toegevoegt* ]


  • Gomez12
  • Registratie: Maart 2001
  • Laatst online: 17-10-2023
Xorgye schreef op zondag 18 juni 2006 @ 22:10:
*reactie op Soultaker*
En ik bedoel met 'raar' doen dat hij toch gegevens in mijn bestand laat staan terwijl er eigenlijk een egale reeks aan tekens in moet staan... geen fragmenten van wat dan ook...

Maar los van dat raden jullie dus aan niet met de standaart C functies dit te doen, maar gespecialiseerdere functies te gebruiken?
Ik vermoed inderdaad dat deze 2 dingen met elkaar te maken hebben. Je hebt namelijk nog al wat soorten cache in dit geval :
1 : De C Fwrite cache
2 : De windows filesystem cache
3 : De hdd cache

En als er ergens in deze cyclus een stukje caching plaatsvind wordt er een gedeelte niet verwijderd ( plus dat ik me even af zit te vragen of een compiler niet ook een stuk uit je algoritme wegoptimaliseerd waardoor je caching nog meer om de hoek komt kijken. )

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 19-02 20:38
Dat is helemaal het probleem niet hier; die caches beïnvloeden niet wat er uiteindelijk in het bestand komt te staan. Ik denk dus dat Xorgye fwrite() verkeerd aanroept, of zijn buffer niet goed vult. De precieze oorzaak is moeilijk aan te wijzen zonder de relevante code te zien.

(En ja: in 32-bits Windows kun je grotere arrays dan 32kb alloceren - zelfs in 16 bits segmented memory kun je 64kb alloceren, en nog wel meer ook, maar dan wordt adressering alleen wat lastiger.)

  • Confusion
  • Registratie: April 2001
  • Laatst online: 01-03-2024

Confusion

Fallen from grace

Je wilt dus het *nix commando shred opnieuw bouwen? Ik zou zeggen: UTSL. :)

[ Voor 6% gewijzigd door Confusion op 19-06-2006 08:36 ]

Wie trösten wir uns, die Mörder aller Mörder?


  • Gomez12
  • Registratie: Maart 2001
  • Laatst online: 17-10-2023
Confusion schreef op maandag 19 juni 2006 @ 08:35:
Je wilt dus het *nix commando shred opnieuw bouwen? Ik zou zeggen: UTSL. :)
???UTSL???
Ehhm googelen is best moeilijk als je 2 letters omdraait...

Maar met goeie tekst kom ik uit op Use The Source, Luke... Weer wat geleerd.

@Kenneth. 2 letters omdraaien geeft niet zo veel zinnige resultaten, en omdat ik wel RTFM, UTFM ken maar deze niet echt beschaafd vind in een discussie was ik gewoon even benieuwd of dit wel vriendelijk was.

UTFM zie ik nu dat dat dus niet bekend is bij google, maar staat dus voor Use The F... Manual.

[ Voor 49% gewijzigd door Gomez12 op 19-06-2006 20:05 ]


  • kenneth
  • Registratie: September 2001
  • Niet online

kenneth

achter de duinen

Use The Source, Luke :)

Wat Google je ook had kunnen vertellen ;)

[ Voor 55% gewijzigd door kenneth op 19-06-2006 20:00 ]

Look, runners deal in discomfort. After you get past a certain point, that’s all there really is. There is no finesse here.

Pagina: 1