_INSIDE BTRIEVE FILES_ by Douglas Reilly [LISTING ONE] OPEN (Btrieve function 0) damaged file Open destination file (Could be Btrieve file, could be DOS Sequential file) if STEP_FIRST (Btrieve function 33) does not return an error DO write record to destination file save the physical position from call to GET_POSITION (Btrieve function 22) in last_saved_pos. WHILE STEP_NEXT (Btrieve function 24) does not return an error. if last Btrieve error is not an end of file error if STEP_LAST (Btrieve function 34) does not return an error DO write record to destination file save the physical position from call to GET_POSITION (Btrieve function 22) in cur_pos. WHILE STEP_PREV (Btrieve function 35) does not return an error AND cur_pos is not equal to last_saved_pos CLOSE (Btrieve function 1) source close destination file (either Btrieve or DOS sequential file). [LISTING TWO] #include "stdio.h" #include "stdio.h" /* Given a FILE pointer, return the length of the file. */ long filelen(FILE *t) { int i; long loc; long begloc; extern errno; errno=0; if ( (begloc=ftell(t))==-1L || (fseek(t,0L,SEEK_END))!=0 || (loc=ftell(t))==-1L || (fseek(t,begloc,SEEK_SET))!=0 ) { return(-1L); } return(loc); } /* Given the name of a damaged file, a good "clone" of the damaged file, rebuild the header on the damaged file. Don't use this file directly, but next do a simple recover on the file so that the rest of the information in the header is updated. This should NOT be tried on any file except one that returns a Btrieve status 2 (I/O error) or 30 (Not a Btrieve file) on OPEN. */ int do_hdr_rebld(char *damagedFile,char *goodClone,int pageSize) { int ret; char headerbuf[4096]; long damaged_size=0L; long num_pages=0L; long b1,b2,b3,b4; FILE *in; FILE *out; /* Open the good clone file, if you can */ if ( (in=fopen(goodClone,"rb"))==NULL ) { printf("\nCan't open undamaged file to read header. Exiting"); return(0); } /* read the header from the good file */ fread(headerbuf,1,pageSize,in); fclose(in); if ( (out=fopen(damagedFile,"r+b"))==NULL ) { printf("\nCan't open damaged file. Exiting."); return(0); } /* get the length of the file, in bytes. */ if ( (damaged_size=filelen(out))==-1 ) { printf("\nCan't read damaged file. Exiting."); return(0); } /* convert to pages. We could do a sanity check to ensure that the file length is evenly divisible by the page length. */ num_pages=damaged_size/(long)pageSize; /* isolate each byte. Yep, there probably is a better way (shifting bits), but this seems clearer to me, and we won't use this routine very often. */ b1=(num_pages&0xFF000000L); b1=b1/0x1000000L; b2=(num_pages&0x00FF0000L); b2=b2/0x10000L; b3=(num_pages&0x0000FF00L); b3=b3/0x100; b4=(num_pages&0x000000FFL); headerbuf[0x26]=(char)(b2); headerbuf[0x27]=(char)(b1); headerbuf[0x28]=(char)(b4); headerbuf[0x29]=(char)(b3); /* get to the start of the file... */ fseek(out,0L,SEEK_SET); /* write the header */ ret=fwrite(headerbuf,1,pageSize,out); fclose(out); return(ret); }