mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
250 lines
7.2 KiB
250 lines
7.2 KiB
// XCOOKIE.C - delta cookie handling routines
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
#include "messages.h"
|
|
EnableAssert
|
|
|
|
#define OPEN_MAXTRIES 5 // for DosOpen against cookie file
|
|
|
|
char *pszCookieFile = (char *)NULL; // Name of cookie lock file
|
|
|
|
int wLockMon, wLockDay, wLockHour, wLockMin; /* time of lock */
|
|
|
|
//============================================================================
|
|
//
|
|
// add_cookie_lock
|
|
//
|
|
// Add a cookie lock to cookie lock file
|
|
// The right conditions must exist (ie: many read locks, but one write lock)
|
|
//
|
|
//============================================================================
|
|
int add_cookie_lock(AD *pad, char *Lockbuf, int Locktype, F fAutotype)
|
|
{
|
|
char LFreadbuf[LINE_LEN/2];
|
|
char LFname[CMAXNAME];
|
|
char LFlock[CMAXLOCK];
|
|
char LFdate[CMAXDATE];
|
|
char tbuf[LINE_LEN/2];
|
|
char *tp = tbuf;
|
|
int hfCookieFile, TotLocks, TotReads;
|
|
int cb, cbWritten;
|
|
int err;
|
|
|
|
TotLocks = 0;
|
|
TotReads = 0;
|
|
if ((hfCookieFile = open_cookie()) == -1)
|
|
FatalError(szCookieOpen, pszCookieFile, SzForEn(_doserrno));
|
|
|
|
while ((cb = _read(hfCookieFile, LFreadbuf, (LINE_LEN/2)-1)) > 0)
|
|
{
|
|
char *cp;
|
|
char c;
|
|
|
|
LFreadbuf[cb] = '\0';
|
|
cp = LFreadbuf;
|
|
while ((c = *cp) != '\0')
|
|
{
|
|
*tp++ = *cp++;
|
|
if (c == '\n')
|
|
{
|
|
TotLocks++;
|
|
*tp = '\0';
|
|
if ((sscanf(tbuf,"%s %s %s",LFname, LFlock, LFdate) != 3)
|
|
|| ((strncmp(LFlock,"READ",4) != 0) &&
|
|
(strncmp(LFlock,"WRITE",5) != 0) &&
|
|
strncmp(LFlock,"READ-BLOCK",10) != 0))
|
|
{
|
|
_close(hfCookieFile);
|
|
FatalError(szCookieCorrupt, pszCookieFile);
|
|
}
|
|
else
|
|
{
|
|
if (Locktype == WRITE_LOCK)
|
|
{
|
|
if ((strcmp(szLockName, LFname) != 0) ||
|
|
(strncmp(LFlock,"WRITE",5) == 0) ||
|
|
fAutotype)
|
|
{
|
|
_close(hfCookieFile);
|
|
return (OP_DENY);
|
|
}
|
|
else if (strcmp(LFlock,"READ")==0)
|
|
{
|
|
TotReads++;
|
|
}
|
|
}
|
|
if ((Locktype == READ_LOCK &&
|
|
strcmp(LFlock,"READ") != 0) &&
|
|
!(strcmp(LFname,szLockName) == 0 &&
|
|
strcmp(LFlock,"READ-BLOCK") == 0))
|
|
{
|
|
_close(hfCookieFile);
|
|
return (OP_DENY);
|
|
}
|
|
if ((Locktype == RB_LOCK) && (strcmp(LFlock,"READ") != 0))
|
|
{
|
|
_close(hfCookieFile);
|
|
return (OP_DENY);
|
|
}
|
|
}
|
|
tp = tbuf;
|
|
}
|
|
}
|
|
}
|
|
|
|
// now we have reached the end, and the request is not blocked, so add it
|
|
// but first ensure that a read-to-write lock conversion will be issued
|
|
// only for 1 outstanding read. If the workstation has mutliple existing
|
|
// read locks, then return OP_DENY. This honors WKSTA concurrency
|
|
// from multiple screen groups.
|
|
|
|
if ((TotReads > 1) && (Locktype == WRITE_LOCK))
|
|
{
|
|
_close(hfCookieFile);
|
|
return (OP_DENY);
|
|
}
|
|
|
|
// if there were existing some (read) locks AND we made it here AND the
|
|
// requested lock type is WRITE, it means that existing READ locks are
|
|
// owned solely by the requester and they should be REPLACED with WRITE lock.
|
|
// All that means truncate the file before making the additional lock
|
|
|
|
if ((Locktype == WRITE_LOCK) && (TotLocks > 0))
|
|
{
|
|
if (_chsize(hfCookieFile, 0) != 0)
|
|
{
|
|
err = errno;
|
|
_close(hfCookieFile);
|
|
FatalError(szCookieTrunc, pszCookieFile, SzForEn(err));
|
|
}
|
|
}
|
|
|
|
if (_lseek(hfCookieFile, 0, 2) == -1)
|
|
{
|
|
err = errno;
|
|
_close(hfCookieFile);
|
|
FatalError(szCookieSeek, pszCookieFile, SzForEn(err));
|
|
}
|
|
|
|
cb = strlen(Lockbuf);
|
|
while (cb)
|
|
{
|
|
cbWritten = _write(hfCookieFile, Lockbuf, cb);
|
|
|
|
// write shouldn't ever return 0, but just in case...
|
|
if (-1 == cbWritten || 0 == cbWritten)
|
|
{
|
|
if (WRetryError(eoWrite, "writing", 0, pszCookieFile) != 0)
|
|
continue;
|
|
else
|
|
{
|
|
_close(hfCookieFile);
|
|
return (OP_SYSERR);
|
|
}
|
|
}
|
|
ClearPreviousError();
|
|
cb -= cbWritten;
|
|
Lockbuf += cbWritten;
|
|
}
|
|
|
|
_close(hfCookieFile);
|
|
return (OP_OK);
|
|
}
|
|
|
|
|
|
//============================================================================
|
|
//
|
|
// LockFill
|
|
//
|
|
// Given name, create an entire lock-line with KEYWORD, date, time, etc
|
|
//
|
|
//============================================================================
|
|
void LockFill(AD *pad, char *TargBuf, int Ltype)
|
|
{
|
|
time_t ltime;
|
|
struct tm *ptm;
|
|
char *szLock;
|
|
|
|
switch (Ltype)
|
|
{
|
|
default:
|
|
AssertF( fFalse );
|
|
case READ_LOCK:
|
|
szLock = "READ";
|
|
break;
|
|
case RB_LOCK:
|
|
szLock = "READ-BLOCK";
|
|
break;
|
|
case WRITE_LOCK:
|
|
szLock = "WRITE";
|
|
break;
|
|
}
|
|
|
|
time(<ime);
|
|
if ((ptm = localtime(<ime)) == NULL)
|
|
FatalError("Invalid system time\n");
|
|
|
|
sprintf(TargBuf, "%-16s%-14s %02d/%02d @ %02d:%02d ", szLockName, szLock,
|
|
ptm->tm_mon+1, ptm->tm_mday, ptm->tm_hour, ptm->tm_min);
|
|
|
|
wLockMon = ptm->tm_mon+1;
|
|
wLockDay = ptm->tm_mday;
|
|
wLockHour = ptm->tm_hour;
|
|
wLockMin = ptm->tm_min;
|
|
}
|
|
|
|
|
|
/*----------------------------------------------------------------------------
|
|
* Name: open_cookie
|
|
* Purpose: Open the cookie file from global file name: pszCookieFile
|
|
* Assumes:
|
|
* Returns: valid file handle, or -1 for error
|
|
*/
|
|
int open_cookie(void)
|
|
{
|
|
char szPhys[_MAX_PATH];
|
|
int hfCookieFile;
|
|
int i = 0;
|
|
|
|
SzPhysPath(szPhys, pszCookieFile);
|
|
|
|
while (((hfCookieFile = _sopen(szPhys, O_CREAT|O_RDWR, SH_DENYNO, S_IREAD|S_IWRITE)) == -1)
|
|
&& i < OPEN_MAXTRIES)
|
|
{
|
|
if (fVerbose)
|
|
PrErr("Waiting for access to cookie lock file %s\n", szPhys);
|
|
SleepTicks(60);
|
|
i++;
|
|
}
|
|
|
|
return (hfCookieFile);
|
|
}
|
|
|
|
|
|
//============================================================================
|
|
//
|
|
// TrimSz
|
|
//
|
|
// Remove all white space from given string
|
|
//
|
|
// warning-
|
|
// original string is NOT preserved
|
|
//
|
|
//============================================================================
|
|
void TrimSz(char *str)
|
|
{
|
|
char *left, *right;
|
|
|
|
left = str;
|
|
right = str;
|
|
|
|
while (*right != '\0')
|
|
{
|
|
if (isspace(*right))
|
|
++right;
|
|
else
|
|
*left++ = *right++;
|
|
}
|
|
*left = '\0';
|
|
}
|