Page 1 of 2

WriteByte until FreeDiskSpace = 0 byte

Posted: Tue Aug 01, 2006 3:49 pm
by eJan
How to know when WriteByte is reached out of FreeDiskSpace. I have tried with PB code: http://www.purebasic.fr/english/viewtop ... 208#129208 but API work very slow - especialy for writing 4-5 gigabytes file (to fill free HD space with 0's for backup image).

Code: Select all

If CreateFile(0, "FREE_SPACE")
  
  For a=1 To 1
    Repeat
      WriteByte(0, 0) ; Write 0 byte to 'FREE_SPACE' file
    ForEver ; Until FreeDiskSpace = 0 byte
  Next
  
  CloseFile(0)
EndIf

Posted: Tue Aug 01, 2006 4:08 pm
by Kale
Why do you need to use code like this? Maybe it can be achieved in a nicer way?

Posted: Tue Aug 01, 2006 4:18 pm
by eJan
Kale wrote:Why do you need to use code like this? Maybe it can be achieved in a nicer way?
To fill free disk space with zeroes (most of wipe utilities works in that way: WinHex, SDelete: http://www.sysinternals.com/Utilities/SDelete.html, nullfile).

Posted: Tue Aug 01, 2006 5:04 pm
by dracflamloc
Why would you do it byte-wise, that will be slow.

You should do it with a large data chunk of zeros to speed it up.

Posted: Tue Aug 01, 2006 8:09 pm
by eJan
dracflamloc wrote:Why would you do it byte-wise, that will be slow.

You should do it with a large data chunk of zeros to speed it up.
Thanks for suggestion. I'm gonna measure the difference with time.

Posted: Tue Aug 01, 2006 8:46 pm
by Dreglor
It's cleaner and probably a lot faster to do something like this
you can modify it to fit with your app ;)

Code: Select all

Procedure CleanFile(Filename.s, FileSize.l, ChunkSize.l = 0)
  ;Note: if Chunk Size is left zero it will just write the file in one pass.
  ;in chunk cleaning remeber that the size of the file will exccede by 1 chunk.
  Handle = CreateFile(#PB_Any, Filename)
  If IsFile(Handle) = #False
    ProcedureReturn #False 
  EndIf
  If ChunkSize = 0
    ChunkLocation = AllocateMemory(FileSize)
    ZeroMemory_(ChunkLocation, FileSize)
    WriteData(Handle, ChunkLocation, FileSize)
    FreeMemory(ChunkLocation)
  Else
    NumberOfChunks = Round(ChunkSize / FileSize, 1)
    ChunkLocation = AllocateMemory(ChunkSize)
    ZeroMemory_(ChunkLocation, ChunkSize)
    For Chunk = 0 To NumberOfChunks
      If 
      WriteData(Handle, ChunkLocation, ChunkSize)
    Next
    FreeMemory(ChunkLocation)
  EndIf
  
  CloseFile(Handle)
  DeleteFile(Filename)
  ProcedureReturn #True
EndProcedure

Posted: Wed Aug 02, 2006 12:36 pm
by b1be
this may help

http://www.purebasic.fr/english/viewtop ... 551#152551

but of course, you must determine how much FREE SPACE do you have on the drive, exceeding size with 1 byte will produce ZeroFile (0 Bytes)


quick test

Code: Select all

Procedure.q GetDiskSpace(drive$,type$) 
  Value.q=-1 
  If GetDiskFreeSpaceEx_(drive$,@free.q,@total.q,0) 
    Select LCase(type$) 
      Case "t" : Value=total 
      Case "f" : Value=free 
      Case "u" : Value=total-free 
      Default : Value=-1 
    EndSelect 
  EndIf 
  ProcedureReturn Value 
EndProcedure 

Procedure CreateFilledFile(Name.s, fsize.q) 
  Protected file.l = CreateFile(#PB_Any, Name) 
  If file 
    If fsize<=0 
      CloseFile(file) 
      ProcedureReturn #True 
    Else 
      FileSeek(file, fsize-1) 
      WriteByte(file, 0) 
      CloseFile(file) 
      ProcedureReturn #True 
    EndIf 
  EndIf 
EndProcedure

CreateFilledFile("C:\FREE_SPACE",GetDiskSpace("c:","f")-1)
this should fill C:

Posted: Wed Aug 02, 2006 1:14 pm
by eJan
b1be wrote:this may help

http://www.purebasic.fr/english/viewtop ... 551#152551

but of course, you must determine how much FREE SPACE do you have on the drive, exceeding size with 1 byte will produce ZeroFile (0 Bytes)


quick test

Code: Select all

Procedure.q GetDiskSpace(drive$,type$) 
  Value.q=-1 
  If GetDiskFreeSpaceEx_(drive$,@free.q,@total.q,0) 
    Select LCase(type$) 
      Case "t" : Value=total 
      Case "f" : Value=free 
      Case "u" : Value=total-free 
      Default : Value=-1 
    EndSelect 
  EndIf 
  ProcedureReturn Value 
EndProcedure 

Procedure CreateFilledFile(Name.s, fsize.q) 
  Protected file.l = CreateFile(#PB_Any, Name) 
  If file 
    If fsize<=0 
      CloseFile(file) 
      ProcedureReturn #True 
    Else 
      FileSeek(file, fsize-1) 
      WriteByte(file, 0) 
      CloseFile(file) 
      ProcedureReturn #True 
    EndIf 
  EndIf 
EndProcedure

CreateFilledFile("C:\FREE_SPACE",GetDiskSpace("c:","f")-1)
this should fill C:
Thanks b1be, I can't believe how fast it is - 5,47 GB is filled for 47 milliseconds. Great!! :D

Posted: Wed Aug 02, 2006 8:55 pm
by Xombie
Okay. I know I've been pretty darn slow lately but that last procedure only looks like it's writing 1 byte. Tell me I haven't caught Fangles-ism and am missing something completely obvious (Hey, Fangles :) )

Posted: Wed Aug 02, 2006 9:01 pm
by dracflamloc
Well it will create the file size hes looking for but I'm not too confident it actually writes 0's on that whole 5gb

Posted: Wed Aug 02, 2006 9:37 pm
by Xombie
Ah. Yeah, I am slow. So the idea was to seek to a spot, right a zero and then assume the rest of the area before is also zero - empty space.

Not sure that will actually accomplish securely wiping a disk drive. I thought Windows had some strange ways of allocating files and handling stuffs.

eJan - You mention SDelete - you know they provide the source code, yeah? You could grab it and study it to see how they handle things. It seems they also have a nice little description of the process on the project page.

Posted: Thu Aug 03, 2006 1:35 am
by eJan
Xombie wrote:Ah. Yeah, I am slow. So the idea was to seek to a spot, right a zero and then assume the rest of the area before is also zero - empty space.

Not sure that will actually accomplish securely wiping a disk drive. I thought Windows had some strange ways of allocating files and handling stuffs.

eJan - You mention SDelete - you know they provide the source code, yeah? You could grab it and study it to see how they handle things. It seems they also have a nice little description of the process on the project page.
It is really fast, but doesn't fill the disk. I have to return to do it this way:

Code: Select all

Procedure.q GetDiskSpace(drive.s, type.s) 
  Value.q=-1 
  If GetDiskFreeSpaceEx_(drive,@free.q,@total.q,0) 
    Select LCase(type) 
      Case "t" : Value=total 
      Case "f" : Value=free 
      Case "u" : Value=total-free 
      Default : Value=-1 
    EndSelect 
  EndIf 
  ProcedureReturn Value 
EndProcedure

Procedure FillFreeSpace(drive.s,f_name.s)
  Protected file.l=CreateFile(#PB_Any,f_name)
  If file
    free=GetDiskSpace(drive,"f")
    a=0
    Repeat
      a=a+1
      WriteByte(file,0) ; Write 0 byte to 'f_name' file
    Until a=free ; free=5.9 Gb, but only 1.9 Gb is written??
    CloseFile(file)
    DeleteFile(f_name)
  EndIf
EndProcedure

FillFreeSpace("C:","FREE_SPACE")
but for some reason this code write to partition until <> 4 Gb is free then stops / or write forever. I can't find out why is that (maybe variable).

Posted: Thu Aug 03, 2006 7:35 pm
by b1be

Code: Select all

Procedure CreateFilledFile(Name.s, fsize.q) 
  Protected file.l = CreateFile(#PB_Any, Name) 
  If file 
    If fsize<=0 
      CloseFile(file) 
      ProcedureReturn #True 
    Else 
      FileSeek(file, fsize-1) 
      WriteByte(file, 0) 
      CloseFile(file) 
      ProcedureReturn #True 
    EndIf 
  EndIf 
EndProcedure 

CreateFilledFile("C:\Temp.hex",6)
OpenFile(0,"C:\Temp.hex")
FileSeek(0,2) ;replace 3rd byte with "a" 97-ASCII
WriteByte(0,97)
CloseFile(0)
then, open with a hex editor "C:\Temp.hex"
the bytes are written to hdd, you can see the 3rd byte is "a" 97-ASCII 61-HEX
i'm using XPSP2 with NTFS, Cant Test on other OS/FileSystem

dont know what are you looking for exactly tho'

P.S.:@Xombie ok, it Writes only 1 byte, but it does the job, i think it's a Windows Feature/Bug

Posted: Thu Aug 03, 2006 8:41 pm
by eJan
b1be wrote:then, open with a hex editor "C:\Temp.hex"
the bytes are written to hdd, you can see the 3rd byte is "a" 97-ASCII 61-HEX
i'm using XPSP2 with NTFS, Cant Test on other OS/FileSystem

dont know what are you looking for exactly tho'

P.S.:@Xombie ok, it Writes only 1 byte, but it does the job, i think it's a Windows Feature/Bug
Yes it does fill free disk space to 0 bytes, but I can't use it because it doesn't fill free disk space with 00's. Only working solution is:

Code: Select all

Procedure.q GetDiskSpace(drive.s, type.s) 
  Value.q=-1 
  If GetDiskFreeSpaceEx_(drive,@free.q,@total.q,0) 
    Select LCase(type) 
      Case "t" : Value=total 
      Case "f" : Value=free 
      Case "u" : Value=total-free 
      Default : Value=-1 
    EndSelect 
  EndIf 
  ProcedureReturn Value 
EndProcedure

Procedure FillFreeSpace(drive.s,f_name.s)
  Protected file.l=CreateFile(#PB_Any,f_name)
  If file
    free=GetDiskSpace(drive,"f")
    a=0
    Repeat
      a=a+1
      WriteByte(file,0) ; Write 0 byte to 'f_name' file
    Until a=free
    CloseFile(file)
    DeleteFile(f_name)
  EndIf
EndProcedure

FillFreeSpace("C:","FREE_SPACE")
Only one thing is that I don't know how to count more than 1607573504 (1.6 GB) when I have 5 GB:

Code: Select all

a=0
Repeat 
  a=a+1
Until a=5902540800 ; cannot count more than 1607573504

MessageRequester("",Str(a))
or here 1607573505:

Code: Select all

For a=0 To 5902540800 ; cannot count more than 1607573505
Next

MessageRequester("", Str(a))

Posted: Thu Aug 03, 2006 9:01 pm
by b1be
Make your counter a Quad
Purebasic Help wrote:Quad .q 8 Bytes Length -9223372036854775808 to +9223372036854775807

Code: Select all

a.q=590254079997 
Repeat 
  a=a+1 
  Debug a
Until a=590254080000 
P.S.:
eJan wrote:Yes it does fill free disk space to 0 bytes, but I can't use it because it doesn't fill free disk space with 00's
What is the Difference Between 0's and 00's ? 0 Dec = 00 Hex ?