PRB: Opening a C File when Disk Is Write-Protected

ID Number: Q42773

5.00 5.10 6.00 6.00a 6.00ax 7.00

MS-DOS

Summary:

SYMPTOMS

With the run-time library in the Microsoft C Optimizing Compiler

versions 5.0, 5.1, 6.0, 6.0a, 6.0ax, and C/C++ version 7.0, a program

can open an existing file for both read and write when the floppy

disk is write-protected. The following statement may be used to open

the file:

handle = open( "a:\\test.dat", O_RDWR | O_TRUNC );

No error condition is returned and no hard error occurs. However,

later, when the program tries to write to the file handle or even

to close the file without writing, a hard error will occur with the

following message:

Writing protect error writing drive A:

Abort, Retry, Fail?

CAUSE

This is not a problem with the open() function in the Microsoft C

run-time library. The low-level DOS function call that is used to

implement open() does not check for a write-protect error. When the

file is to be closed by close(), the internal buffer has to be

flushed to the disk. No low-level DOS function can close a file

without flushing its associated buffer.

RESOLUTION

There is no direct way to detect the write-protect condition. An

indirect workaround is to open a file with the mode to be O_CREAT,

as follows:

open ( "a:\\chk00000.xxx", O_CREAT, S_IWRITE | S_IREAD) ;

A hard error will occur, which can be captured by a user-

implemented and installed hard-error handler. This handler will

override the printing of the hard-error message on the user screen.

The open() function does return -1 when it regains the control from

the hard-error handle. If the file was opened successfully, it may

be removed at the end of the program.

More Information:

The following sample program demonstrates checking of a write-

protected disk:

Sample Code

-----------

/* Compile options needed: none

*/

#include <fcntl.h>

#include <sys\types.h>

#include <sys\stat.h>

#include <io.h>

#include <stdio.h>

#include <dos.h>

void far handler ( unsigned, unsigned, unsigned far * ) ;

#define PROTECTED 1

#define OTHER 2

int Flag = 0 ;

char * ChkName = "a:\\qwlbqwsi.ufp" ; /* dummy file name */

void main( )

{

int FileHandle;

_harderr ( handler ); /* set up hard-error handler */

FileHandle = open ( ChkName, O_CREAT, S_IWRITE | S_IREAD );

if( FileHandle == -1 ) /* check write-protection */

{

switch( Flag ) /* may be set by handler */

{

case PROTECTED :

puts( "Disk in drive A: is write-protected." );

break;

case OTHER :

puts( "A another hard-error has occurred." );

break;

default :

puts( "Error opening file (non hard-error.)" );

}

}

else

{

puts( "Disk is not write-protected." );

close( FileHandle );

remove( ChkName ); /* delete the file */

}

}

/* Hard error routine should be as short as possible */

void far handler ( unsigned deverror, unsigned errcode,

unsigned far *devhdr )

{

if( errcode == 0 )

Flag = PROTECTED;

else

Flag = OTHER; /* like drive door is open */

_hardretn( 0 );

}

Note: The argument 0 to _hardretn() is not significant in this

program. Please refer to the "Microsoft C Run-Time Library Reference"

for more specific information regarding the _hardretn() function.

Additional reference words: 5.00 5.10 6.00 6.00a 6.00ax 7.00