[comp.os.msdos.programmer] Need help with unbuffered writes

viraf@seas.gwu.edu (Viraf Bankwalla) (01/05/91)

Hi,

  I've got a question regarding file I/O in MS-DOS.

  I've noticed that although I may do a fflush (buffered I/O),
  or write, or _dos_write, the data is not always written out
  to file.

  On speaking with Miscrsoft, they informed me that the write
  may be committed by using INT 0x21, Function 0x68, on DOS 3.3
  or later.  Is there a way around this for earlier versions of
  dos, without opening and closing the file each time.

  In the below example, if USE_DOS_COMMIT is not defined,
  and I type in a string (say TEST), and power down the
  machine, the file has a size of 0 bytes.

  Thanks in advance.

  viraf bankwalla.
  viraf@seas.gwu.edu
  ...!uunet!gwusun!viraf.


/*----------------- SAMPLE CODE ------------------*/

#include <dos.h>
#include <fcntl.h>
#include <conio.h>
#include <stdio.h>
#include <string.h>

void main()
{
	char prompt[] = "Target exists. Overwrite? ", newline[] = "\n\r";
	int out_file, ch;
	unsigned ret, count;
	char str[256];
	char *out_name = "copy2.out";
	char _far *buf = str;
	union REGS inregs, outregs;

	ret = _dos_creatnew( out_name,	NORMAL, &out_file);
	if( ret == EXIST )
	{
		/* Use _dos_write to display prompts. Use bdos to call
		 * function 1 to get and echo keystroke.
		 */
		_dos_write( 1, prompt, sizeof( prompt ) - 1, &ch );
		ch = bdos( 1, 0, 0 ) & 0x00ff;
		if( (ch == 'y') || (ch == 'Y') )
			ret = _dos_creat( out_name, NORMAL, &out_file);
		_dos_write( 1, newline, sizeof( newline ) - 1, &ch );
	}
	if( ret )
		return;

	/*****
	**
	** Get one string at a time, and write
	** it out.
	**
	*****/
	for(;;)
	{
		cprintf("Enter string : "); cscanf("%s", str);

		if ((count = (int) strlen(str)) == 0)
			continue;

		if (stricmp(str, "quit") == 0)
		{
			printf("User quit\n");
			break;
		}

		if( (ret = _dos_write( out_file, buf, count, &count )) != 0)
		{
			printf(("Error writing to file"));
			return;
		}

#ifdef USE_DOS_COMMIT
		/*
		** Call the dos COMMIT interrupt
		*/
		inregs.h.ah = 0x68;		/* Dos commit function */
		inregs.x.bx = out_file;	/* Dos file handle	   */
		(void) intdos(&inregs, &outregs);

		cprintf("write status = %u\n", outregs.x.cflag);
#endif

	}

	/* Close files and free memory. */
	_dos_close( out_file );
	return;

}

/*----------------- END SAMPLE CODE ------------------*/

otto@tukki.jyu.fi (Otto J. Makela) (01/07/91)

In article <2498@sparko.gwu.edu> viraf@seas.gwu.edu (Viraf Bankwalla) writes:
     I've noticed that although I may do a fflush (buffered I/O),
     or write, or _dos_write, the data is not always written out
     to file.

     On speaking with Miscrsoft, they informed me that the write
     may be committed by using INT 0x21, Function 0x68, on DOS 3.3
     or later.  Is there a way around this for earlier versions of
     dos, without opening and closing the file each time.

Yes, the classic solution for DOS is to first DUP the file handle code,
and then CLOSE the new handle.
--
   /* * * Otto J. Makela <otto@jyu.fi> * * * * * * * * * * * * * * * * * * */
  /* Phone: +358 41 613 847, BBS: +358 41 211 562 (CCITT, Bell 24/12/300) */
 /* Mail: Kauppakatu 1 B 18, SF-40100 Jyvaskyla, Finland, EUROPE         */
/* * * Computers Rule 01001111 01001011 * * * * * * * * * * * * * * * * */

yow@magic.Berkeley.EDU (Billy Yow 283-4009) (01/08/91)

If you copy the opened file handle and then close the copied handle the file
will be flushed. And you still have an open file via the orginal handle.
This works on all versions of DOS after 2.0 (I think).  I read this is a
mag. several
months ago but have never tested it.

						Bill Yow

The yow@magic.Berkeley.EDU is not a true mail address.