>Can anyone send me a program that recovers a crashed DBF file (FPW2.6)
>As usual it's most likely the header is gone. Can you at least point me to the right place to find something like this?
>Thanks in advance, it would save a lot of time ...
I use the following. Not too elegant, but I was a little younger when I wrote this. (Now my code is worse of course :))
Note that is was originally written for DOS.
HTH,
Marc
***
*** CrashRec.Prg
***
*
* MG 07/10/94
*
*
* This program scans the dbfs in a passed directory (pDataDir).
* Each file is diagnosed. If it can be 'USE'd exclusively it passes
* the test. If it cannot be used because it is in used by someone else
* it assumed to pass the test.
*
* If on the other hand it cannot be used, then it mus be recovered.
* This is done by adjusting the number of records in the header to
* the other parameters of the file (The file length in bytes, the
* record length and the header length following the dbfs header).
*
* Recovery for a file can be prevented by pressing escape when
* prompted. The number of missing records is displayed as well as
* whether or not figures balance out. If they do not balance out,
* it is adviseable, but not required, to investigate further before
* allowing the recovery.
*
* DISCLAIMER
* ----------
*
* The program is used at the risk of the person who invokes it.
*
* LIMITATION
* ----------
*
* This program only solves one of the many corruptions that a database
* can encounter. Specifically, dbfs that where being updated during
* a server crash tend to respond favorably to this recovery program.
*
* In fact after running the program, you will
* probably be able to USE the files again, but some of your data will
* be lost.
*
* Explicitly, but not exhaustively left out of this program, are
* corrupted memofiles.
*
parameter pDatadir
private all like x*
xP=0
xR=0
xR1=0
xL=0
xF=0
if parameters()=0
pDataDir=""
endif
define window CrashRec;
from 5,5 to srows()-3,75;
title "Crash recovery"
activate window CrashRec
=adir(xFiles,(pDataDir+"*.dbf"))
? "Please note that this program could inflict major damage to "
? "your data."
?
? "You use it at your own risk."
?
xSetEsc= set("ESCAPE")="ON"
set escape off
wait "Press any key to proceed, or ESCAPE to terminate"
if lastkey()=27
if xSetEsc
set escape on
endif
clear window
release window
return
endif
if xSetEsc
set escape on
endif
? "There are "
?? alltrim(str(alen(xFiles,1)))
?? " dbfs to be checked"
?
xErrStat= 0
xErrHandl= on("Error")
xEl=0
for xEl=1 to alen(xFiles,1)
if !xDiagnose()
if !xRecover()
exit
endif
endif
wait "" timeout 1
endfor
do xCleanup
***
*** -----------------------------------
***
procedure xAdjust
wait "adjusting" window nowait
xB7= int(xR1/256^3)
xRest= xR1-xB7*256^3
xB6= int(xRest/256^2)
xRest= xRest-xB6*256^2
xB5= int(xRest/256)
xB4= xRest-xB5*256
xChr7= chr(xB7)
xChr6= chr(xB6)
xChr5= chr(xB5)
xChr4= chr(xB4)
xH= fopen(pDataDir+xFiles(xEl,1),12)
xDummy= fseek(xH,4)
xDummy= fwrite(xH,xChr4)
xDummy= fseek(xH,5)
xDummy= fwrite(xH,xChr5)
xDummy= fseek(xH,6)
xDummy= fwrite(xH,xChr6)
xDummy= fseek(xH,7)
xDummy= fwrite(xH,xChr7)
=fClose(xH)
wait clear
***
*** -----------------------------------
***
procedure xCleanup
on error &xErrHandl
release window CrashRec
***
*** -----------------------------------
***
procedure xDiagnose
? "Checking "+xFiles(xEl,1)
xErrStat=0
on error do xError
use pDataDir+xFiles(xEl,1) exclu in 0
on error &xErrHandl
do case
case xErrStat=0
use
? "Passed"
?
return
case xErrStat=1
use
? "Must be recovered"
return .f.
case xErrStat= 2
? "File is in use"
? "Assumed ok"
?
case xErrStat= 3
? "File is in use by current station "
? "Assumed ok"
?
case xErrStat= 4
? "File access denied "
? "Skipped"
?
case xErrStat= 5
? "Could not determine why file would not open"
? "Skipped"
?
endcase
***
*** -----------------------------------
***
procedure xError
on error &xErrHandl
xErr= error()
do case
case (xErr= 125) or (xErr=108)
*
* File in use ... assume it is ok
*
xErrStat=2
return
case xErr= 15
*
* "Not a DBF file ...‚
*
xErrStat= 1
case xErr= 3
*
* "File in use"
*
xErrStat= 3
case xErr= 1705
*
* "File access denied"
*
xErrStat= 4
otherwise
*
* Undefined error
? "Error: "
?? alltrim(str(xErr))
xErrStat= 5
endcase
***
*** -----------------------------------
***
procedure xRPL
xH= fopen(pDataDir+xFiles(xEl,1),12)
xR=0
xDummy= fseek(xH,4)
xBuffer= fread(xH,1)
xR= asc(xBuffer)
xDummy= fseek(xH,5)
xBuffer= fread(xH,1)
xR= asc(xBuffer)*256+xR
xDummy= fseek(xH,6)
xBuffer= fread(xH,1)
xR= asc(xBuffer)*256^2+xR
xDummy= fseek(xH,7)
xBuffer= fread(xH,1)
xR= asc(xBuffer)*256^3+xR
*
xP=0
xDummy= fseek(xH,8)
xBuffer= fread(xH,1)
xP= asc(xBuffer)
xDummy= fseek(xH,9)
xBuffer= fread(xH,1)
xP= asc(xBuffer)*256+xP
*
xL=0
xDummy= fseek(xH,10)
xBuffer= fread(xH,1)
xL= asc(xBuffer)
xDummy= fseek(xH,11)
xBuffer= fread(xH,1)
xL= asc(xBuffer)*256+xL
=fClose(xH)
***
*** -----------------------------------
***
procedure xRecover
? "File length= "
xF= xFiles(xEl,2)
?? xF
xR=0
xP=0
xL=0
do xRPL
? "Number of records= "
?? alltrim(str(xR))
? "Position of the first data record= "
?? alltrim(str(xP))
? "Length of one record= "
?? alltrim(str(xL))
?
if xL=0
? "File could not be recovered"
wait window
return
endif
xR1= (xF-1-xP) / xL
if xR1<>int(xR1)
? xR1
? "Figures do not balance out"
else
? "Figures balance out"
endif
xR1= int(xR1)
?? " - Lost records= "
?? alltrim(str(xR-xR1))
wait "Press Escape if you do not want to recover this file"
if lastkey()=27
? "This database has not been recovered"
return
endif
do xAdjust
if xDiagnose()
? "Recovered"
? "Reindexing..."
use pDataDir+xFiles(xEl,1) exclu in 0
reindex
use
else
? "Could not recover this database"
endif
?
If things have the tendency to go your way, do not worry. It won't last. Jules Renard.