[comp.sys.ibm.pc] Open files when PC goes down

lbr@holos0.UUCP (Len Reed) (03/17/89)

I am developing a system that runs on MD-DOS 3.x.  I need to be able
to save as much data as possible if the system crashes.  The program
may have written thousands of bytes to several files.  Obviously there
can be unwritten data in memory buffers, so some data loss is inevitable.

As I understand it, MS-DOS doesn't update the directory entry on an
output file until the file is closed.  So if a file is opened (I'm
using Microsoft C and ASM 5.1) with mode (O_CREAT | O_TRUNC | O_WRONLY),
the directory entry says zero bytes and the pointer to the first
cluster of the file is maintained in MS-DOS but not on the disk.  If
a crash occurs CHKDSK will put all the data into *.CHK files. 

If I open the file (O_CREAT | O_TRUNC | O_WRONLY), write one byte,
close it, then open it O_WRONLY, I have a one byte file and the directory
points to the first cluster.  Adding clusters by issuing enough writes
links everything up fine, with the only problem being that the directory
still says the file size is one byte.  After a crash, if the file had only
one cluster, CHKDSK will have no complaints but the data will be invisible.
Opening the file and LSEEKing to the "right" spot recovers the data.   If
it had more than one cluster, CHKDSK complains about the size and rounds
it up to a full cluster: 4096, 8192, etc. on my hard disk.  This means
that the data at the end of the file will be garbage.

So, is there a way to get MS-DOS to update the file size without closing
the file?  (Frequent close/open pairs are not acceptable in this
application.)  Several brute force methods suggest themselves:

	1) Actually update the file size in the directory myself.
	2) Maintain a file of file sizes.  This file would be of
	   fixed size and thus immune to the problem I describe.
	   Use this file to control recovery.
	3) Write a unique EOF marker (my files are not "text") with each
	   write call.  Before each write call lseek back over the EOF
	   marker.  After a crash, run a recovery program that finds the
	   markers and uses lseek to adjust the file size.

Is there a cleaner way?  Is there any way to tell DOS to update the
file size entry in the directory without closing the file?

If you have a good answer to this, please e-mail me.  I will summarize
if there is interest.  (This newsgroup expires quickly at my site; if
you post your answer I may miss it.)

Thanks.
-- 
    -    Len Reed

Devin_E_Ben-Hur@cup.portal.com (03/19/89)

Len Reed asks about how to assure that data written to an open file is
recoverable after a system crash before the file close.

The accepted procedure for this is to duplicate the file handle and close
the duplicate.  This will flush internal dos buffers to disk and write
the FAT and directory info associated with the file, but will leave the
original file handle open and correctly positioned.  Here's an asm
fragment to do this:

	mov	bx,file_handle
	mov	ah,045h		;duplicate handle func
	int	021h
	jc	error
	xchg	bx,ax		;move duplicate handle to bx
	mov	ah,03Eh		;close file func
	int	021h
	jc	error

Devin_Ben-Hur@Cup.Portal.Com
...ucbvax!sun!portal!cup.portal.com!devin_ben-hur

rmarks@KSP.Unisys.COM (Richard Marks) (03/21/89)

In article <1939@holos0.UUCP> lbr@holos0.UUCP (Len Reed) writes:
>I am developing a system that runs on MD-DOS 3.x.  I need to be able
>to save as much data as possible if the system crashes.
>
>As I understand it, MS-DOS doesn't update the directory entry on an
>output file until the file is closed.
>
>So, is there a way to get MS-DOS to update the file size without closing
>the file?

	On DOS 3.3 use int 21, func 68, BX=handle to secure a file.

	Also on any DOS 2.x/3.x can try int 21, func 0D which resets the
	disk.  On some BIOSes this will update all open files.

Good Luck,
Richard Marks
rmarks@KSP.unisys.COM