Category : Files from Magazines
Archive   : MSJV7_4.ZIP
Filename : OPEN.C

 
Output of file : OPEN.C contained in archive : MSJV7_4.ZIP
/*
Copyright 1991 by David Thielen, All Rights Reserved.

This code example is from a commercial product and has restricted
rights. This code, or any code derived from this code may be
incorporated into any programs with the following restrictions;
1) It cannot be sold as source code, and 2) It cannot be sold in a
product which provides this code as an API.
*/


// If we create a R/O file & we want to write to it - we use the create
// and live with bad sharing.


#include "file_io.h"
#include "stdlib.h"
#include "string.h"

union U_TIME
{
char sTime[4];
long lTime;
};

int FileOpen (BYTE *pFile,unsigned uMode,unsigned short uAtr,
unsigned *puErr)
{
int iRtn, iTries, fRO;
unsigned uFileMode, uOpenMode, uErr;
BYTE *pName, *pErr;
union U_TIME uTime;

#ifdef DEBUG
if ((! pFile) || (! *pFile) || (! puErr) ||
(! (uMode & (O_READ | O_WRITE))) ||
(! (uMode & (O_OPEN | O_CREATE | O_TEMP))))
DebugPrintf ("OpenName (%s, %X, %X, %X)\n", pFile, uMode, uAtr, puErr);
#endif

// We do some simple parameter checking. This stops us from passing
// bad params to DOS & saves us the time of an open if we know it will
// fail.
if ((! (uMode & (O_OPEN | O_CREATE | O_TEMP))) || (! *pFile))
{
*puErr = 0x57;
return (-1);
}

// Check to see if we may be creating a R/O file that we want
// to write to
if ((uAtr & A_READ_ONLY) && (uMode & (O_CREATE | O_TEMP)) &&
(uMode & O_WRITE))
fRO = -1;
else
fRO = 0;

// First, lets set up the mode word - we still use the low byte of
// it in pre-DOS 4.
uFileMode = 0;
switch (uMode & (O_READ | O_WRITE))
{
case O_READ | O_WRITE :
uFileMode |= 0x02;
break;
case O_WRITE :
uFileMode |= 0x01;
break;

// O_READ is 0 - if neither set -> default to this
}

switch (uMode & (S_DENY_READ | S_DENY_WRITE))
{
case S_DENY_READ | S_DENY_WRITE :
uFileMode |= 0x10;
break;
case S_DENY_READ :
uFileMode |= 0x30;
break;
case S_DENY_WRITE :
uFileMode |= 0x20;
break;

// Set to DENY_NONE, not compatibility mode
default :
uFileMode |= 0x40;
break;
}

if (uMode & S_DENY_CHILD)
uFileMode |= 0x80;

// If temp - ignore OPEN & CREATE
if (uMode & O_TEMP)
{
uMode |= O_OPEN; // set O_OPEN for below

// make sure path ends with '\', point to end of path
pName = pErr = pFile + strlen (pFile);
if (*(pName-1) != '\\')
*pName++ = '\\';

#ifdef DEBUG
memset (pName, '$', 12); // make sure big enough buffer
#endif

// lets create it
if (DosMajVer >= 3)
{
*pName = 0; // In case added '\'
_asm
{
mov ax, 5A00h
mov cx, [uAtr]
mov dx, [pFile]
int 21h // Create temp file
mov [iRtn], ax
mov [uErr], 0
jnc dne1
mov [uErr], ax
dne1:
}

if ((*puErr = uErr) != 0) // Create failed
{
*pErr = 0; // Set to passed in string
return (-1); // Return the error
}

// If set to R/O, O_WRITE - use this handle
if (fRO)
return (iRtn);

// close file, drop to below to open with share
FileClose (iRtn);
}
else

// < DOS 3.0
// We need to create a temp file - we use the time to build a
// name & find-first to see if it exists. We only try 5 times
// because we are time based - using the system clock.
{
*puErr = 0x12;

for (iTries=0; iTries<5; iTries++)
{
// get a name
_asm
{
mov ah, 2Ch
int 21h // System time
mov word ptr [uTime], dx
mov word ptr [uTime+2], cx
}
uTime.sTime[0] -= (char) iTries; // Subtract try - clock frozen
ltoa (uTime.lTime, pName, 36); // Convert to 7 digit string

// does it exist?
_asm
{
mov ah, 4Eh
mov cx, 27h
mov dx, [pFile]
int 21h // Find First
mov [uErr], 0
jnc dne2
mov [uErr], ax
dne2:
}


// An error other than ! file
if ((uErr) && (uErr != 0x12))
{
*puErr = uErr;
*pErr = 0;
return (-1);
}

// If it doesn't exist - create it
if (uErr == 0x12)
{
_asm
{
mov ah, 3Ch
mov cx, [uAtr]
mov dx, [pFile]
int 21h // Create
mov [iRtn], ax
mov [uErr], 0
jnc dne3
mov [uErr], ax
dne3:
}

// Since share doesn't exist in DOS 2 - we return the CREATE
// handle - no point in doing an open for sharing.
if (! (*puErr = uErr))
return (iRtn);
}
}

// Couldn't create a temp file. Return the passed in string
*pErr = 0;
return (-1);
}
}


// OPEN/CREATE - either from temp or O_OPEN/O_CREATE

// If DOS >= 4.0 - use func 6Ch
// OS/2 is DOS version 10 - we treat that like DOS 3.3
if ((DosMajVer >= 4) && (DosMajVer != 10))
{

// We set the critical error handling to always go to int 24 for 2
// reasons. First, we want to be version independent and since we
// can't skip int 24 for all versions, we need to hit int 24 in all
// versions on critical errors. Second, ignoring int 24 is not
// handled consistently by DOS on all file handle calls and int 24
// will still be called in some erro cases even if the bit is set.
uOpenMode = 0;

// func 6C - can cause all writes to be a commit. ONLY use this if
// you TRUELY need all writes to be committed - this is EXPENSIVE.
// If even 1 write out of 10 does not need to be committed, don't
// use this bit and call FileCommit the other 9 times.
if (uMode & O_COMMIT)
uFileMode |= 0x4000;

// These bits decide what to do if the file does/doesn't exist.
if (uMode & O_OPEN)
{
if (uMode & O_TRUNC)
uOpenMode |= 0x02; // Replace if exists
else
uOpenMode |= 0x01; // Open if exists
}

if (uMode & O_CREATE)
uOpenMode |= 0x10; // Create if ! exists

// lets open it
_asm
{
mov ax, 6C00h
mov bx, [uFileMode]
mov cx, [uAtr]
mov dx, [uOpenMode]
mov si, [pFile]
int 21h // extended open
mov [iRtn], ax
mov [uErr], 0
jnc dne4
mov [uErr], ax
dne4:
}

// We got it - lets return it
if ((*puErr = uErr) != 0)
return (-1);
}
else

// OK - we don't have the DOS 4+ super-duper one size fits all open,
// we have to use (create &) open.
{
// first we try an open - if we are on an exclusive create, we need
// to know if we need to fail, otherwise, we are in business.
uErr = 0;
_asm
{
mov ah, 3Dh
mov al, byte ptr [uFileMode]
mov dx, [pFile]
int 21h // Open
mov [iRtn], ax
jnc dne5
mov [uErr], ax
dne5:
}
*puErr = uErr;

// We now use the following logic:
// 1) If O_OPEN & we were successful - we've got it
// else 2) If ! O_CREATE & we failed - we return -1
// else 3) if O_CREATE & we were successful - we return -1

// 1) If O_OPEN & we were successful - we've got it
if ((uMode & O_OPEN) && (! uErr))
goto Finish; // Opened file

// 2) If ! O_CREATE & we failed - we return -1
if ((! (uMode & O_CREATE)) && (uErr))
return (-1);

// 3) if O_CREATE & we were successful - we return -1
// Since O_CREATE must be true here - we don't test for it
if (! uErr)
{
FileClose (iRtn);
*puErr = 0x50; // File already exists
return (-1); // Return error
}

// We know the file doesn't exist AND O_CREATE is set
// So its time to create it. For 3.0+ we use the newer create
// in case we are in Windows & someone else creates it right now.
uErr = 0;
if (DosMajVer >= 3)
_asm
{
mov ah, 5Bh
mov cx, [uAtr]
mov dx, [pFile]
int 21h // Create - can't exist
mov [iRtn], ax
jnc dne6
mov [uErr], ax
dne6:
}
else
_asm
{
mov ah, 3Ch
mov cx, [uAtr]
mov dx, [pFile]
int 21h // Create - may exist
mov [iRtn], ax
jnc dne7
mov [uErr], ax
dne7:
}

// If we hit an error here - we're out of luck - return an error.
// NOTE: this includes erroring out if another app created a file
// between our open (O_TEMP or O_CREATE) above & our create - the
// odds are so low we live with this - we don't screw anything up,
// we just don't get the file.
if ((*puErr = uErr) != 0)
return (-1);

// If set to R/O, O_WRITE - use this handle
if (fRO)
return (iRtn);

// OK - we have the file - close it & re-open it with sharing
FileClose (iRtn);

_asm
{
mov ah, 3Dh
mov al, byte ptr [uFileMode]
mov dx, [pFile]
int 21h // Open
mov [iRtn], ax
jnc dne8
mov [uErr], ax
dne8:
}

// if we have an error - error out, otherwise we have it
if ((*puErr = uErr) != 0)
return (-1);
}

Finish:
// Do we have a trunc or append?
if (uMode & O_TRUNC)
FileSetSize (iRtn, 0L);

if (uMode & O_APPEND)
FileSeek (iRtn, FileGetSize (iRtn));

*puErr = 0;
return (iRtn);
}


  3 Responses to “Category : Files from Magazines
Archive   : MSJV7_4.ZIP
Filename : OPEN.C

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/